#!/usr/bin/env python3 import click from random import randint from random import random #################################################### ##### Example Execution # $ pip3 install click # $ chmod +x ./obfuscate.py # $ ./obfuscate.py "Hello World" --manglecase --dirac-max=5 # Input "Hello World" # # Output "ĥ̻͈̏̔ē͋͆͞ŀ͓̦̈́Ľ͎̖̃̉̈Ŏ̷͕̽͢ ̑͢Ẁ̻̈́ŏ̀̌͌͐ŕ̳ͥ͛̉͝ĺ̟̇ͦĐ̥̄ͭ̀͡" # # $ #################################################### @click.command() @click.option('--no-manglecase/--manglecase', default=True) @click.option('--dirac-min', default=2, type=click.IntRange(0,100)) @click.option('--dirac-max', default=14, type=click.IntRange(0,100)) @click.option('--unmangle-probability', default=0.1, type=click.FloatRange(0,1)) @click.argument('clean_string') def mangle(clean_string, no_manglecase, dirac_min, dirac_max, unmangle_probability): print(f'Input "{clean_string}"\n') respect_case = no_manglecase mangled_string = '' for clean_letter in clean_string: new_letter = mangle_letter(clean_letter, unmangle_probability=unmangle_probability, respect_case=respect_case) if dirac_max < 0: dirac_max = 0 if dirac_min < 0: dirac_min = 0 if dirac_min > dirac_max: dirac_min = dirac_max new_letter += get_diracs(randint(dirac_min,dirac_max)) mangled_string += new_letter print(f'Output "{mangled_string}"\n') def mangle_letter(letter_raw, unmangle_probability: float = 0.10, respect_case: bool = True) -> str: scope = (-1, -1) letter = letter_raw.lower() if letter == 'a': scope = (0x00, 0x05) elif letter == 'c': scope = (0x06, 0x0D) elif letter == 'd': scope = (0x0E, 0x11) elif letter == 'e': scope = (0x12, 0x1B) elif letter == 'g': scope = (0x1C, 0x23) elif letter == 'h': scope = (0x24, 0x27) elif letter == 'i': scope = (0x28, 0x31) elif letter == 'j': scope = (0x34, 0x35) elif letter == 'k': scope = (0x36, 0x37) elif letter == 'l': scope = (0x39, 0x42) elif letter == 'n': scope = (0x43, 0x4B) elif letter == 'o': scope = (0x4C, 0x51) elif letter == 'r': scope = (0x54, 0x59) elif letter == 's': scope = (0x5A, 0x61) elif letter == 't': scope = (0x62, 0x67) elif letter == 'u': scope = (0x68, 0x73) elif letter == 'w': scope = (0x74, 0x75) elif letter == 'y': scope = (0x76, 0x77) elif letter == 'z': scope = (0x79, 0x7E) if scope[0] < 0 or random() < unmangle_probability: return letter_raw new_int = randint(*scope) if respect_case: tmp_int = new_int - scope[0] if letter_raw.isupper(): tmp_int &= 0xFFFE else: # i.e. islower() tmp_int |= 0x0001 new_int = tmp_int + scope[0] else: pass # Now put it into the extended latin range new_chr = chr(0x0100 | new_int) return new_chr # Pull a random list of diarac from the dirac table. # https://en.wikipedia.org/wiki/Combining_character def get_diracs(count) -> str: diracs_list = [] for _ in range(count): tmp_int = 0x4F while tmp_int == 0x4F: tmp_int = randint(0,0x6F) diracs_list.append(chr(0x0300 | tmp_int)) return ''.join(diracs_list) if __name__ == "__main__": mangle()