def aes_encode(block, key): block = pad_bits_append(block, len(key)) # the pycrypto library expects the key and block in 8 bit ascii # encoded strings so we have to convert from the bit array block = bits_to_string(block) key = bits_to_string(key) ecb = AES.new(key.encode("latin-1"), AES.MODE_ECB) return string_to_bits(str(ecb.encrypt(block.encode("latin-1")), encoding="latin-1"))
def aes_encode(block, key): block = pad_bits_append(block, len(key)) # the pycrypto library expects the key and block in 8 bit ascii # encoded strings so we have to convert from the bit array block = bits_to_string(block) key = bits_to_string(key) ecb = AES.new(key.encode("latin-1"), AES.MODE_ECB) return string_to_bits( str(ecb.encrypt(block.encode("latin-1")), encoding="latin-1"))
def deliver_hint(recipient, hint_str): """ Establish an encrypted session with the specified recipient and send hint_str. """ initialization_response = initialize(recipient[0]) session_token = initialization_response['token'] pg = get_pg() p = int(pg['p'], 16) g = int(pg['g'], 16) eve_key_response_int = pow(g, X_EVE, p) eve_key_response = hex(eve_key_response_int)[2:] # chop off the "0x" key_received_response = send_key(recipient[0], session_token, eve_key_response, "Eve") (ctr_key, ctr_nonce) = get_ctr_info(X_EVE, int(initialization_response['public'], 16)) initial_message = receive_msg(recipient[0], session_token) decrypted_message = counter_mode_encrypt(initial_message['msg'], ctr_key, initial_message['iv'], ctr_nonce) decrypted_message_str = bits_to_string(decrypted_message) print("decrypted_message_str", decrypted_message_str) hint_hex = hex(bits_to_int(string_to_bits(hint_str)))[2:] encrypted_hint = counter_mode_encrypt(hint_hex, ctr_key, initial_message['iv'], ctr_nonce) encrypted_hint_hex = hex(bits_to_int(encrypted_hint))[2:] response = send_msg(recipient[0], session_token, encrypted_hint_hex, initial_message['iv']) decrypted_message = counter_mode_encrypt(response['reply']['msg'], ctr_key, response['reply']['iv'], ctr_nonce) decrypted_message_str = bits_to_string(decrypted_message) print("decrypted_message_str", decrypted_message_str)
def retrieve_plaintext(ciphertext, private_key, n): """ Given the specified ciphertext string encrypted using the specified private_key and n value, returns the decrypted plaintext. Removes oaep if necessary. """ ciphertext_bits = pad_bits(string_to_bits(ciphertext), MESSAGE_CHARS * ASCII_BITS) ciphertext_int = bits_to_int(ciphertext_bits) padded_plaintext_int = pow(ciphertext_int, private_key, n) # If the message wasn't padded, we'll detect that here. padded_plaintext_bits = pad_bits(convert_to_bits(padded_plaintext_int), len(ciphertext_bits)) plaintext_string = bits_to_string(padded_plaintext_bits).strip('\x00') if is_valid_message(plaintext_string): return plaintext_string else: return remove_oaep_from_plaintext(padded_plaintext_int, n)
def get_ctr_info(private_value, received_public_value): """ Calculates shared secret and returns (key, nonce) for use with AES-CTR Expects parameters to be ints. Returns key and nonce as hex strings. """ pg = get_pg() p = int(pg['p'], 16) shared_secret = pow(received_public_value, private_value, p) shared_secret_bits = pad_to_block(convert_to_bits(shared_secret), ASCII_BITS) shared_secret_bytestring = bits_to_string(shared_secret_bits).encode(encoding='latin-1') shared_secret_hash = sha1(shared_secret_bytestring).hexdigest() assert len(shared_secret_hash) == 40 # sha1 generates hash of 20 bytes. Use first 16 bytes for the key and last 4 for the nonce key = shared_secret_hash[0:32] nonce = shared_secret_hash[32:40] return (key, nonce)
def _verify(bills, nonces, value): """ # Returns True if all of the bills have the value specified, # False otherwise """ print("Doing verification for", len(bills), "bills") for bill, nonce in zip(bills, nonces): unblinded_bill = unblind_bill(bill, nonce, cutchoose.BANK_PUBLIC_KEY[0], cutchoose._BANK_PRIVATE_KEY, cutchoose.BANK_PUBLIC_KEY[1]) unblinded_bill_str = bits_to_string(pad_to_block(convert_to_bits(unblinded_bill), ASCII_BITS)) unblinded_bill_value = cutchoose.bill_value(unblinded_bill_str) print("unblinded bill_str is", unblinded_bill_str) if not unblinded_bill_value == value: print("bill", unblinded_bill_str, "has value", unblinded_bill_value, "but expected", value) return False print("Bills passed verification") return True
def get_ctr_info(private_value, received_public_value): """ Calculates shared secret and returns (key, nonce) for use with AES-CTR Expects parameters to be ints. Returns key and nonce as hex strings. """ pg = get_pg() p = int(pg['p'], 16) shared_secret = pow(received_public_value, private_value, p) shared_secret_bits = pad_to_block(convert_to_bits(shared_secret), ASCII_BITS) shared_secret_bytestring = bits_to_string(shared_secret_bits).encode( encoding='latin-1') shared_secret_hash = sha1(shared_secret_bytestring).hexdigest() assert len(shared_secret_hash) == 40 # sha1 generates hash of 20 bytes. Use first 16 bytes for the key and last 4 for the nonce key = shared_secret_hash[0:32] nonce = shared_secret_hash[32:40] return (key, nonce)
def lfsr_decrypt(ciphertext, lfsr): """ Attempts to obtain the plaintext string corresponding to the encrypted hexadecimal string in ciphertext by xoring with a keystream produced by lfsr. Returns the resulting plaintext string. """ ciphertext_bits = hex_string_to_bits(ciphertext) keystream_bits = lfsr.get_output_bits(len(ciphertext_bits)) assert len(keystream_bits) == len(ciphertext_bits) assert keystream_bits == SAMPLE_LFSR_OUTPUT[:len(ciphertext_bits)] for i in range(LFSR_DECRYPTION_ATTEMPTS): potential_plaintext_bits = xor(ciphertext_bits, keystream_bits) potential_plaintext_str = bits_to_string(potential_plaintext_bits) if is_valid_message(potential_plaintext_str): return potential_plaintext_str keystream_bits = keystream_bits[1:] + [lfsr.get_next_output()] return None
def decrypt_by_public_key_root(public_key, n, ciphertext): ciphertext_bits = string_to_bits(ciphertext) ciphertext_int = bits_to_int(ciphertext_bits) PUBLIC_KEY_ROOT_ATTEMPTS = 10 for i in range(PUBLIC_KEY_ROOT_ATTEMPTS): plaintext_root_result = gmpy2.iroot(gmpy2.mpz(ciphertext_int + i * n), public_key) if plaintext_root_result[1]: plaintext_int = int(plaintext_root_result[0]) assert pow(plaintext_int, public_key) == ciphertext_int + i * n print("Found integer root of message") plaintext_bits = pad_bits(convert_to_bits(plaintext_int), MESSAGE_CHARS * ASCII_BITS) plaintext_string = bits_to_string(plaintext_bits).strip('\x00') assert is_valid_message(plaintext_string) return plaintext_string else: print("Root result is non-integer") print("Unable to decrypt by taking private key root") return None
def remove_oaep_from_plaintext(oaep_padded_plaintext_int, n): """ Given the specified plaintext integer padded using OAEP, returns the corresponding plaintext string with OAEP removed. n gives the parameter from the RSA operation ciphertext = plaintext ^ public_key (mod n) used to encrypt the message. This parameter is required because the message produced by the RSA decryption operation m = plaintext ^ private_key (mod n) can be any of plaintext + i * n where i is in {0, 1, 2, ...}. Therefore we'll keep trying different guesses of i until one of them (hopefully) produces a valid message. Returns None if unable to recover a valid plaintext string. """ MAX_OAEP_REMOVAL_TRIES = 10 for i in range(MAX_OAEP_REMOVAL_TRIES): g = (MESSAGE_CHARS * ASCII_BITS) // 2 h = (MESSAGE_CHARS * ASCII_BITS) // 2 plaintext_bits = oaep.decode_oaep(int(oaep_padded_plaintext_int + n * i), g, h) plaintext_string = bits_to_string(plaintext_bits).strip('\x00') if is_valid_message(plaintext_string): return plaintext_string return None
def _verify(bills, nonces, value): """ # Returns True if all of the bills have the value specified, # False otherwise """ print("Doing verification for", len(bills), "bills") for bill, nonce in zip(bills, nonces): unblinded_bill = unblind_bill(bill, nonce, cutchoose.BANK_PUBLIC_KEY[0], cutchoose._BANK_PRIVATE_KEY, cutchoose.BANK_PUBLIC_KEY[1]) unblinded_bill_str = bits_to_string( pad_to_block(convert_to_bits(unblinded_bill), ASCII_BITS)) unblinded_bill_value = cutchoose.bill_value(unblinded_bill_str) print("unblinded bill_str is", unblinded_bill_str) if not unblinded_bill_value == value: print("bill", unblinded_bill_str, "has value", unblinded_bill_value, "but expected", value) return False print("Bills passed verification") return True
def remove_oaep_from_plaintext(oaep_padded_plaintext_int, n): """ Given the specified plaintext integer padded using OAEP, returns the corresponding plaintext string with OAEP removed. n gives the parameter from the RSA operation ciphertext = plaintext ^ public_key (mod n) used to encrypt the message. This parameter is required because the message produced by the RSA decryption operation m = plaintext ^ private_key (mod n) can be any of plaintext + i * n where i is in {0, 1, 2, ...}. Therefore we'll keep trying different guesses of i until one of them (hopefully) produces a valid message. Returns None if unable to recover a valid plaintext string. """ MAX_OAEP_REMOVAL_TRIES = 10 for i in range(MAX_OAEP_REMOVAL_TRIES): g = (MESSAGE_CHARS * ASCII_BITS) // 2 h = (MESSAGE_CHARS * ASCII_BITS) // 2 plaintext_bits = oaep.decode_oaep( int(oaep_padded_plaintext_int + n * i), g, h) plaintext_string = bits_to_string(plaintext_bits).strip('\x00') if is_valid_message(plaintext_string): return plaintext_string return None
import lfsr import binascii import unit4_util given_prng = [0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0] def xor(word1, word2): key = [] for i in xrange(0, len(word1)): key.append(word1[i] ^ word2[i]) return key message = '8d801f00c7554d3980b0c4f400c1ebc572d86f57f48d322b8e7c3a1f01c531dbe772b77be5acd34bf1979b70089615ace253c4b01350f36f82215f164b7934fdd48a30' m_bytes = binascii.unhexlify(message) message_bits = unit4_util.string_to_bits(m_bytes) # Use LFSR_A51_1 to generate another 200 bits for the PRNG lfsr = lfsr.LFSR_A51_1(given_prng[1000-19:]) new_prng = given_prng[0:1000-19] for _ in range(0, 2000): new_prng.append(lfsr.next_output_bit()) # Loop through each 2000 bit range of the PRNG and use it to try and decrypt the # message. Examine each output message visually to find the interesting one # (which is message 1000 incidentally) for i in range(0, 2000): otp = new_prng[i:len(message_bits) + i] plaintext = xor(message_bits, otp) print i, unit4_util.bits_to_string(plaintext)
key corresponding to the specified private_key. """ ciphertext_int = bits_to_int(ciphertext) plaintext_int = pow(ciphertext_int, private_key, n) return decode_oaep(plaintext_int + n, g, h) def decode_oaep(oaep_padded_int, g, h): """ Given the specified OAEP-padded plaintext as an integer (with OAEP using parameters g and h), returns the corresponding plaintext bits with the padding removed. """ plaintext_bits = pad_bits(convert_to_bits(oaep_padded_int), g + h) first_chunk = plaintext_bits[0:g] second_chunk = plaintext_bits[g:g + h] assert len(plaintext_bits) == g + h assert len(first_chunk) == g assert len(second_chunk) == h first_chunk_H = hash(first_chunk, h) r = xor(first_chunk_H, second_chunk) G_r = hash(r, g) m_prime = xor(first_chunk, G_r) return m_prime if __name__ == "__main__": print("Decrypting...") plaintext_bits = decrypt(ciphertext, n, d, g, h) plaintext = bits_to_string(plaintext_bits).strip('\x00') print("Message:", plaintext)
initial_message['iv'], ctr_nonce) encrypted_hint_hex = hex(bits_to_int(encrypted_hint))[2:] response = send_msg(recipient[0], session_token, encrypted_hint_hex, initial_message['iv']) decrypted_message = counter_mode_encrypt(response['reply']['msg'], ctr_key, response['reply']['iv'], ctr_nonce) decrypted_message_str = bits_to_string(decrypted_message) print("decrypted_message_str", decrypted_message_str) if __name__ == "__main__": assert bits_to_string(hex_string_to_bits("53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67")) == \ "Single block msg" print("Trying Test Vector #1") assert counter_mode_encrypt("53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67", "AE 68 52 F8 12 10 67 CC 4B F7 A5 76 55 77 F3 9E", "00 00 00 00 00 00 00 00", "00 00 00 30") == \ hex_string_to_bits("E4 09 5D 4F B7 A7 B3 79 2D 61 75 A3 26 13 11 B8") print("Trying Test Vector #2") assert counter_mode_encrypt( "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" + "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F", "7E 24 06 78 17 FA E0 D7 43 D6 CE 1F 32 53 91 63", "C0 54 3B 59 DA 48 D9 0B",
def hash(input_, length): input_string = bits_to_string(input_).encode(encoding='latin-1') h = sha512(input_string).digest() return string_to_bits(h)[:length]
def run_mitm_session(first, second): """ Run a message exchange between the specified parties, but perform a MITM attack using a known private key for the exchange with each in order to snoop on the contents of the messages. """ first_initialization_response = initialize(first[0]) first_session_token = first_initialization_response['token'] second_initialization_response = initialize(second[0]) second_session_token = second_initialization_response['token'] pg = get_pg() p = int(pg['p'], 16) g = int(pg['g'], 16) eve_key_response_int = pow(g, X_EVE, p) eve_key_response = hex(eve_key_response_int)[2:] # chop off the "0x" first_key_received_response = send_key(first[0], first_session_token, eve_key_response, second[1]) second_key_received_response = send_key(second[0], second_session_token, eve_key_response, first[1]) (first_ctr_key, first_ctr_nonce) = get_ctr_info(X_EVE, int(first_initialization_response['public'], 16)) (second_ctr_key, second_ctr_nonce) = get_ctr_info(X_EVE, int(second_initialization_response['public'], 16)) first_person_message = receive_msg(first[0], first_session_token) first_person_decrypted_message = counter_mode_encrypt(first_person_message['msg'], first_ctr_key, first_person_message['iv'], first_ctr_nonce) first_person_decrypted_message_str = bits_to_string(first_person_decrypted_message) first_person_decrypted_message_hex = hex(bits_to_int(first_person_decrypted_message))[2:] test_encrypted_message_bits = counter_mode_encrypt(first_person_decrypted_message_hex, first_ctr_key, first_person_message['iv'], first_ctr_nonce) test_encrypted_message_str = hex(bits_to_int(test_encrypted_message_bits))[2:] assert test_encrypted_message_str == first_person_message['msg'] # Set up the message to be sent through the MITM session with second person first_re_encrypted_message_bits = counter_mode_encrypt(first_person_decrypted_message_hex, second_ctr_key, first_person_message['iv'], second_ctr_nonce) first_re_encrypted_message_str = hex(bits_to_int(first_re_encrypted_message_bits))[2:] response = send_msg(second[0], second_session_token, first_person_message['msg'], first_person_message['iv']) recipient, sender = first, second recipient_session_token, sender_session_token = first_session_token, second_session_token recipient_ctr_key, sender_ctr_key = first_ctr_key, second_ctr_key recipient_ctr_nonce, sender_ctr_nonce = first_ctr_nonce, second_ctr_nonce while 'reply' in response and 'iv' in response['reply'] and len(response['reply']['iv']) > 0: decrypted_response = counter_mode_encrypt(response['reply']['msg'], sender_ctr_key, response['reply']['iv'], sender_ctr_nonce) decrypted_response_str = bits_to_string(decrypted_response) print(sender[1], "decrypted_response_str", decrypted_response_str) response = send_msg(recipient[0], recipient_session_token, response['reply']['msg'], response['reply']['iv']) # Switch places recipient, sender = sender, recipient recipient_session_token, sender_session_token = sender_session_token, recipient_session_token recipient_ctr_key, sender_ctr_key = sender_ctr_key, recipient_ctr_key recipient_ctr_nonce, sender_ctr_nonce = sender_ctr_nonce, recipient_ctr_nonce
def run_mitm_session(first, second): """ Run a message exchange between the specified parties, but perform a MITM attack using a known private key for the exchange with each in order to snoop on the contents of the messages. """ first_initialization_response = initialize(first[0]) first_session_token = first_initialization_response['token'] second_initialization_response = initialize(second[0]) second_session_token = second_initialization_response['token'] pg = get_pg() p = int(pg['p'], 16) g = int(pg['g'], 16) eve_key_response_int = pow(g, X_EVE, p) eve_key_response = hex(eve_key_response_int)[2:] # chop off the "0x" first_key_received_response = send_key(first[0], first_session_token, eve_key_response, second[1]) second_key_received_response = send_key(second[0], second_session_token, eve_key_response, first[1]) (first_ctr_key, first_ctr_nonce) = get_ctr_info( X_EVE, int(first_initialization_response['public'], 16)) (second_ctr_key, second_ctr_nonce) = get_ctr_info( X_EVE, int(second_initialization_response['public'], 16)) first_person_message = receive_msg(first[0], first_session_token) first_person_decrypted_message = counter_mode_encrypt( first_person_message['msg'], first_ctr_key, first_person_message['iv'], first_ctr_nonce) first_person_decrypted_message_str = bits_to_string( first_person_decrypted_message) first_person_decrypted_message_hex = hex( bits_to_int(first_person_decrypted_message))[2:] test_encrypted_message_bits = counter_mode_encrypt( first_person_decrypted_message_hex, first_ctr_key, first_person_message['iv'], first_ctr_nonce) test_encrypted_message_str = hex( bits_to_int(test_encrypted_message_bits))[2:] assert test_encrypted_message_str == first_person_message['msg'] # Set up the message to be sent through the MITM session with second person first_re_encrypted_message_bits = counter_mode_encrypt( first_person_decrypted_message_hex, second_ctr_key, first_person_message['iv'], second_ctr_nonce) first_re_encrypted_message_str = hex( bits_to_int(first_re_encrypted_message_bits))[2:] response = send_msg(second[0], second_session_token, first_person_message['msg'], first_person_message['iv']) recipient, sender = first, second recipient_session_token, sender_session_token = first_session_token, second_session_token recipient_ctr_key, sender_ctr_key = first_ctr_key, second_ctr_key recipient_ctr_nonce, sender_ctr_nonce = first_ctr_nonce, second_ctr_nonce while 'reply' in response and 'iv' in response['reply'] and len( response['reply']['iv']) > 0: decrypted_response = counter_mode_encrypt(response['reply']['msg'], sender_ctr_key, response['reply']['iv'], sender_ctr_nonce) decrypted_response_str = bits_to_string(decrypted_response) print(sender[1], "decrypted_response_str", decrypted_response_str) response = send_msg(recipient[0], recipient_session_token, response['reply']['msg'], response['reply']['iv']) # Switch places recipient, sender = sender, recipient recipient_session_token, sender_session_token = sender_session_token, recipient_session_token recipient_ctr_key, sender_ctr_key = sender_ctr_key, recipient_ctr_key recipient_ctr_nonce, sender_ctr_nonce = sender_ctr_nonce, recipient_ctr_nonce
hint_hex = hex(bits_to_int(string_to_bits(hint_str)))[2:] encrypted_hint = counter_mode_encrypt(hint_hex, ctr_key, initial_message['iv'], ctr_nonce) encrypted_hint_hex = hex(bits_to_int(encrypted_hint))[2:] response = send_msg(recipient[0], session_token, encrypted_hint_hex, initial_message['iv']) decrypted_message = counter_mode_encrypt(response['reply']['msg'], ctr_key, response['reply']['iv'], ctr_nonce) decrypted_message_str = bits_to_string(decrypted_message) print("decrypted_message_str", decrypted_message_str) if __name__ == "__main__": assert bits_to_string(hex_string_to_bits("53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67")) == \ "Single block msg" print("Trying Test Vector #1") assert counter_mode_encrypt("53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67", "AE 68 52 F8 12 10 67 CC 4B F7 A5 76 55 77 F3 9E", "00 00 00 00 00 00 00 00", "00 00 00 30") == \ hex_string_to_bits("E4 09 5D 4F B7 A7 B3 79 2D 61 75 A3 26 13 11 B8") print("Trying Test Vector #2") assert counter_mode_encrypt( "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F" + "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F", "7E 24 06 78 17 FA E0 D7 43 D6 CE 1F 32 53 91 63", "C0 54 3B 59 DA 48 D9 0B",
ii = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] ee = [e0, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15] nn = [n0, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15] cc = [c0, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15] import gmpy # solution for message 1 for i, (e, c, n) in enumerate(zip(ee, cc, nn)): if e != 3: continue c = gmpy.mpz(c) (m, r) = gmpy.root(c, e) if r == 1: bm = convert_to_bits(m) print bits_to_string(pad_bits(bm, len(bm) + pad(len(bm)))) # solution for message 9 for i, (e, c, n) in enumerate(zip(ee, cc, nn)): if e != 3: continue for k in range(1, 32): c = gmpy.mpz(c) + k * gmpy.mpz(n) (m, r) = gmpy.root(c, e) if r == 1: bm = convert_to_bits(m) print bits_to_string(pad_bits(bm, len(bm) + pad(len(bm)))) # solution for 11 and 12 #for i, n_i in enumerate(nn): # for j, n_j in enumerate(nn):
def hash(input_, length): h = sha512(bits_to_string(input_)).digest() return string_to_bits(h)[:length]