def try_key_lets(cipher, key_potentials): print('Trying keys... \n') dictionary = ct.load_dictionary() for attempt in itertools.product(*key_potentials): cm = zip(list(encrypted), itertools.cycle(attempt)) cm = [chr(x ^ ord(y)) for x, y in cm] if ct.is_language(''.join(cm), dictionary): print('Decrypted text:\n{}\nKey:\n{}'.format(attempt, cm)) else: continue
def cycle_xor(hex_string): byte_string = ct.hex_to_bytes(hex_string) found_match = False dictionary = ct.load_dictionary() for _ in range(256): xored = bytes(b ^ _ for b in list(byte_string)) if ct.is_language(''.join([chr(b) for b in xored]), dictionary): print('Key: {}, ASCII: {}'.format(_, repr(xored))) found_match = True if not found_match: print('Unable to find match.')
def cycle_xor(hex_string): byte_string = ct.hex_to_bytes(hex_string) found_match = False dictionary = ct.load_dictionary() for _ in range(256): xored = bytes(b ^ _ for b in list(byte_string)) if ct.is_language(''.join([chr(b) for b in xored]), dictionary): print('Hex String: {} \nKey: "{}" \nASCII: {}'.format(hex_string, chr(_), xored.decode())) found_match = True if not found_match: # I had this print out each line in the loaded .txt, but that made output messy. Now passing. pass
def cycle_xor(hex_string): byte_string = ct.hex_to_bytes(hex_string) found_match = False dictionary = ct.load_dictionary() for _ in range(256): xored = bytes(b ^ _ for b in list(byte_string)) if ct.is_language(''.join([chr(b) for b in xored]), dictionary): print('Hex String: {} \nKey: "{}" \nASCII: {}'.format( hex_string, chr(_), xored.decode())) found_match = True if not found_match: # I had this print out each line in the loaded .txt, but that made output messy. Now passing. pass
def try_likely_bytes(possible_key_bytes, list_of_ciphers): ''' Xor the Cartesian product of 5 most likely key-stream bytes against ciphers, if an English sentence is detected, return decryption.''' min_len = min([len(cipher) for cipher in list_of_ciphers]) possible_key_streams = product(*possible_key_bytes) dictionary = ct.load_dictionary() for key_stream in possible_key_streams: concat = b''.join(key_stream) for cipher in list_of_ciphers: work_cipher = cipher[:len(concat)] decryption = b''.join( [bytes([a ^ b]) for a, b in zip(cipher, concat)]) if ct.is_language(decryption, dictionary): print('Likely key stream found.') return concat else: print('Unable to find key stream.') return None
def try_likely_bytes(possible_key_bytes, list_of_ciphers): ''' Xor the Cartesian product of 5 most likely key-stream bytes against ciphers, if an English sentence is detected, return decryption.''' min_len = min([len(cipher) for cipher in list_of_ciphers]) possible_key_streams = product(*possible_key_bytes) dictionary = ct.load_dictionary() for key_stream in possible_key_streams: concat = b''.join(key_stream) for cipher in list_of_ciphers: work_cipher = cipher[:len(concat)] decryption = b''.join([bytes([a ^ b]) for a,b in zip(cipher, concat)]) if ct.is_language(decryption, dictionary): print('Likely key stream found.') return concat else: print('Unable to find key stream.') return None
def hamming_by_key_len(cipher, max_len=40, blocks=6): ''' Return dictionary of hamming distance by key length.''' keys_ham_distance = {} for key_len in range(2, max_len + 1): keys_ham_distance[key_len] = 0 for block in range(blocks): keys_ham_distance[key_len] += ct.hamming_slices(encrypted, key_len, block) / key_len keys_ham_distance[key_len] /= blocks return keys_ham_distance if __name__ == '__main__': with open('6.txt') as f: encrypted = f.read() encrypted = ct.base64_to_bytes(encrypted) attempts = hamming_by_key_len(encrypted) lowest_hamming = sorted(attempts, key=attempts.get)[:5] print('Prospective keys:\n{}'.format(lowest_hamming)) dictionary = ct.load_dictionary() for key_len in lowest_hamming: pot_keys = find_potential_keys(encrypted, key_len) pot_lets = [x for x, y in pot_keys] attempt = ''.join([chr(x) for x in ct.cycle_xor(encrypted, pot_lets)]) if ct.is_language(attempt, dictionary): print('Potential key:\n{}\nDecryption:\n{}'.format(''.join(pot_lets), attempt)) else: print('Key length of {} does not produce match on most likely letters.'.format(key_len))