def test_session(): initiator = RLPxSession(ECCx(raw_privkey=mk_privkey('secret1')), is_initiator=True) initiator_pubk = initiator.ecc.raw_pubkey responder = RLPxSession(ECCx(raw_privkey=mk_privkey('secret2'))) responder_pubk = responder.ecc.raw_pubkey auth_msg = initiator.create_auth_message(remote_pubkey=responder_pubk) auth_msg_ct = initiator.encrypt_auth_message(auth_msg, responder_pubk) responder.decode_authentication(auth_msg_ct) auth_ack_msg = responder.create_auth_ack_message() auth_ack_msg_ct = responder.encrypt_auth_ack_message( auth_ack_msg, initiator_pubk) initiator.decode_auth_ack_message(auth_ack_msg_ct) initiator.setup_cipher() responder.setup_cipher() assert responder.ecdhe_shared_secret == initiator.ecdhe_shared_secret assert responder.token == initiator.token assert responder.aes_secret == initiator.aes_secret assert responder.mac_secret == initiator.mac_secret assert responder.egress_mac.digest() == initiator.ingress_mac.digest() assert responder.egress_mac.digest() == initiator.ingress_mac.digest() assert responder.ingress_mac.digest() == initiator.egress_mac.digest() assert responder.ingress_mac.digest() == initiator.egress_mac.digest() assert responder.mac_secret == initiator.mac_secret return initiator, responder
def test_auth_ack_is_eip8_for_eip8_auth(): responder = RLPxSession(ECCx(raw_privkey=eip8_values['key_b'])) responder.decode_authentication(eip8_handshakes[1]['auth']) assert responder.got_eip8_auth ack = responder.create_auth_ack_message(version=55) ack_ct = responder.encrypt_auth_ack_message(ack) initiator = RLPxSession(ECCx(raw_privkey=eip8_values['key_a']), is_initiator=True) initiator.decode_auth_ack_message(ack_ct) assert initiator.got_eip8_ack assert initiator.remote_version == 55
def test_eip8_handshake_messages(): initiator = RLPxSession(ECCx(raw_privkey=eip8_values['key_a']), is_initiator=True) responder = RLPxSession(ECCx(raw_privkey=eip8_values['key_b'])) for handshake in eip8_handshakes: ack_rest = initiator.decode_auth_ack_message(handshake['ack']) assert initiator.remote_ephemeral_pubkey == eip8_values['eph_pub_b'] assert initiator.responder_nonce == eip8_values['nonce_b'] assert initiator.got_eip8_ack == handshake['eip8_format'] assert initiator.remote_version == handshake['ack_version'] assert ack_rest == b'' auth_rest = responder.decode_authentication(handshake['auth']) assert responder.remote_ephemeral_pubkey == eip8_values['eph_pub_a'] assert responder.initiator_nonce == eip8_values['nonce_a'] assert responder.remote_pubkey == eip8_values['pub_a'] assert responder.got_eip8_auth == handshake['eip8_format'] assert auth_rest == b''
def test_eip8_key_derivation(): responder = RLPxSession(ECCx(raw_privkey=eip8_values['key_b']), ephemeral_privkey=eip8_values['eph_key_b']) responder.decode_authentication(eip8_handshakes[1]['auth']) ack = responder.create_auth_ack_message(nonce=eip8_values['nonce_b']) responder.encrypt_auth_ack_message(ack) responder.setup_cipher() want_aes_secret = decode_hex( b'80e8632c05fed6fc2a13b0f8d31a3cf645366239170ea067065aba8e28bac487') want_mac_secret = decode_hex( b'2ea74ec5dae199227dff1af715362700e989d889d7a493cb0639691efb8e5f98') assert responder.aes_secret == want_aes_secret assert responder.mac_secret == want_mac_secret responder.ingress_mac.update(b'foo') mac_digest = responder.ingress_mac.digest() want_mac_digest = decode_hex( b'0c7ec6340062cc46f5e9f1e3cf86f8c8c403c5a0964f5df0ebd34a75ddc86db5') assert mac_digest == want_mac_digest
def test_handshake(): tv = test_values initiator = RLPxSession(ECCx(raw_privkey=tv['initiator_private_key']), is_initiator=True, ephemeral_privkey=tv['initiator_ephemeral_private_key']) initiator_pubkey = initiator.ecc.raw_pubkey responder = RLPxSession(ECCx(raw_privkey=tv['receiver_private_key']), ephemeral_privkey=tv['receiver_ephemeral_private_key']) responder_pubkey = responder.ecc.raw_pubkey # test encryption _enc = initiator.encrypt_auth_message(tv['auth_plaintext'], responder_pubkey) assert len(_enc) == len(tv['auth_ciphertext']) assert len(tv['auth_ciphertext']) == 113 + len(tv['auth_plaintext']) # len # test auth_msg plain auth_msg = initiator.create_auth_message(remote_pubkey=responder_pubkey, ephemeral_privkey=tv['initiator_ephemeral_private_key'], nonce=tv['initiator_nonce']) # test auth_msg plain assert len(auth_msg) == len(tv['auth_plaintext']) == 194 assert auth_msg[65:] == tv['auth_plaintext'][65:] # starts with non deterministic k _auth_msg_cipher = initiator.encrypt_auth_message(auth_msg, responder_pubkey) # test shared responder.ecc.get_ecdh_key(initiator_pubkey) == \ initiator.ecc.get_ecdh_key(responder_pubkey) # test decrypt assert auth_msg == responder.ecc.ecies_decrypt(_auth_msg_cipher) # check receive responder_ephemeral_pubkey = privtopub(tv['receiver_ephemeral_private_key']) auth_msg_cipher = tv['auth_ciphertext'] auth_msg = responder.ecc.ecies_decrypt(auth_msg_cipher) assert auth_msg[65:] == tv['auth_plaintext'][65:] # starts with non deterministic k responder.decode_authentication(auth_msg_cipher) auth_ack_msg = responder.create_auth_ack_message(responder_ephemeral_pubkey, nonce=tv['receiver_nonce']) assert auth_ack_msg == tv['authresp_plaintext'] auth_ack_msg_cipher = responder.encrypt_auth_ack_message(auth_ack_msg, remote_pubkey=responder.remote_pubkey) # set auth ack msg cipher (needed later for mac calculation) responder.auth_ack = tv['authresp_ciphertext'] responder.setup_cipher() assert responder.ecdhe_shared_secret == tv['ecdhe_shared_secret'] assert len(responder.token) == len(tv['token']) assert responder.token == tv['token'] assert responder.aes_secret == tv['aes_secret'] assert responder.mac_secret == tv['mac_secret'] assert responder.initiator_nonce == tv['initiator_nonce'] assert responder.responder_nonce == tv['receiver_nonce'] assert responder.auth_init == tv['auth_ciphertext'] assert responder.auth_ack == tv['authresp_ciphertext'] # test values are from initiator perspective? assert responder.ingress_mac.digest() == tv['initial_egress_MAC'] assert responder.ingress_mac.digest() == tv['initial_egress_MAC'] assert responder.egress_mac.digest() == tv['initial_ingress_MAC'] assert responder.egress_mac.digest() == tv['initial_ingress_MAC'] r = responder.decrypt(tv['initiator_hello_packet']) # unpack hello packet import struct import rlp import rlp.sedes as sedes from rlp.codec import consume_item header = r['header'] frame_length = struct.unpack(b'>I', b'\x00' + header[:3])[0] header_sedes = sedes.List([sedes.big_endian_int, sedes.big_endian_int]) header_data = rlp.decode(header[3:], strict=False, sedes=header_sedes) print('header', repr(header_data)) # frame frame = r['frame'] # normal: rlp(packet-type) [|| rlp(packet-data)] || padding packet_type, end = consume_item(frame, start=0) packet_type = rlp.decode(frame, sedes=sedes.big_endian_int, strict=False) print('packet_type', repr(packet_type)) # decode hello body _sedes_capabilites_tuple = sedes.List([sedes.binary, sedes.big_endian_int]) structure = [ ('version', sedes.big_endian_int), ('client_version_string', sedes.big_endian_int), ('capabilities', sedes.CountableList(_sedes_capabilites_tuple)), ('listen_port', sedes.big_endian_int), ('remote_pubkey', sedes.binary) ] hello_sedes = sedes.List([x[1] for x in structure]) frame_data = rlp.decode(frame[end:], sedes=hello_sedes) frame_data = dict((structure[i][0], x) for i, x in enumerate(frame_data)) print('frame', frame_data)