Ejemplo n.º 1
0
async def get_directly_linked_peers_without_handshake(
        alice_factory: BasePeerFactory = None,
        bob_factory: BasePeerFactory = None) -> Tuple[BasePeer, BasePeer]:
    """
    See get_directly_linked_peers().

    Neither the P2P handshake nor the sub-protocol handshake will be performed here.
    """
    cancel_token = CancelToken("get_directly_linked_peers_without_handshake")

    if alice_factory is None:
        alice_factory = ParagonPeerFactory(
            privkey=ecies.generate_privkey(),
            context=ParagonContext(),
            token=cancel_token,
        )

    if bob_factory is None:
        bob_factory = ParagonPeerFactory(
            privkey=ecies.generate_privkey(),
            context=ParagonContext(),
            token=cancel_token,
        )

    alice_private_key = alice_factory.privkey
    bob_private_key = bob_factory.privkey

    alice_remote = kademlia.Node(bob_private_key.public_key,
                                 kademlia.Address('0.0.0.0', 0, 0))
    bob_remote = kademlia.Node(alice_private_key.public_key,
                               kademlia.Address('0.0.0.0', 0, 0))

    use_eip8 = False
    initiator = auth.HandshakeInitiator(alice_remote, alice_private_key,
                                        use_eip8, cancel_token)

    f_alice: 'asyncio.Future[BasePeer]' = asyncio.Future()
    handshake_finished = asyncio.Event()

    (
        (alice_reader, alice_writer),
        (bob_reader, bob_writer),
    ) = get_directly_connected_streams()

    async def do_handshake() -> None:
        aes_secret, mac_secret, egress_mac, ingress_mac = await auth._handshake(
            initiator, alice_reader, alice_writer, cancel_token)

        transport = Transport(
            remote=alice_remote,
            private_key=alice_factory.privkey,
            reader=alice_reader,
            writer=alice_writer,
            aes_secret=aes_secret,
            mac_secret=mac_secret,
            egress_mac=egress_mac,
            ingress_mac=ingress_mac,
        )
        alice = alice_factory.create_peer(transport)

        f_alice.set_result(alice)
        handshake_finished.set()

    asyncio.ensure_future(do_handshake())

    use_eip8 = False
    responder = auth.HandshakeResponder(bob_remote, bob_private_key, use_eip8,
                                        cancel_token)
    auth_cipher = await bob_reader.read(constants.ENCRYPTED_AUTH_MSG_LEN)

    initiator_ephemeral_pubkey, initiator_nonce, _ = decode_authentication(
        auth_cipher, bob_private_key)
    responder_nonce = keccak(os.urandom(constants.HASH_LEN))
    auth_ack_msg = responder.create_auth_ack_message(responder_nonce)
    auth_ack_ciphertext = responder.encrypt_auth_ack_message(auth_ack_msg)
    bob_writer.write(auth_ack_ciphertext)

    await handshake_finished.wait()
    alice = await f_alice

    aes_secret, mac_secret, egress_mac, ingress_mac = responder.derive_secrets(
        initiator_nonce, responder_nonce, initiator_ephemeral_pubkey,
        auth_cipher, auth_ack_ciphertext)
    assert egress_mac.digest() == alice.transport._ingress_mac.digest()
    assert ingress_mac.digest() == alice.transport._egress_mac.digest()
    transport = Transport(
        remote=bob_remote,
        private_key=bob_factory.privkey,
        reader=bob_reader,
        writer=bob_writer,
        aes_secret=aes_secret,
        mac_secret=mac_secret,
        egress_mac=egress_mac,
        ingress_mac=ingress_mac,
    )
    bob = bob_factory.create_peer(transport)

    return alice, bob
