def encrypt_file(self, plaintext_file_name, ciphertext_file_name): pt_file = open(plaintext_file_name, "rb") ct_file = open(ciphertext_file_name, 'wb+') file_size = os.stat(plaintext_file_name).st_size bar = ChargingBar('[*] Encrypting ', max=(file_size // self.chunk_size) - 1) last_block_size = file_size % self.chunk_size ct_file.write(last_block_size.to_bytes(10, byteorder='little')) for chunk in self.encryption_chunk_reader(pt_file, self.chunk_size): cts = [] for p in self.primes: small_p = (chunk % p) small_cipher = (self.alpha * small_p + self.beta) % p cts.append(small_cipher) for i, ct in enumerate(cts): x = ct.to_bytes(PRIME_SIZE, byteorder='little') ct_file.write(x) bar.next() bar.finish() l("Encryption done") l("Saved at %s" % os.path.abspath(ct_file.name))
def decrypt_file(self, ciphertext_file_name, plaintext_file_name): ct_file = open(ciphertext_file_name, "rb") pt_file = open(plaintext_file_name, 'wb+') file_size = os.stat(ciphertext_file_name).st_size count_of_primes = len(self.primes) bar = ChargingBar('[*] Decrypting ', max=(file_size // self.chunk_size) - 1) # Read cipher text chunk cts = [] for i, (chunk, chunk_size) in enumerate( self.decryption_chunk_reader(ct_file, PRIME_SIZE, self.chunk_size)): chunk = ((chunk - self.beta) * modinv(self.alpha, self.primes[i % count_of_primes]) ) % self.primes[i % count_of_primes] cts.append(chunk) if len(cts) < count_of_primes: continue bar.next() ct = solve_crt(cts, self.primes) pt_file.write(ct.to_bytes(chunk_size, byteorder='little')) cts = [] bar.finish() l("Decryption done") l("Saved at %s" % os.path.abspath(pt_file.name))
def __init__(self, base_num, seed, block_size_bytes): self.base_num = base_num self.seed = seed self.block_size_bytes = block_size_bytes # Generate lookUpTable keys = np.arange(base_num) values = deepcopy(keys) if seed: random.seed(seed) random.shuffle(values) self.look_up_table_encryption = {str(key): str(value) for (key, value) in zip(keys, values)} self.look_up_table_decryption = {str(key): str(value) for (key, value) in zip(values, keys)} l(self.look_up_table_encryption) # Generate lookUpTable # self.look_up_table_encryption = DenCoder.generate_table(seed,base_num,'enc') # self.look_up_table_decryption = DenCoder.generate_table(seed,base_num,'dec') biggest_number_in_block_base_10_len = len(str(int2base(2 ** (block_size_bytes * 8), base_num))) # Calculate block padding self.max_block_size_after_encrypt_bits = len( binaryStr(int(str(base_num - 1) * biggest_number_in_block_base_10_len, base_num))) self.max_block_size_after_encrypt_bytes = int(ceil(self.max_block_size_after_encrypt_bits / 8)) self.max_block_size_after_encrypt_bits = self.max_block_size_after_encrypt_bytes * 8 self.padding_block_size_bytes = self.calculate_padding_length(self.max_block_size_after_encrypt_bits)
def decrypt_file(self, ciphertext_file_name, plaintext_file_name): # filename, chunk_size, padding_size, base_destination): ct_chunk_reader = self.decryption_chunk_reader(ciphertext_file_name, self.padding_block_size_bytes, self.base_num) # ct_chunk_reader = self.decryption_chunk_reader(ciphertext_file_name) #, self.padding_block_size_bytes, self.base_num, self.max_block_size_after_encrypt_bytes, self.block_size_bytes ) pt_file = open(plaintext_file_name, 'wb+') file_size = os.stat(ciphertext_file_name).st_size bar = ChargingBar('[*] Decrypting ', max=(file_size // (self.max_block_size_after_encrypt_bytes * 1000)) + 1) for index, (pt_chunk, block_size) in enumerate(ct_chunk_reader): if index % 1000 == 0: bar.next() nums_after_lookup_table = '' for num in pt_chunk: nums_after_lookup_table = nums_after_lookup_table + self.look_up_table_decryption.get(num) nums_after_lookup_table = int(nums_after_lookup_table, self.base_num) # if len(bin(nums_after_lookup_table)[2:])/8 > block_size: # someshit=1 ct_bytes = nums_after_lookup_table.to_bytes(block_size, byteorder='little') # ct_bytes = nums_after_lookup_table.to_bytes(self.block_size_bytes, byteorder='little') pt_file.write(ct_bytes) # except Exception as e: # print(e) # pass bar.next(bar.max - bar.index) bar.finish() l("Decryption done") l("Saved at %s" % os.path.abspath(pt_file.name))
def encrypt_file(self, plaintext_file_name, ciphertext_file_name): pt_file = self.encryption_chunk_reader(plaintext_file_name, self.block_size_bytes) ct_file = open(ciphertext_file_name, 'wb+') file_size = os.stat(plaintext_file_name).st_size bar = ChargingBar('[*] Encrypting ', max=(file_size // (self.block_size_bytes * 100)) + 1) for index, pt_chunk in enumerate(pt_file): if index % 100 == 0: bar.next() plain_num_base_10 = int.from_bytes(pt_chunk, byteorder='little') # print(self.block_size_bytes) nums_after_lookup_table = '' # temp = '' for num in int2base(plain_num_base_10, self.base_num): # temp += num nums_after_lookup_table = nums_after_lookup_table + self.look_up_table_encryption.get(num) # print('PT: %s' % temp) # print('CT: %s' % nums_after_lookup_table ) leading_zero_bytes = re.search('(?!0)', nums_after_lookup_table).start() nums_after_lookup_table = int(nums_after_lookup_table, self.base_num) padding_bits = self.max_block_size_after_encrypt_bits - len( bin(nums_after_lookup_table)[2:]) - leading_zero_bytes padding_bytes = padding_bits.to_bytes(self.padding_block_size_bytes, byteorder='little') # print('------') ct_bytes = nums_after_lookup_table.to_bytes(self.max_block_size_after_encrypt_bytes, byteorder='little') ct_file.write(padding_bytes) ct_file.write(ct_bytes) bar.finish() l("Encryption done") l("Saved at %s" % os.path.abspath(ct_file.name))
def extract_key(ciphertext_file, plaintext_file, primes, key_file): count_of_primes = len(primes) l("Starting key extraction") found_key = False calpha = cbeta = None for alpha in range(1, 100): if found_key: break for beta in range(0, 100): if found_key: break l("Checking Alpha= %s \tBeta= %s" % (alpha, beta)) try: pt_file = open(plaintext_file, 'rb') ct_file = open(ciphertext_file, 'rb') fakecoder = DenCoder(0, 0, primes) encrypt_reader_generator = fakecoder.encryption_chunk_reader( pt_file, fakecoder.chunk_size) decrypt_reader_generator = fakecoder.decryption_chunk_reader( ct_file, PRIME_SIZE, fakecoder.chunk_size) enc_chunk = next(encrypt_reader_generator) enc_cts = [] for p in primes: small_p = (enc_chunk % p) small_cipher = (alpha * small_p + beta) % p enc_cts.append(small_cipher) dec_cts = [] for i, (dec_chunk, chunk_size) in enumerate(decrypt_reader_generator): chunk = ((dec_chunk - beta) * modinv(alpha, primes[i % count_of_primes]) ) % primes[i % count_of_primes] dec_cts.append(chunk) if len(dec_cts) < count_of_primes: continue ct = solve_crt(dec_cts, primes) dec_cts = [] break if ct == enc_chunk: l("Found key: valid Alpha=%s \tBeta=%s " % (alpha, beta)) calpha = alpha cbeta = beta found_key = True break else: continue except Exception as e: continue if not found_key: l("Sorry i wasn't able to find your key :(") else: DenCoder.save_key(key_file, calpha, cbeta, primes) l("Key file generated at %s" % (os.path.realpath(key_file.name)))
def decrypt_file(self, ciphertext_file_name, plaintext_file_name): ct_file = open(ciphertext_file_name, "rb") pt_file = open(plaintext_file_name, 'wb+') file_size = os.stat(ciphertext_file_name).st_size bar = ChargingBar('[*] Decrypting ', max=(file_size // self.chunk_size_ct) - 1) p, q = self.p, self.q pq = self.pq n = self.mode for i, (chunk, chunk_size) in enumerate( self.decryption_chunk_reader(ct_file, self.chunk_size_ct)): m_p = powmod(chunk, ((p + 1) // 4), p) m_q = powmod(chunk, ((q + 1) // 4), q) _, r, s = egcd(p, q) assert (r * p + s * q == 1) rpm_q = r * p * m_q sqm_p = s * q * m_p m1 = (rpm_q + sqm_p) % pq bar.next() if self.is_valid_m(chunk, m1, n): pt_file.write(m1.to_bytes(chunk_size, byteorder='little')) continue m2 = (rpm_q - sqm_p) % pq if self.is_valid_m(chunk, m2, n): pt_file.write(m2.to_bytes(chunk_size, byteorder='little')) continue m3 = -m2 % pq if self.is_valid_m(chunk, m3, n): pt_file.write(m3.to_bytes(chunk_size, byteorder='little')) continue m4 = -m1 % pq if self.is_valid_m(chunk, m4, n): pt_file.write(m4.to_bytes(chunk_size, byteorder='little')) continue assert False bar.finish() l("Decryption done") l("Saved at %s" % os.path.abspath(pt_file.name))
def encrypt_file(self, plaintext_file_name, ciphertext_file_name): pt_file = open(plaintext_file_name, "rb") ct_file = open(ciphertext_file_name, 'wb+') file_size = os.stat(plaintext_file_name).st_size bar = ChargingBar('[*] Encrypting ', max=(file_size // self.chunk_size_pt) - 1) last_block_size = file_size % (self.chunk_size_pt) ct_file.write(last_block_size.to_bytes(10, byteorder='little')) for chunk in self.encryption_chunk_reader(pt_file, self.chunk_size_pt): cipher = powmod(chunk, 2, self.mode) ct_file.write( cipher.to_bytes(self.chunk_size_ct, byteorder='little')) bar.next() bar.finish() l("Encryption done") l("Saved at %s" % os.path.abspath(ct_file.name))
def decrypt_file(self, ciphertext_file_name, plaintext_file_name): pt_file = open(ciphertext_file_name, "rb") ct_file = open(plaintext_file_name, 'wb+') pt_bytes = pt_file.read() pt_data = int.from_bytes(pt_bytes, 'big') file_size = os.stat(ciphertext_file_name).st_size bar = ChargingBar('[*] Decrypting ', max=((file_size * 8 // self.chunk_size))) random_generator = self.next_random_number() random_num = next(random_generator) pt_data = pt_data ^ random_num for _ in range((file_size * 8 // self.chunk_size) - 1): random_num = next(random_generator) pt_data ^= (random_num << (_ + 1) * self.chunk_size) bar.next() bar.next() pt_data = pt_data.to_bytes(file_size, byteorder='big') ct_file.write(pt_data) bar.finish() l("Decryption done") l("Saved at %s" % os.path.abspath(ct_file.name))
def generate_key(key_file, alpha, beta, primes, primes_count, primes_count_min_range, primes_count_max_range): l("Generating key file ...") if alpha >= MIN_32_BITS: raise click.UsageError("Alpha is in range of 32bit numbers!") primes_list = [] # Unless user specifies primes, We'll have to pick random numbers in range 32bits if primes: primes_list = [int(p) for p in primes.split(',')] for p in primes_list: if not is_prime(p): raise click.UsageError("Dude %d is not a prime number :|" % p) else: primes_count = primes_count if primes_count else random.randrange( primes_count_min_range, primes_count_max_range) l("Generating %d primes in range of 32bits, Please wait..." % primes_count) primes_list = [] while len(primes_list) < primes_count: rand_32_int = random.randrange( MIN_32_BITS, MAX_32_BITS) | 1 # Only use odd numbers if rand_32_int not in primes_list and is_prime(rand_32_int): primes_list.append(rand_32_int) print("Chosed primes: " + str(primes_list)) DenCoder.save_key(key_file, alpha, beta, primes_list) l("Key file generated at %s" % (os.path.realpath(key_file.name)))
def generate_key(key_file, count_of_bits): l("Generating p,q primes in range of 32bits, Please wait...") MIN_RANGE_NUMBER = 1 << count_of_bits MAX_RANGE_NUMBER = (1 << (count_of_bits + 1)) - 1 primes_list = [] while len(primes_list) < 2: rand_32_int = random.randrange( MIN_RANGE_NUMBER, MAX_RANGE_NUMBER ) | 3 # We only want numbers % 4 == 3, So we'll modify their lower bits to 3 if rand_32_int not in primes_list and is_prime(rand_32_int): primes_list.append(rand_32_int) l("Chosen primes: " + str(primes_list)) p, q = sorted(primes_list) DenCoder.save_key(key_file, p, q) l("Key file generated at %s" % (os.path.realpath(key_file.name)))
def extract_key(ciphertext_file, plaintext_file, mode_from, mode_to, key_file): PT_DATA = int.from_bytes(open(plaintext_file, 'rb').read(), 'big') CT_DATA = int.from_bytes(open(ciphertext_file, 'rb').read(), 'big') l("Starting key extraction") alpha = beta = seed = mode = 0 found_key = False for mode in range(mode_from, mode_to + 1): chunk_size = calculate_max_bits_for_number(mode) P1_HILL = PT_DATA & (2**chunk_size - 1) C1 = CT_DATA & (2**chunk_size - 1) P2_HILL = (PT_DATA >> chunk_size) & (2 ** chunk_size - 1) C2 = (CT_DATA >> chunk_size) & (2 ** chunk_size- 1) P3_HILL = (PT_DATA >> (2 * chunk_size)) & (2 ** chunk_size - 1) C3 = (CT_DATA >> (2 * chunk_size)) & (2 ** chunk_size - 1) P4_HILL = (PT_DATA >> (3 * chunk_size)) & (2 ** chunk_size - 1) C4 = (CT_DATA >> (3 * chunk_size)) & (2 ** chunk_size - 1) P5_HILL = (PT_DATA >> (4 * chunk_size)) & (2 ** chunk_size - 1) C5 = (CT_DATA >> (4 * chunk_size)) & (2 ** chunk_size - 1) l("Checking mode %s" % mode) try: X1 = P1_HILL ^ C1 X2 = P2_HILL ^ C2 X3 = P3_HILL ^ C3 X4 = P4_HILL ^ C4 X5 = P5_HILL ^ C5 gcd, __, ___ = egcd((X3 - X4)%mode, mode) gcd_flag = False if gcd != 1: alpha = ((((X4 - X5)%mode)//gcd) * modinv(((X3 - X4)%mode) // gcd, mode // gcd)) % (mode // gcd) gcd_flag = True else: alpha = (((X4 - X5)%mode) * modinv((X3 - X4)%mode, mode)) % mode if gcd_flag: for alpha_test in range(alpha, mode + 1, gcd): try: # alpha * X1 + beta % mode = X2 # beta % mode = X2 - alpha * X1 beta = (X3 - (alpha_test * X2)%mode ) % mode # alpha * seed + beta % mode = X1 # seed = X1 - beta * (alpha ^ -1 ) seed = ((X1 - beta) * (modinv(alpha_test, mode))) % mode DenCoder.affinehill(alpha_test, beta, seed, mode, X1) DenCoder.affinehill(alpha_test, beta, X1, mode, X2) DenCoder.affinehill(alpha_test, beta, X2, mode, X3) DenCoder.affinehill(alpha_test, beta, X3, mode, X4) # DenCoder.affinehill(alpha, beta, X4, mode, X5) l("-" * 40) l("%s is a valid mode :)" % mode) l("alpha: %s" % alpha_test) l("beta: %s" % beta) l("seed: %s" % seed) l("mode: %s" % mode) DenCoder.save_key(key_file, alpha_test, beta, seed, mode) l("You key has been saved in " + os.path.abspath(key_file.name)) found_key = True # break except Exception as e: continue else: beta = (X2 - alpha * X1) % mode # alpha * seed + beta % mode = X1 # seed = X1 - beta * (alpha ^ -1 ) seed = ((X1 - beta) * (modinv(alpha, mode))) % mode DenCoder.affinehill(alpha, beta, seed, mode, X1) DenCoder.affinehill(alpha, beta, X1, mode, X2) DenCoder.affinehill(alpha, beta, X2, mode, X3) DenCoder.affinehill(alpha, beta, X3, mode, X4) # DenCoder.affinehill(alpha, beta, X4, mode, X5) l("-" * 40) l("%s is a valid mode :)" % mode) l("alpha: %s" % alpha) l("beta: %s" % beta) l("seed: %s" % seed) l("mode: %s" % mode) DenCoder.save_key(key_file, alpha, beta, seed, mode) l("You key has been saved in " + os.path.abspath(key_file.name)) found_key = True except Exception as e: pass if not found_key: l("Sorry i wasn't able to find your key :(")
def print_lookup_table(self): l(self.look_up_table_encryption)
def extract_key(ciphertext_file, plaintext_file, key_file): PT_BYTES = open(plaintext_file, 'rb').read() CT_BYTES = open(ciphertext_file, 'rb').read() last_valid_block_size = -1 last_valid_base_num = -1 last_valid_padding_size = -1 last_valid_lookup_table = dict() for padding_size in range(1, 5): # padding = ct_file[0:padding_size] padding = CT_BYTES[0:padding_size] padding_length = int.from_bytes(padding, byteorder='little') print("-" * 20) print("Cheking padding size: %s" % padding_size) # for block_size_bytes in range(1, 100): breaked = False for block_size_bytes in range(1, 200): print("Cheking block_size : %s" % block_size_bytes) # for base_num in [9]: # for base_num in [3,5,6,7,8,9]: for base_num in range(2, 10): # l("Checking base_num: %s" % base_num ) # Read Cipher Block biggest_number_in_block_base_10_len = len(str(int2base(2 ** (block_size_bytes * 8), base_num))) max_block_size_after_encrypt_bits = len( binaryStr(int(str(base_num - 1) * biggest_number_in_block_base_10_len, base_num))) max_block_size_after_encrypt_bytes = int(ceil(max_block_size_after_encrypt_bits / 8)) # print('MAX: %s' % max_block_size_after_encrypt_bytes) shit = CT_BYTES[padding_size:padding_size + max_block_size_after_encrypt_bytes] cipher_int_base_10 = int.from_bytes(shit, byteorder='little') cipher_int = int2base(cipher_int_base_10, base_num) block_size = max_block_size_after_encrypt_bytes * 8 - padding_length zeros_count = block_size - len(bin(cipher_int_base_10)[2:]) cipher_block_in_base_n = zeros_count * '0' + cipher_int # Read PlainText Block plaintext_block_base_10 = int.from_bytes(PT_BYTES[0:block_size_bytes], byteorder='little') plaintext_block_base_n = int2base(plaintext_block_base_10, base_num) # print(plaintext_block_base_n) # print(cipher_block_in_base_n) # If two blocks are valid: # 1. Their len must be same size # 2. Dictionary generated by them should be valid for all numbers in block if len(plaintext_block_base_n) != len(cipher_block_in_base_n): continue if last_valid_block_size < block_size_bytes: is_lookup_table_valid, encryption_lookup_table = DenCoder.is_dictionary_valid( plaintext_block_base_n, cipher_block_in_base_n) if is_lookup_table_valid: last_valid_padding_size = padding_size last_valid_base_num = base_num last_valid_block_size = block_size_bytes last_valid_lookup_table = encryption_lookup_table # print("VALID: %s" % last_valid_block_size) # if breaked: # break if last_valid_base_num == -1: exit("Unable to find a valid solution :(") print("Valid Base Number: %s" % last_valid_base_num) print("Valid Block Size: %s" % last_valid_block_size) while True: if len(last_valid_lookup_table) == last_valid_base_num: # We have all key -> value l("You are lucky bro, We found all values lookup table ") l(last_valid_lookup_table) break elif len(last_valid_lookup_table) + 1 == last_valid_base_num: # Only one value is missing so we can find it using Proof behind l("There is only one value missing in our lookup table, but we can use Proof behind to find it :)") l("Current lookup table:") l(last_valid_lookup_table) all_keys = [str(x) for x in range(last_valid_base_num)] all_values = [str(x) for x in range(last_valid_base_num)] for index, key in enumerate(last_valid_lookup_table.keys()): if key in last_valid_lookup_table: all_values.remove(last_valid_lookup_table[key]) all_keys.remove(key) last_valid_lookup_table[all_keys[0]] = all_values[0] l("After finding missing value:") l(last_valid_lookup_table) break else: # More than one value is missing, We need to read another block l("We didn't get enough numbers to calculate valid key") l("Let's read another block") l(last_valid_lookup_table) biggest_number_in_block_base_10_len = len( str(int2base(2 ** (last_valid_block_size * 8), last_valid_base_num))) max_block_size_after_encrypt_bits = len(binaryStr( int(str(last_valid_base_num - 1) * biggest_number_in_block_base_10_len, last_valid_base_num))) max_block_size_after_encrypt_bytes = int(ceil(max_block_size_after_encrypt_bits / 8)) cihper_reader_generator = range(last_valid_block_size + last_valid_padding_size, 1000, max_block_size_after_encrypt_bytes + last_valid_padding_size) plain_reader_generator = range(last_valid_block_size, 1000, last_valid_block_size) for decryptor_cursor, plain_cursor in zip(cihper_reader_generator, plain_reader_generator): padding = CT_BYTES[decryptor_cursor:decryptor_cursor + last_valid_padding_size] padding_length = int.from_bytes(padding, byteorder='little') shit = CT_BYTES[decryptor_cursor:decryptor_cursor + max_block_size_after_encrypt_bytes] cipher_int_base_10 = int.from_bytes(shit, byteorder='little') cipher_int = int2base(cipher_int_base_10, last_valid_base_num) block_size = max_block_size_after_encrypt_bytes * 8 - padding_length zeros_count = block_size - len(bin(cipher_int_base_10)[2:]) cipher_block_in_base_n = zeros_count * '0' + cipher_int # Read PlainText Block plaintext_block_base_10 = int.from_bytes( PT_BYTES[plain_cursor:plain_cursor + last_valid_block_size], byteorder='little') plaintext_block_base_n = int2base(plaintext_block_base_10, last_valid_base_num) is_lookup_table_valid, last_valid_lookup_table = DenCoder.is_dictionary_valid( plaintext_block_base_n, cipher_block_in_base_n, last_valid_lookup_table) if is_lookup_table_valid: l("Something went wrong :(") exit(-1) if len(last_valid_lookup_table) + 1 >= last_valid_base_num: l("We've read enough blocks to crack") break l("Now we have lookup table, Let's find a valid seed to generate look up table") valid_seed = None for seed in range(10000000000000000): test_lookup_table = DenCoder.generate_table(seed, last_valid_base_num, 'enc') if test_lookup_table == last_valid_lookup_table: l("Found a valid seed: %s" % seed) valid_seed = seed break if valid_seed is None: l("Sorry we were unable to find a valid seed :(") else: DenCoder.save_key(key_file, last_valid_base_num, valid_seed, last_valid_block_size)
def generate_key(key_file,base_num,block_size_bytes): l("Generating key file ...") seed = random.random() #den_coder = DenCoder(base_num=base_num, seed=seed, block_size_bytes=block_size_bytes) DenCoder.save_key(key_file, base_num=base_num, seed=seed, block_size_bytes=block_size_bytes) l("Key file generated at %s" % (os.path.realpath(key_file.name)))
def fullcrack(ciphertext_file, plaintext_file, key_file): l("Not implemented yet")
def decrypt(key_file,ciphertext_file,plaintext_file): l("Parsing key file") den_coder = DenCoder.read_key(open(key_file)) den_coder.decrypt_file(ciphertext_file,plaintext_file)
def generate_key(key_file, alpha, beta, seed, mode): l("Generating key file ...") DenCoder.save_key(key_file, alpha, beta, seed, mode) l("Key file generated at %s" % (os.path.realpath(key_file.name)))