Exemplo n.º 1
0
    def message(cls,
                *,
                nonce: Optional[Nonce] = None,
                initiator_key: Optional[AES128Key] = None,
                message: Optional[BaseMessage] = None,
                source_node_id: Optional[NodeID] = None,
                dest_node_id: Optional[NodeID] = None,
                protocol_id: bytes = PROTOCOL_ID) -> Packet[MessagePacket]:
        if nonce is None:
            nonce = Nonce(secrets.token_bytes(12))

        auth_data = MessagePacket(nonce)

        if message is None:
            message = RandomMessage()

        return cls._prepare(
            nonce=nonce,
            initiator_key=initiator_key,
            message=message,
            auth_data=auth_data,
            source_node_id=source_node_id,
            dest_node_id=dest_node_id,
            protocol_id=protocol_id,
        )
Exemplo n.º 2
0
def _decode_auth(encoded_packet: bytes) -> Tuple[Union[AuthHeader, Nonce], int]:
    try:
        decoded_auth, _, message_start_index = rlp.codec.consume_item(
            encoded_packet, TAG_SIZE
        )
    except DecodingError as error:
        raise ValidationError(
            "Packet authentication section is not proper RLP"
        ) from error

    if is_bytes(decoded_auth):
        validate_nonce(decoded_auth)
        return Nonce(decoded_auth), message_start_index
    elif is_list_like(decoded_auth):
        validate_length(decoded_auth, 5, "auth header")
        for index, element in enumerate(decoded_auth):
            if not is_bytes(element):
                raise ValidationError(
                    f"Element {index} in auth header is not bytes: {element}"
                )
        auth_header = AuthHeader(
            auth_tag=decoded_auth[0],
            id_nonce=decoded_auth[1],
            auth_scheme_name=decoded_auth[2],
            ephemeral_public_key=decoded_auth[3],
            encrypted_auth_response=decoded_auth[4],
        )
        validate_auth_header(auth_header)
        return auth_header, message_start_index
    else:
        raise Exception("unreachable: RLP can only encode bytes and lists")
Exemplo n.º 3
0
    def _prepare(*,
                 nonce: Optional[Nonce] = None,
                 initiator_key: Optional[AES128Key] = None,
                 message: BaseMessage,
                 auth_data: TAuthData,
                 source_node_id: Optional[NodeID] = None,
                 dest_node_id: Optional[NodeID] = None,
                 protocol_id: bytes = PROTOCOL_ID) -> Packet[TAuthData]:
        if nonce is None:
            nonce = Nonce(secrets.token_bytes(12))

        if initiator_key is None:
            initiator_key = AES128Key(secrets.token_bytes(16))

        if source_node_id is None:
            source_node_id = NodeID(secrets.token_bytes(32))

        if dest_node_id is None:
            dest_node_id = NodeID(secrets.token_bytes(32))

        return Packet.prepare(
            nonce=nonce,
            initiator_key=initiator_key,
            message=message,
            auth_data=auth_data,
            source_node_id=source_node_id,
            dest_node_id=dest_node_id,
            protocol_id=protocol_id,
        )
Exemplo n.º 4
0
 def from_wire_bytes(cls, data: bytes) -> "Header":
     if len(data) != HEADER_PACKET_SIZE:
         raise DecodingError(
             f"Invalid length for Header: actual={len(data)}  "
             f"expected={HEADER_PACKET_SIZE}  data={data.hex()}")
     stream = BytesIO(data)
     protocol_id = stream.read(6)
     if protocol_id != PROTOCOL_ID:
         raise DecodingError(f"Invalid protocol: {protocol_id!r}")
     version = stream.read(2)
     if version != b"\x00\x01":
         raise DecodingError(f"Unsupported version: {version!r}")
     flag = stream.read(1)[0]
     aes_gcm_nonce = Nonce(stream.read(12))
     auth_data_size = int.from_bytes(stream.read(2), "big")
     return cls(protocol_id, version, flag, aes_gcm_nonce, auth_data_size)
Exemplo n.º 5
0
def test_decryption_with_wrong_inputs():
    key = AES128Key(b"\x00" * 16)
    nonce = Nonce(b"\x11" * 12)
    plain_text = b"\x33" * 5
    aad = b"\x44" * 5
    cipher_text = aesgcm_encrypt(key, nonce, plain_text, aad)

    assert aesgcm_decrypt(key, nonce, cipher_text, aad) == plain_text
    with pytest.raises(ValidationError):
        aesgcm_decrypt(b"", nonce, cipher_text, aad)
    with pytest.raises(ValidationError):
        aesgcm_decrypt(key, b"", cipher_text, aad)
    with pytest.raises(DecryptionError):
        aesgcm_decrypt(key, nonce, b"", aad)
    with pytest.raises(DecryptionError):
        aesgcm_decrypt(key, nonce, cipher_text, b"")
