def foobar(input_file, file_list, option, buffer_size, count): """ Sample method showing some usage examples. """ # First of all, check if the paramters have the correct type pv.param_type_list([[input_file, "input file", str], [file_list, "file list", list], [option, "option", str], [buffer_size, "buffer size", int], [count, "count", int]]) # Ensure that 'input_file' exists pv.path(input_file, "input file", True, True) # Ensure that 'input_file' is not identical with any from 'file_list' pv.compfile(input_file, "input file", file_list) # Ensure that the file name of 'input_file' does not contain any wildcards # and also that it does not contain brackets or exlamation marks pv.string(input_file, "input file", False, ['(', ')', '!']) # Ensure 'option' is one of the options from the list pv.compstr(option, "option", ["print", "read", "write"]) # Ensure that 'buffer_size' is a postive integer between 1 and 4096 pv.intrange(buffer_size, "buffer size", 1, 4096, False) # Finally, ensure that 'count' is either zero or a positive integer pv.intvalue(count, "count", True, True, False) print("Parameter validation successful.")
def compare_files(file_input, directory, ignore_read_errors=True, obfuscate_enc=0, obfuscate_key=0): """ Compare files to find out which key fits to an encrypted file and vice versa. """ pv.path(file_input, "input", True, True) pv.path(directory, "compare", False, True) pv.intvalue(obfuscate_enc, "encrypted file obfuscation", True, True, \ False) pv.intvalue(obfuscate_key, "key file obfuscation", True, True, False) obfuscate_enc = int(obfuscate_enc) obfuscate_key = int(obfuscate_key) file_input = os.path.abspath(file_input) file_input_size = int(common.get_file_size(file_input)) directory = os.path.abspath(directory) list_files = [] for item in os.listdir(directory): path = os.path.join(directory, item) if os.path.isfile(path): if path == file_input: continue file_enc_size1 = int(common.get_file_size(path) + obfuscate_enc) file_enc_size2 = int(common.get_file_size(path) - obfuscate_enc) file_key_size1 = int(common.get_file_size(path) + obfuscate_key) file_key_size2 = int(common.get_file_size(path) - obfuscate_key) try: if file_input_size == file_enc_size1 or \ file_input_size == file_enc_size2 or \ file_input_size == file_key_size1 or \ file_input_size == file_key_size2: list_files.append(path) except Exception as e: if not ignore_read_errors: raise Exception(e) else: pass list_files.sort() return list_files
def indent(directory, file_ext, spaces=4, padding=12, left_justify=False, recursive=False, overwrite=False, verbose=False): """ Method to perform the indentation process. """ pv.path(directory, "input", False, True) pv.string(file_ext, "file extension", False, None) pv.intvalue(spaces, "spaces", True, False, False) pv.intvalue(padding, "padding", True, False, False) directory = os.path.abspath(directory) spaces = int(spaces) padding = int(padding) num = 1 if verbose: print "\nGathering files to process. Please wait.\n" list_files = common.get_files(directory, file_ext, recursive) if len(list_files) == 0: if verbose: print "No files to process.\n" return just = len(str(len(list_files))) for file_input in list_files: if verbose: print "Processing file %s of %s: '%s'" % \ (str(num).rjust(just, " "), str(len(list_files)), file_input) num += 1 if overwrite: __indent_file(file_input, spaces, padding, left_justify) else: __indent_copy(file_input, spaces, padding, left_justify) if verbose: print "\nFinished.\n"
def generate_key_string(key_bytes, dev_random=False, fortuna=False): """ Generate a binary key and convert it into a Base64 string. """ pv.intvalue(key_bytes, "key size", True, False, False) key_bytes = int(key_bytes) prng = randgen.get_prng(dev_random, fortuna) key_string = prng.get_bytes(key_bytes) # Run the appropriate code for the Python framework used if sys.version_info[0] == 2: key_string = base64.b64encode(key_string) elif sys.version_info[0] > 2: key_bytes = base64.b64encode(key_string) key_string = key_bytes.decode(sys.getdefaultencoding()) return key_string
def obfuscate_file(task_id, file_path, buffer_size=4096, bytes_random=0, dev_random=False, fortuna=False): """ Create a task file first, then add given amount of random bytes to the given file. """ pv.path(file_path, "target", True, True) pv.intvalue(buffer_size, "buffer size", True, False, False) pv.intvalue(bytes_random, "random bytes", True, False, False) buffer_size = int(buffer_size) bytes_random = int(bytes_random) file_path = os.path.abspath(file_path) file_size = common.get_file_size(file_path) + int(bytes_random) common.build_task_file(task_id, file_path, file_size, None, 0, None, 0, "file obfuscation") add_random_bytes(file_path, buffer_size, bytes_random, dev_random, fortuna)
def extract_bytes(file_input, file_output, offset=0, length=0, buffer_size=4096, overwrite=False, remove=False): """ Extract a user-defined byte range into a separate file. """ pv.path(file_input, "input", True, True) if not overwrite: pv.path(file_output, "output", True, False) pv.compfile(file_input, "input", [[file_output, "output"]]) pv.intvalue(offset, "offset", True, True, False) pv.intvalue(length, "length", True, False, False) pv.intvalue(buffer_size, "buffer size", True, False, False) file_input = os.path.abspath(file_input) file_output = os.path.abspath(file_output) offset = int(offset) length = int(length) buffer_size = int(buffer_size) file_size = get_file_size(file_input) if (offset + length) > file_size: exception("With this offset the maximal length is %s bytes." % \ str(file_size - offset)) __extract_bytes(file_input, file_output, offset, length, buffer_size, remove)
def add_random_bytes(file_path, buffer_size=4096, bytes_random=0, dev_random=False, fortuna=False): """ Add given amount of random bytes to a file. """ delay = common.get_delay() pv.path(file_path, "target", True, True) pv.intvalue(buffer_size, "buffer size", True, False, False) pv.intvalue(bytes_random, "random bytes", True, False, False) buffer_size = int(buffer_size) bytes_random = int(bytes_random) file_path = os.path.abspath(file_path) byte_blocks = int(bytes_random / buffer_size) byte_remainder = bytes_random % buffer_size data_random = bytearray(b"") always_use_urandom = \ bool(int(common.global_config(["Obfuscator"], ["always_use_urandom"], dev_random))) if always_use_urandom: dev_random = False prng = randgen.get_prng(dev_random, fortuna) fh_target = open(file_path, "ab") for block in range(byte_blocks): data_random = prng.get_bytes(buffer_size) fh_target.write(data_random) time.sleep(delay) if byte_remainder > 0: data_random = prng.get_bytes(byte_remainder) fh_target.write(data_random) time.sleep(delay) fh_target.close()
def validate_range(range_value_min=0, range_value_max=0, range_value_step=0): """ Validate byte range values. """ pv.intvalue(range_value_max, "maximum byte range", True, False, False) range_value_max = int(range_value_max) pv.intrange(range_value_min, "minimum byte range", 1, (int(range_value_max) - 1), False) pv.intvalue(range_value_step, "step byte range", True, False, True) range_value_min = int(range_value_min) range_value_step = int(range_value_step) range_length = range_value_max - range_value_min if range_length < 4: exception("The range must at least have a length of 4.") range_max_step = int(range_length / 2) pv.intrange(range_value_step, "step byte range", (range_max_step * -1), range_max_step, False) return range_value_min, range_value_max, range_value_step
def replace(directory, file_ext, mode, spaces=8, recursive=False, overwrite=False, verbose=True): """ Method to perform the replacement process. """ pv.path(directory, "input", False, True) pv.string(file_ext, "file extension", False, None) mode = mode.lower() pv.compstr(mode, "mode", ["spaces", "tabs"]) pv.intvalue(spaces, "spaces", True, False, False) directory = os.path.abspath(directory) spaces = int(spaces) num = 1 if verbose: print "\nGathering files to process. Please wait.\n" list_files = common.get_files(directory, file_ext, recursive) just = len(str(len(list_files))) for file_input in list_files: if verbose: print "Processing file %s of %s: '%s'" % \ (str(num).rjust(just, " "), str(len(list_files)), file_input) num += 1 if overwrite: __replace_file(file_input, mode, spaces) else: __replace_copy(file_input, mode, spaces) if verbose: print "\nFinished.\n"
def get_bytes(self, amount): """ Get a certain amount of pseudo-random bytes. """ pv.intvalue(amount, "random bytes", True, False, False) amount = int(amount) if self.__fortuna_reseed_count == 0 or \ self.__fortuna_reseed_count >= self.__fortuna_reseed_period: try: self.__fortuna.reseed( self.__randgen.get_bytes(self.__fortuna_seed_bytes)) except TypeError: common.exception("Version mismatch?") if self.__fortuna_reseed_count >= self.__fortuna_reseed_period: self.__fortuna_reseed_period = 1 else: self.__fortuna_reseed_period += 1 bytes_random = \ bytearray(b"" + self.__fortuna.pseudo_random_data(amount)) return bytes_random
def generate_key_file(task_id, file_path, file_size, buffer_size=4096, bytes_random=0, use_existing_key=False, dev_random=False, fortuna=False, overwrite=False, parts=1): """ Create a task file first, then build the key file. """ if use_existing_key: pv.path(file_path, "key", True, True) else: if not overwrite: pv.path(file_path, "key", True, False) pv.intvalue(file_size, "key file size", True, False, False) pv.intvalue(buffer_size, "buffer size", True, False, False) pv.intvalue(bytes_random, "random bytes", True, True, False) pv.intvalue(parts, "key file parts", True, False, False) file_path = os.path.abspath(file_path) file_size = int(file_size) buffer_size = int(buffer_size) bytes_random = int(bytes_random) if parts == 1: generation_type = "key generation" else: generation_type = "multi-part key generation" file_size = file_size + bytes_random common.build_task_file(task_id, file_path, file_size, None, 0, None, 0, generation_type) build_file_key(file_path, file_size, buffer_size, bytes_random, False, dev_random, fortuna, overwrite, parts)
def progress_bar(width=0, value=0, description="", padding=0, block_char="=", status_char="", percent=False): """ Draw a character based progress bar. """ pv.intvalue(width, "width", True, False, False) pv.intvalue(value, "percent", True, True, False) pv.intvalue(padding, "padding", True, True, False) if len(description) > 0: description = description.ljust(padding, " ") if len(block_char) == 0: block_char = "=" if len(status_char) > 0: status_char = status_char[0].rjust(2, " ") padding += 2 if percent: pstatus = "(%s %%)".rjust(8, " ") % str(value).rjust(3, " ") padding += 8 else: pstatus = "" blocks_max = width - (padding + 2) blocks = int((blocks_max * value) / 100) if blocks > blocks_max: blocks = blocks_max blocks_empty = blocks_max - blocks progress_bar = "%s[%s%s]%s%s" % \ (description, (block_char * blocks), (" " * blocks_empty), pstatus, status_char) return progress_bar
def get_status(task_id, delay=0): """ Get the status of the Erfr process with the given task ID. """ task_file = common.get_task_file(task_id) pv.intrange(task_id, "task ID", 1, common.get_max_tasks(), False) pv.intvalue(delay, "delay", True, True, False) delay = int(delay) task_id = int(task_id) progress_key = True process_type = "" process_type_list = ["encryption", "decryption", "key generation"] file_input_path = "" file_input_size = 0 file_key_path = "" file_key_size = 0 file_output_path = "" file_output_size = 0 valid_type = False if not common.file_exists(task_file): common.exception("No process is running with the given task ID.") dict_contents = __read_content(task_file) process_type = dict_contents["process_type"] if process_type == "": common.exception("The process type cannot be empty.") for item in process_type_list: if process_type == item: valid_type = True if not valid_type: common.exception("The process type '%s' is not supported." \ % process_type) file_input_path = dict_contents["file_input_path"] file_input_size = dict_contents["file_input_size"] if "crypt" in process_type: file_key_path = dict_contents["file_key_path"] file_key_size = dict_contents["file_key_size"] file_output_path = dict_contents["file_output_path"] file_output_size = dict_contents["file_output_size"] if process_type == "decryption": progress_key = False print print "Monitoring Erfr %s process with task ID %s." % \ (process_type, task_id) if delay > 0: if delay == 1: print "Refreshing the process status every second." else: print "Refreshing the process status every %s seconds." % \ str(delay) print print "-" * 78 if file_key_path == "" and file_output_path == "": __monitor_file(task_file, file_input_path, file_input_size, "File name", delay, True) else: __monitor_file(task_file, file_input_path, file_input_size, "Input file", delay, False) print __monitor_file(task_file, file_key_path, file_key_size, "Key file", delay, progress_key) print __monitor_file(task_file, file_output_path, file_output_size, "Output file", delay, True) print "-" * 78 print if delay > 0: print "Process finished."
def rename_files(directory, rename_mode, separator=" ", recursive=False, padding=0, exclude=None, pattern=None, ignore_case=True, regex_syntax=False, report_file=None, ignore_symlinks=False, ignore_file_ext=False, custom_name=None, step=1, order_by=None): """ Rename the base name of files based on the name of the directory where they are stored in and add a numeric ID. """ pv.path(directory, "given", False, True) pv.compstr(rename_mode, "rename mode", ["fill-gaps", "increase", "keep-order", "rename-new"]) pv.intrange(padding, "padding", 0, 12, True) pv.string(separator, "seperator", False, common.get_invalid_chars()) pv.intvalue(step, "step", True, False, False) if not order_by == None: pv.compstr(order_by, "order by", ["accessed", "created", "modified"]) if not rename_mode == "keep-order": raise Exception("The order-by argument can only be used in " \ "combination with keep-order mode.") step = int(step) rename_mode = rename_mode.lower() directory = os.path.abspath(directory) if not directory.endswith(os.path.sep): directory += os.path.sep if report_file == None: simulate = False else: pv.path(report_file, "report", True, False) report_file = os.path.abspath(report_file) simulate = True if not custom_name == None: pv.string(custom_name, "custom file name", False, common.get_invalid_chars()) time_start = dt.now() list_content = [] list_excluded = [] list_renamed = [] list_skipped = [] regex = None if not pattern == None: regex = common.compile_regex(pattern, ignore_case, regex_syntax) list_content, list_excluded = \ common.get_files(directory, recursive, ignore_case, regex, exclude, ignore_symlinks, order_by) for item in list_content: list_files = item[1] if rename_mode == "fill-gaps": list_renamed, list_skipped = \ __rename_files_fill(list_files, list_renamed, list_skipped, separator, padding, True, ignore_file_ext, custom_name, step) elif rename_mode == "rename-new": list_renamed, list_skipped = \ __rename_files_fill(list_files, list_renamed, list_skipped, separator, padding, False, ignore_file_ext, custom_name, step) elif rename_mode == "keep-order": list_renamed, list_skipped = \ __rename_files_keep_order(list_files, list_renamed, list_skipped, separator, padding, ignore_file_ext, custom_name, step, order_by) else: raise Exception("An invalid rename mode was given.") if simulate: if padding == 0: padding = "Set automatically" else: padding = str(padding) explicit = None if exclude == None: exclude = False explicit = False elif exclude: explicit = False else: explicit = True if order_by == "accessed": order_by = "Access time" elif order_by == "created": order_by = "Creation time" elif order_by == "modified": order_by = "Modification time" else: order_by = "False" list_header = [] list_header.append("Nomen File Renamer simulation report") list_header.append(["Report file name:", report_file]) list_header.append(["Directory:", directory]) list_header.append(["Recursive:", recursive]) list_header.append(["Ignore symlinks:", ignore_symlinks]) list_header.append(["Rename mode:", rename_mode.capitalize()]) list_header.append(["Order by time:", order_by]) list_header.append(["Separator:", "\"" + separator + "\" " \ "(without double quotes)"]) list_header.append(["Numeric padding:", padding]) list_header.append(["Step size:", step]) list_header.append(["Exclude files:", exclude]) list_header.append(["Explicit files:", explicit]) list_header.append(["Pattern:", pattern]) list_header.append(["Ignore case:", ignore_case]) list_header.append(["Regex syntax:", regex_syntax]) common.report(report_file, list_header, list_renamed, list_excluded, list_skipped, time_start) else: common.rename(list_renamed)
def __prepare_process(self, task_id, file_input, file_key, file_output, buffer_size, existing_key, overwrite, obfuscate_enc, obfuscate_key, fortuna, dev_random, rotate_min, rotate_max, rotate_step, rotate_mod, reverse_bytes, sbox, skip_checks): """ Prepare the requested process by checking the given parameters and execute the appropriate method. """ if not skip_checks: pv.path(file_input, "input", True, True) if not overwrite: if self.__encrypt: pv.path(file_key, "key", True, existing_key) pv.path(file_output, "output", True, False) pv.compfile(file_input, "input", [[file_key, "key"], [file_output, "output"]]) pv.intvalue(buffer_size, "buffer size", True, False, False) pv.intvalue(obfuscate_enc, "encrypted file obfuscation byte", True, True, False) pv.intvalue(obfuscate_key, "key file obfuscation byte", True, True, False) if rotate_min == None and rotate_max == None and rotate_step == None: self.__rotate = False else: pv.intvalue(rotate_min, "minimum rotation", True, True, False) pv.intvalue(rotate_max, "maximum rotation", True, True, False) pv.intvalue(rotate_min, "rotation step", True, False, True) range_value_min, range_value_max, range_value_step = \ common.validate_range(rotate_min, rotate_max, rotate_step) self.__rotate = True if reverse_bytes == None: self.__reverse = False else: pv.intrange(reverse_bytes, "reverse byte", 2, None, False) self.__reverse = True self.__task_id = task_id self.__fortuna = fortuna self.__dev_random = dev_random self.__file_input = os.path.abspath(file_input) self.__file_key = os.path.abspath(file_key) self.__file_output = os.path.abspath(file_output) self.__buffer_size = int(buffer_size) self.__existing_key = existing_key self.__overwrite = overwrite self.__obfuscate_enc = int(obfuscate_enc) self.__obfuscate_key = int(obfuscate_key) self.__sbox = sbox if self.__rotate: self.__rotate_min = int(rotate_min) self.__rotate_max = int(rotate_max) self.__rotate_step = int(rotate_step) self.__rotate_mod = rotate_mod self.__rotate_obj = rt.Rotate(self.__rotate_min, self.__rotate_max, self.__rotate_step, self.__rotate_mod) if self.__reverse: self.__reverse_bytes = int(reverse_bytes)
def build_task_file(task_id, file_input_path, file_input_size, file_key_path, file_key_size, file_output_path, file_output_size, process_type): """ Build a temporary task file using the Erfr task ID containing the relevant information of the corresponding encryption or decryption ("crypt_process"), key generation or obfuscation process. """ if task_id == None: return pv.intrange(task_id, "task ID", 1, get_max_tasks(), False) pv.intvalue(file_input_size, "input file size", True, False, False) if file_input_path == None: exception("The input file path is missing.") if "crypt" in process_type: pv.intvalue(file_key_size, "key file size", True, True, False) if file_key_path == None: exception("The key file path is missing.") pv.intvalue(file_output_size, "output file size", True, True, False) if file_output_path == None: exception("The output file path is missing.") task = __validate_files(file_input_path, file_key_path, file_output_path) if not task == 0: exception("At least one of the given files already is in use by " \ "another Erfr process with ID %s." % task) task_file = get_task_file(task_id) if file_exists(task_file): exception("The task file for the given ID already exists.") string = __build_content_string(file_input_path, file_input_size, file_key_path, file_key_size, file_output_path, file_output_size, process_type) encode_file = bool(int(global_config(["TaskID"], ["encode_base64"], 1))) # Check if the file shall be encoded and then run the appropriate code for # the Python framework used if encode_file: if sys.version_info[0] == 2: content = base64.encodestring(string) elif sys.version_info[0] > 2: temp = string.encode(sys.getdefaultencoding()) content = base64.encodestring(temp) else: if sys.version_info[0] == 2: content = string elif sys.version_info[0] > 2: content = bytes(string, sys.getdefaultencoding()) try: fh_task = open(task_file, "wb") fh_task.write(content) fh_task.close() except: print "Failed to create task file. Due to this, the monitor " + \ "component will not work on this process."
def build_file_key(file_path, file_size, buffer_size=4096, bytes_random=0, use_existing_key=False, dev_random=False, fortuna=False, overwrite=False, parts=1): """ Build a key file which contains the random values which are required to encrypt the input file. """ delay = common.get_delay() if use_existing_key: pv.path(file_path, "key", True, True) else: if not overwrite: pv.path(file_path, "key", True, False) pv.path(file_path + ".001", "key part", True, False) file_path = os.path.abspath(file_path) pv.intvalue(file_size, "key file size", True, False, False) pv.intvalue(buffer_size, "buffer size", True, False, False) pv.intvalue(bytes_random, "random bytes", True, True, False) pv.intvalue(parts, "key file parts", True, False, False) file_size = int(file_size) buffer_size = int(buffer_size) bytes_random = int(bytes_random) parts = int(parts) if parts > (file_size + bytes_random): common.exception("The file is too small for given number of key " \ "parts.") elif parts > 999: common.exception("The number of key parts must be less than 1000.") if not use_existing_key: key_path = file_path part_id = 0 part_temp = int(file_size + bytes_random) part_size = part_temp / parts part_last = part_temp - (part_size * (parts - 1)) for part in range(parts): if parts > 1: part_id += 1 key_path = file_path + "." + str(part_id).rjust(3, "0") if part_id < parts: file_size = part_size else: file_size = part_last data_key = bytearray(b"") fh_key = open(key_path, "wb") byte_blocks = int(file_size / buffer_size) byte_remainder = file_size % buffer_size prng = randgen.get_prng(dev_random, fortuna) for block in range(byte_blocks): data_key = prng.get_bytes(buffer_size) fh_key.write(data_key) time.sleep(delay) if byte_remainder > 0: data_key = prng.get_bytes(byte_remainder) fh_key.write(data_key) time.sleep(delay) fh_key.close() if parts == 1: if bytes_random > 0: obfuscator.add_random_bytes(file_path, buffer_size, bytes_random, dev_random)