Ejemplo n.º 2
0
async def get_directly_linked_peers_without_handshake(peer1_class=LESPeer,
                                                      peer1_headerdb=None,
                                                      peer2_class=LESPeer,
                                                      peer2_headerdb=None):
    """See get_directly_linked_peers().

    Neither the P2P handshake nor the sub-protocol handshake will be performed here.
    """
    cancel_token = CancelToken("get_directly_linked_peers_without_handshake")
    if peer1_headerdb is None:
        peer1_headerdb = get_fresh_mainnet_headerdb()
    if peer2_headerdb is None:
        peer2_headerdb = get_fresh_mainnet_headerdb()
    peer1_private_key = ecies.generate_privkey()
    peer2_private_key = ecies.generate_privkey()
    peer1_remote = kademlia.Node(peer2_private_key.public_key,
                                 kademlia.Address('0.0.0.0', 0, 0))
    peer2_remote = kademlia.Node(peer1_private_key.public_key,
                                 kademlia.Address('0.0.0.0', 0, 0))
    initiator = auth.HandshakeInitiator(peer1_remote, peer1_private_key,
                                        cancel_token)
    peer2_reader = asyncio.StreamReader()
    peer1_reader = asyncio.StreamReader()
    # Link the peer1's writer to the peer2's reader, and the peer2's writer to the
    # peer1's reader.
    peer2_writer = type("mock-streamwriter", (object, ), {
        "write": peer1_reader.feed_data,
        "close": lambda: None
    })
    peer1_writer = type("mock-streamwriter", (object, ), {
        "write": peer2_reader.feed_data,
        "close": lambda: None
    })

    peer1, peer2 = None, None
    handshake_finished = asyncio.Event()

    async def do_handshake():
        nonlocal peer1
        aes_secret, mac_secret, egress_mac, ingress_mac = await auth._handshake(
            initiator, peer1_reader, peer1_writer, cancel_token)

        peer1 = peer1_class(remote=peer1_remote,
                            privkey=peer1_private_key,
                            reader=peer1_reader,
                            writer=peer1_writer,
                            aes_secret=aes_secret,
                            mac_secret=mac_secret,
                            egress_mac=egress_mac,
                            ingress_mac=ingress_mac,
                            headerdb=peer1_headerdb,
                            network_id=1)

        handshake_finished.set()

    asyncio.ensure_future(do_handshake())

    responder = auth.HandshakeResponder(peer2_remote, peer2_private_key,
                                        cancel_token)
    auth_cipher = await peer2_reader.read(constants.ENCRYPTED_AUTH_MSG_LEN)

    initiator_ephemeral_pubkey, initiator_nonce, _ = decode_authentication(
        auth_cipher, peer2_private_key)
    responder_nonce = keccak(os.urandom(constants.HASH_LEN))
    auth_ack_msg = responder.create_auth_ack_message(responder_nonce)
    auth_ack_ciphertext = responder.encrypt_auth_ack_message(auth_ack_msg)
    peer2_writer.write(auth_ack_ciphertext)

    await handshake_finished.wait()

    aes_secret, mac_secret, egress_mac, ingress_mac = responder.derive_secrets(
        initiator_nonce, responder_nonce, initiator_ephemeral_pubkey,
        auth_cipher, auth_ack_ciphertext)
    assert egress_mac.digest() == peer1.ingress_mac.digest()
    assert ingress_mac.digest() == peer1.egress_mac.digest()
    peer2 = peer2_class(remote=peer2_remote,
                        privkey=peer2_private_key,
                        reader=peer2_reader,
                        writer=peer2_writer,
                        aes_secret=aes_secret,
                        mac_secret=mac_secret,
                        egress_mac=egress_mac,
                        ingress_mac=ingress_mac,
                        headerdb=peer2_headerdb,
                        network_id=1)

    return peer1, peer2
Ejemplo n.º 3
0
async def get_directly_linked_peers_without_handshake(peer1_class=LESPeer,
                                                      peer1_chaindb=None,
                                                      peer2_class=LESPeer,
                                                      peer2_chaindb=None):
    """See get_directly_linked_peers().

    Neither the P2P handshake nor the sub-protocol handshake will be performed here.
    """
    if peer1_chaindb is None:
        peer1_chaindb = get_fresh_mainnet_chaindb()
    if peer2_chaindb is None:
        peer2_chaindb = get_fresh_mainnet_chaindb()
    peer1_private_key = ecies.generate_privkey()
    peer2_private_key = ecies.generate_privkey()
    peer1_remote = kademlia.Node(peer2_private_key.public_key,
                                 kademlia.Address('0.0.0.0', 0, 0))
    peer2_remote = kademlia.Node(peer1_private_key.public_key,
                                 kademlia.Address('0.0.0.0', 0, 0))
    initiator = auth.HandshakeInitiator(peer1_remote, peer1_private_key)
    peer2_reader = asyncio.StreamReader()
    peer1_reader = asyncio.StreamReader()
    # Link the peer1's writer to the peer2's reader, and the peer2's writer to the
    # peer1's reader.
    peer2_writer = type("mock-streamwriter", (object, ), {
        "write": peer1_reader.feed_data,
        "close": lambda: None
    })
    peer1_writer = type("mock-streamwriter", (object, ), {
        "write": peer2_reader.feed_data,
        "close": lambda: None
    })

    peer1, peer2 = None, None
    handshake_finished = asyncio.Event()

    async def do_handshake():
        nonlocal peer1, peer2
        aes_secret, mac_secret, egress_mac, ingress_mac = await auth._handshake(
            initiator, peer1_reader, peer1_writer)

        # Need to copy those before we pass them on to the Peer constructor because they're
        # mutable. Also, the 2nd peer's ingress/egress MACs are reversed from the first peer's.
        peer2_ingress = egress_mac.copy()
        peer2_egress = ingress_mac.copy()

        peer1 = peer1_class(remote=peer1_remote,
                            privkey=peer1_private_key,
                            reader=peer1_reader,
                            writer=peer1_writer,
                            aes_secret=aes_secret,
                            mac_secret=mac_secret,
                            egress_mac=egress_mac,
                            ingress_mac=ingress_mac,
                            chaindb=peer1_chaindb,
                            network_id=1)

        peer2 = peer2_class(remote=peer2_remote,
                            privkey=peer2_private_key,
                            reader=peer2_reader,
                            writer=peer2_writer,
                            aes_secret=aes_secret,
                            mac_secret=mac_secret,
                            egress_mac=peer2_egress,
                            ingress_mac=peer2_ingress,
                            chaindb=peer2_chaindb,
                            network_id=1)

        handshake_finished.set()

    asyncio.ensure_future(do_handshake())

    responder = auth.HandshakeResponder(peer2_remote, peer2_private_key)
    auth_msg = await peer2_reader.read(constants.ENCRYPTED_AUTH_MSG_LEN)

    # Can't assert return values, but checking that the decoder doesn't raise
    # any exceptions at least.
    _, _ = responder.decode_authentication(auth_msg)

    peer2_nonce = keccak(os.urandom(constants.HASH_LEN))
    auth_ack_msg = responder.create_auth_ack_message(peer2_nonce)
    auth_ack_ciphertext = responder.encrypt_auth_ack_message(auth_ack_msg)
    peer2_writer.write(auth_ack_ciphertext)

    await handshake_finished.wait()

    return peer1, peer2