def test_equality(identity_scheme_registry): base_kwargs = { "sequence_number": 0, "kv_pairs": { b"id": b"mock", b"key1": b"value1", b"key2": b"value2", }, "signature": b"signature", "identity_scheme_registry": identity_scheme_registry, } base_enr = ENR(**base_kwargs) equal_enr = ENR(**base_kwargs) enr_different_sequence_number = ENR( **assoc(base_kwargs, "sequence_number", 1)) enr_different_kv_pairs = ENR( **assoc_in(base_kwargs, ("kv_pairs", b"key1"), b"value2"), ) enr_different_signature = ENR( **assoc(base_kwargs, "signature", b"different-signature")) assert base_enr == base_enr assert equal_enr == base_enr assert enr_different_sequence_number != base_enr assert enr_different_kv_pairs != base_enr assert enr_different_signature != base_enr
def test_signature_scheme_selection(mock_identity_scheme, identity_scheme_registry): mock_enr = ENR(0, {b"id": b"mock"}, b"", identity_scheme_registry) assert mock_enr.identity_scheme is mock_identity_scheme v4_enr = ENR(0, {b"id": b"v4", b"secp256k1": b"\x02" * 33}, b"", identity_scheme_registry) assert v4_enr.identity_scheme is V4IdentityScheme with pytest.raises(ValidationError): ENR(0, {b"id": b"other"}, b"", identity_scheme_registry)
def test_mapping_interface(identity_scheme_registry): kv_pairs = { b"id": b"mock", b"key1": b"value1", b"key2": b"value2", } enr = ENR( signature=b"", sequence_number=0, kv_pairs=kv_pairs, identity_scheme_registry=identity_scheme_registry, ) for key, value in kv_pairs.items(): assert key in enr assert enr[key] == value assert enr.get(key) == value not_a_key = b"key3" assert not_a_key not in kv_pairs assert not_a_key not in enr enr.get(not_a_key) is None assert enr.get(not_a_key, b"default") == b"default" assert tuple(enr.keys()) == tuple(kv_pairs.keys()) assert tuple(enr.values()) == tuple(kv_pairs.values()) assert tuple(enr.items()) == tuple(kv_pairs.items()) assert len(enr) == len(kv_pairs) assert tuple(iter(enr)) == tuple(iter(kv_pairs))
def enr(): return ENR( sequence_number=1, signature=b"", kv_pairs={ b"id": b"v4", } )
def enr(): return ENR(sequence_number=1, signature=b"", kv_pairs={ b"id": b"v4", b"secp256k1": PrivateKey(b"\x01" * 32).public_key.to_compressed_bytes(), })
def test_inititialization(identity_scheme_registry): valid_sequence_number = 0 valid_kv_pairs = {b"id": b"mock"} valid_signature = b"" # signature is not validated during initialization assert UnsignedENR( sequence_number=valid_sequence_number, kv_pairs=valid_kv_pairs, identity_scheme_registry=identity_scheme_registry, ) assert ENR( sequence_number=valid_sequence_number, kv_pairs=valid_kv_pairs, signature=valid_signature, identity_scheme_registry=identity_scheme_registry, ) with pytest.raises(ValidationError): UnsignedENR( sequence_number=valid_sequence_number, kv_pairs={b"no-id": b""}, identity_scheme_registry=identity_scheme_registry, ) with pytest.raises(ValidationError): ENR( sequence_number=valid_sequence_number, kv_pairs={b"no-id": b""}, signature=valid_signature, identity_scheme_registry=identity_scheme_registry, ) with pytest.raises(ValidationError): UnsignedENR( sequence_number=-1, kv_pairs=valid_kv_pairs, identity_scheme_registry=identity_scheme_registry, ) with pytest.raises(ValidationError): ENR( sequence_number=-1, kv_pairs=valid_kv_pairs, signature=valid_signature, identity_scheme_registry=identity_scheme_registry, )
def test_auth_header_preparation(tag, auth_tag, initiator_key, auth_response_key, ephemeral_pubkey): enr = ENR( sequence_number=1, signature=b"", kv_pairs={ b"id": b"v4", } ) message = PingMessage( request_id=5, enr_seq=enr.sequence_number, ) id_nonce_signature = b"\x00" * 32 packet = AuthHeaderPacket.prepare( tag=tag, auth_tag=auth_tag, message=message, initiator_key=initiator_key, id_nonce_signature=id_nonce_signature, auth_response_key=auth_response_key, enr=enr, ephemeral_pubkey=ephemeral_pubkey ) assert packet.tag == tag assert packet.auth_header.auth_tag == auth_tag assert packet.auth_header.auth_scheme_name == AUTH_SCHEME_NAME assert packet.auth_header.ephemeral_pubkey == ephemeral_pubkey decrypted_auth_response = aesgcm_decrypt( key=auth_response_key, nonce=ZERO_NONCE, cipher_text=packet.auth_header.encrypted_auth_response, authenticated_data=tag, ) decoded_auth_response = rlp.decode(decrypted_auth_response) assert is_list_like(decoded_auth_response) and len(decoded_auth_response) == 2 assert decoded_auth_response[0] == id_nonce_signature assert ENR.deserialize(decoded_auth_response[1]) == enr decrypted_message = aesgcm_decrypt( key=initiator_key, nonce=auth_tag, cipher_text=packet.encrypted_message, authenticated_data=b"".join(( tag, rlp.encode(packet.auth_header), )) ) assert decrypted_message[0] == message.message_type assert rlp.decode(decrypted_message[1:], PingMessage) == message
def test_signature_validation(mock_identity_scheme, identity_scheme_registry): unsigned_enr = UnsignedENR(0, {b"id": b"mock"}, identity_scheme_registry) private_key = b"\x00" * 32 enr = unsigned_enr.to_signed_enr(private_key) enr.validate_signature() invalid_signature = b"\xff" * 64 invalid_enr = ENR(enr.sequence_number, dict(enr), invalid_signature, identity_scheme_registry=identity_scheme_registry) with pytest.raises(ValidationError): invalid_enr.validate_signature() with pytest.raises(ValidationError): ENR( 0, {b"id": b"unknown"}, b"", identity_scheme_registry=identity_scheme_registry, )
def test_enr_v4_compat_signature_validation(): private_key = PrivateKey(b"\x11" * 32) enr = ENR( 0, { b"id": b"v4-compat", b"secp256k1": private_key.public_key.to_compressed_bytes(), b"key1": b"value1", }, signature=b'') V4CompatIdentityScheme.validate_enr_signature(enr)
def test_enr_signature_validation(): private_key = PrivateKey(b"\x11" * 32) unsigned_enr = UnsignedENR(0, { b"id": b"v4", b"secp256k1": private_key.public_key.to_compressed_bytes(), b"key1": b"value1", }) enr = unsigned_enr.to_signed_enr(private_key.to_bytes()) V4IdentityScheme.validate_enr_signature(enr) forged_enr = ENR(enr.sequence_number, dict(enr), b"\x00" * 64) with pytest.raises(ValidationError): V4IdentityScheme.validate_enr_signature(forged_enr)
def from_pubkey_and_addr(cls: Type[TNode], pubkey: datatypes.PublicKey, address: AddressAPI) -> TNode: enr = ENR(0, { IDENTITY_SCHEME_ENR_KEY: V4CompatIdentityScheme.id, V4CompatIdentityScheme.public_key_enr_key: pubkey.to_compressed_bytes(), IP_V4_ADDRESS_ENR_KEY: address.ip_packed, UDP_PORT_ENR_KEY: address.udp_port, TCP_PORT_ENR_KEY: address.tcp_port, }, signature=b'') return cls(enr)
def test_serialization_roundtrip(identity_scheme_registry): original_enr = ENR( sequence_number=0, kv_pairs={ b"id": b"mock", b"key2": b"value2", # wrong order so that serialization is forced to fix this b"key1": b"value1", }, signature=b"", identity_scheme_registry=identity_scheme_registry, ) encoded = rlp.encode(original_enr) recovered_enr = rlp.decode( encoded, ENR, identity_scheme_registry=identity_scheme_registry, ) assert recovered_enr == original_enr