Beispiel #1
0
def decoderlp(rlpdata):
    """Decode an RLP encoded object."""
    try:
        item, end = consume_item(rlpdata, 0)
    except IndexError:
        raise DecodingError('RLP string to short', rlpdata)
    return item
Beispiel #2
0
 def decode(self, data):
     # cmdid = rlp.peek(data, 0, sedes=t_int)  # cmdid is first element
     t, l, pos = consume_length_prefix(data, 0)
     cmdid = t_int.deserialize(consume_item(data[pos], 0)[0])
     cls = self.message_class_by_id[cmdid]
     print 'DECODING', cls
     return cls.decode(data)
Beispiel #3
0
def test_consume_item():
    obj = [b'f', b'bar', b'a' * 100, 105, [b'nested', b'list']]
    rlp = encode(obj)
    item, per_item_rlp, end = consume_item(rlp, 0)
    assert per_item_rlp == [
        (b'\xf8y'
         b'f' + b'\x83bar' + b'\xb8d' + b'a' * 100 + b'i' +
         b'\xcc\x86nested\x84list'), [b'f'], [b'\x83bar'],
        [b'\xb8d' + b'a' * 100], [b'i'],
        [b'\xcc\x86nested\x84list', [b'\x86nested'], [b'\x84list']]
    ]
    assert end == 123
    assert per_item_rlp[0] == rlp
Beispiel #4
0
def decode_all(rlp: bytes,
               sedes: rlp.Serializable = None,
               recursive_cache: bool = False,
               **kwargs: Any) -> Iterable[Any]:
    """Decode multiple RLP encoded object.

    If the deserialized result `obj` has an attribute :attr:`_cached_rlp` (e.g. if `sedes` is a
    subclass of :class:`rlp.Serializable`) it will be set to `rlp`, which will improve performance
    on subsequent :func:`rlp.encode` calls. Bear in mind however that `obj` needs to make sure that
    this value is updated whenever one of its fields changes or prevent such changes entirely
    (:class:`rlp.sedes.Serializable` does the latter).

    :param sedes: an object implementing a function ``deserialize(code)`` which will be applied
                  after decoding, or ``None`` if no deserialization should be performed
    :param **kwargs: additional keyword arguments that will be passed to the deserializer
    :param strict: if false inputs that are longer than necessary don't cause an exception
    :returns: the decoded and maybe deserialized Python object
    :raises: :exc:`rlp.DecodingError` if the input string does not end after the root item and
             `strict` is true
    :raises: :exc:`rlp.DeserializationError` if the deserialization fails
    """
    if not is_bytes(rlp):
        raise DecodingError(
            'Can only decode RLP bytes, got type %s' % type(rlp).__name__, rlp)

    end = 0
    rlp_length = len(rlp)

    while rlp_length - end > 0:
        try:
            item, per_item_rlp, end = consume_item(rlp, end)
        except IndexError:
            raise DecodingError('RLP string too short', rlp)
        if sedes:
            obj = sedes.deserialize(item, **kwargs)
            if is_sequence(obj) or hasattr(obj, '_cached_rlp'):
                _apply_rlp_cache(obj, per_item_rlp, recursive_cache)
            yield obj
        else:
            yield item
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)
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,
                                                     tv['receiver_nonce'],
                                                     responder.remote_token_found
                                                     )
    assert auth_ack_msg == tv['authresp_plaintext']
    auth_ack_msg_cipher = responder.encrypt_auth_ack_message(auth_ack_msg, 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('>I', '\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', sedes.big_endian_int),
        ('capabilities', sedes.CountableList(_sedes_capabilites_tuple)),
        ('listen_port', sedes.big_endian_int),
        ('nodeid', 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