Exemplo n.º 6
0
def _decode_who_are_you_payload(encoded_packet: bytes) -> Tuple[Nonce, IDNonce, int]:
    payload_rlp = encoded_packet[MAGIC_SIZE:]

    try:
        payload = rlp.decode(payload_rlp)
    except DecodingError as error:
        raise ValidationError(
            f"WHOAREYOU payload section is not proper RLP: {encode_hex(payload_rlp)}"
        ) from error

    if not is_list_like(payload):
        raise ValidationError(
            f"WHOAREYOU payload section is not an RLP encoded list: {payload}"
        )
    if len(payload) != 3:
        raise ValidationError(
            f"WHOAREYOU payload consists of {len(payload)} instead of 3 elements: {payload}"
        )

    token, id_nonce, enr_seq_bytes = payload
    enr_seq = big_endian_int.deserialize(enr_seq_bytes)
    validate_nonce(token)
    return Nonce(token), id_nonce, enr_seq
Exemplo n.º 7
0
def get_random_auth_tag() -> Nonce:
    return Nonce(secrets.token_bytes(NONCE_SIZE))
Exemplo n.º 8
0
 def get_encryption_nonce(self) -> Nonce:
     return Nonce(
         next(self._nonce_counter).to_bytes(4, "big") +
         secrets.token_bytes(8))
Exemplo n.º 9
0
    "enr:-LK4QKWk9yZo258PQouLshTOEEGWVHH7GhKwpYmB5tmKE4eHeSfman0PZvM2Rpp54RWgoOagAsOfKoXgZSbiCYzERWABh2F0dG5ldHOIAAAAAAAAAACEZXRoMpAAAAAAAAAAAAAAAAAAAAAAgmlkgnY0gmlwhDQlA5CJc2VjcDI1NmsxoQOYiWqrQtQksTEtS3qY6idxJE5wkm0t9wKqpzv2gCR21oN0Y3CCIyiDdWRwgiMo",  # noqa: E501
    "enr:-LK4QEnIS-PIxxLCadJdnp83VXuJqgKvC9ZTIWaJpWqdKlUFCiup2sHxWihF9EYGlMrQLs0mq_2IyarhNq38eoaOHUoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpAAAAAAAAAAAAAAAAAAAAAAgmlkgnY0gmlwhA37LMaJc2VjcDI1NmsxoQJ7k0mKtTd_kdEq251flOjD1HKpqgMmIETDoD-Msy_O-4N0Y3CCIyiDdWRwgiMo",  # noqa: E501
    "enr:-KG4QIOJRu0BBlcXJcn3lI34Ub1aBLYipbnDaxBnr2uf2q6nE1TWnKY5OAajg3eG6mHheQSfRhXLuy-a8V5rqXKSoUEChGV0aDKQGK5MywAAAAH__________4JpZIJ2NIJpcIQKAAFhiXNlY3AyNTZrMaEDESplmV9c2k73v0DjxVXJ6__2bWyP-tK28_80lf7dUhqDdGNwgiMog3VkcIIjKA",  # noqa: E501
    # CatDog: bridge bootnodes
    "enr:-Ku4QKYN_qSG6WnGMs33F4STy8canm2X7vLaz0MB6bA84YJ-GtT5CeUvkuYvMUX-mwuU3Ju14-2wZj7rjwx7eAthAL4Dh2F0dG5ldHOIAAAAAAAAAACEZXRoMpDaNQiCAAAAA___________gmlkgnY0gmlwhBK4vdCJc2VjcDI1NmsxoQNYtv_PfWUWNRo99-21Y4dXl5Z-XGalHp-bJmDHod4x14N1ZHCCI1o",  # noqa: E501
)

NONCE_SIZE = 12  # size of an AESGCM nonce
TAG_SIZE = 32  # size of the tag packet prefix
MAGIC_SIZE = 32  # size of the magic hash in the who are you packet
ID_NONCE_SIZE = 32  # size of the id nonce in who are you and auth tag packets
RANDOM_ENCRYPTED_DATA_SIZE = 12  # size of random data we send to initiate a handshake
# safe upper bound on the size of the ENR list in a nodes message
NODES_MESSAGE_PAYLOAD_SIZE = DISCOVERY_MAX_PACKET_SIZE - 200

ZERO_NONCE = Nonce(b"\x00" *
                   NONCE_SIZE)  # nonce used for the auth header packet
AUTH_RESPONSE_VERSION = 5  # version number used in auth response
AUTH_SCHEME_NAME = b"gcm"  # the name of the only supported authentication scheme

TOPIC_HASH_SIZE = 32  # size of a topic hash

WHO_ARE_YOU_MAGIC_SUFFIX = b"WHOAREYOU"

MAX_REQUEST_ID = 2**32 - 1  # highest request id used for outbound requests
MAX_REQUEST_ID_ATTEMPTS = (
    100  # number of attempts we take to guess a available request id
)

REQUEST_RESPONSE_TIMEOUT = (
    0.5  # timeout for waiting for response after request was sent
)
Exemplo n.º 10
0
def test_nonce_validation_valid(key):
    validate_nonce(Nonce(key))
Exemplo n.º 11
0
def test_nonce_validation_invalid():
    for length in (0, 11, 13, 16):
        with pytest.raises(ValidationError):
            validate_nonce(Nonce(b"\x00" * length))