From d50e1b6872daeba07f5b540d285e0ab510be5bc1 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 2 Aug 2019 14:49:54 -0700 Subject: [PATCH 01/18] Use direct types over indirect types --- libp2p/__init__.py | 2 +- libp2p/security/secure_conn_interface.py | 3 +-- libp2p/security/secure_transport_interface.py | 3 +-- libp2p/security/security_multistream.py | 5 ++--- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/libp2p/__init__.py b/libp2p/__init__.py index af72cb81..391897f3 100644 --- a/libp2p/__init__.py +++ b/libp2p/__init__.py @@ -12,7 +12,7 @@ from libp2p.peer.peerstore import PeerStore from libp2p.peer.peerstore_interface import IPeerStore from libp2p.routing.interfaces import IPeerRouting from libp2p.routing.kademlia.kademlia_peer_router import KadmeliaPeerRouter -from libp2p.security.insecure_security import InsecureTransport +from libp2p.security.insecure.transport import InsecureTransport from libp2p.security.secure_transport_interface import ISecureTransport from libp2p.transport.tcp.tcp import TCP from libp2p.transport.upgrader import TransportUpgrader diff --git a/libp2p/security/secure_conn_interface.py b/libp2p/security/secure_conn_interface.py index 46bb83c1..67d8706e 100644 --- a/libp2p/security/secure_conn_interface.py +++ b/libp2p/security/secure_conn_interface.py @@ -1,8 +1,7 @@ from abc import ABC, abstractmethod from libp2p.network.connection.raw_connection_interface import IRawConnection - -from .typing import TSecurityDetails +from libp2p.security.typing import TSecurityDetails """ diff --git a/libp2p/security/secure_transport_interface.py b/libp2p/security/secure_transport_interface.py index bf6dfd31..3b3e6256 100644 --- a/libp2p/security/secure_transport_interface.py +++ b/libp2p/security/secure_transport_interface.py @@ -2,8 +2,7 @@ from abc import ABC, abstractmethod from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.peer.id import ID - -from .secure_conn_interface import ISecureConn +from libp2p.security.secure_conn_interface import ISecureConn """ diff --git a/libp2p/security/security_multistream.py b/libp2p/security/security_multistream.py index b2fd2bde..5a4cca6a 100644 --- a/libp2p/security/security_multistream.py +++ b/libp2p/security/security_multistream.py @@ -5,11 +5,10 @@ from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.peer.id import ID from libp2p.protocol_muxer.multiselect import Multiselect from libp2p.protocol_muxer.multiselect_client import MultiselectClient +from libp2p.security.secure_conn_interface import ISecureConn +from libp2p.security.secure_transport_interface import ISecureTransport from libp2p.typing import TProtocol -from .secure_conn_interface import ISecureConn -from .secure_transport_interface import ISecureTransport - """ Represents a secured connection object, which includes a connection and details about the security From b98025c3791f409b088187c010086db641199351 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 2 Aug 2019 14:50:20 -0700 Subject: [PATCH 02/18] Move security transports into their respective sub-packages --- .../{insecure_security.py => insecure/transport.py} | 3 +-- libp2p/security/secio/__init__.py | 0 .../security/{simple_security.py => simple/transport.py} | 3 +-- tests/security/test_security_multistream.py | 9 ++++----- 4 files changed, 6 insertions(+), 9 deletions(-) rename libp2p/security/{insecure_security.py => insecure/transport.py} (97%) create mode 100644 libp2p/security/secio/__init__.py rename libp2p/security/{simple_security.py => simple/transport.py} (98%) diff --git a/libp2p/security/insecure_security.py b/libp2p/security/insecure/transport.py similarity index 97% rename from libp2p/security/insecure_security.py rename to libp2p/security/insecure/transport.py index ce3f018b..7e1b77e5 100644 --- a/libp2p/security/insecure_security.py +++ b/libp2p/security/insecure/transport.py @@ -4,8 +4,7 @@ from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.peer.id import ID from libp2p.security.secure_conn_interface import ISecureConn from libp2p.security.secure_transport_interface import ISecureTransport - -from .typing import TSecurityDetails +from libp2p.security.typing import TSecurityDetails class InsecureTransport(ISecureTransport): diff --git a/libp2p/security/secio/__init__.py b/libp2p/security/secio/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/libp2p/security/simple_security.py b/libp2p/security/simple/transport.py similarity index 98% rename from libp2p/security/simple_security.py rename to libp2p/security/simple/transport.py index 4fb0a3cf..8860ab57 100644 --- a/libp2p/security/simple_security.py +++ b/libp2p/security/simple/transport.py @@ -5,8 +5,7 @@ from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.peer.id import ID from libp2p.security.secure_conn_interface import ISecureConn from libp2p.security.secure_transport_interface import ISecureTransport - -from .typing import TSecurityDetails +from libp2p.security.typing import TSecurityDetails class SimpleSecurityTransport(ISecureTransport): diff --git a/tests/security/test_security_multistream.py b/tests/security/test_security_multistream.py index 070f29dd..6abf534a 100644 --- a/tests/security/test_security_multistream.py +++ b/tests/security/test_security_multistream.py @@ -1,13 +1,12 @@ import asyncio -import multiaddr -import pytest - from libp2p import new_node from libp2p.peer.peerinfo import info_from_p2p_addr from libp2p.protocol_muxer.multiselect_client import MultiselectClientError -from libp2p.security.insecure_security import InsecureTransport -from libp2p.security.simple_security import SimpleSecurityTransport +from libp2p.security.insecure.transport import InsecureTransport +from libp2p.security.simple.transport import SimpleSecurityTransport +import multiaddr +import pytest from tests.utils import cleanup, connect # TODO: Add tests for multiple streams being opened on different From ab7653526f7399607ff4f5558675821c2651ae1a Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 2 Aug 2019 16:02:07 -0700 Subject: [PATCH 03/18] Code cleanup / formatting --- libp2p/peer/id.py | 1 - libp2p/security/security_multistream.py | 17 ----------------- libp2p/transport/upgrader.py | 2 -- 3 files changed, 20 deletions(-) diff --git a/libp2p/peer/id.py b/libp2p/peer/id.py index bfb78d0e..26029b62 100644 --- a/libp2p/peer/id.py +++ b/libp2p/peer/id.py @@ -15,7 +15,6 @@ def _serialize_public_key(key: PublicKey) -> bytes: class ID: - _bytes: bytes _xor_id: int = None _b58_str: str = None diff --git a/libp2p/security/security_multistream.py b/libp2p/security/security_multistream.py index 5a4cca6a..9f25fab4 100644 --- a/libp2p/security/security_multistream.py +++ b/libp2p/security/security_multistream.py @@ -24,20 +24,13 @@ class SecurityMultistream(ABC): multiselect_client: MultiselectClient def __init__(self) -> None: - # Map protocol to secure transport self.transports = {} - - # Create multiselect self.multiselect = Multiselect() - - # Create multiselect client self.multiselect_client = MultiselectClient() def add_transport(self, protocol: TProtocol, transport: ISecureTransport) -> None: - # Associate protocol with transport self.transports[protocol] = transport - # Add protocol and handler to multiselect # Note: None is added as the handler for the given protocol since # we only care about selecting the protocol, not any handler function self.multiselect.add_handler(protocol, None) @@ -48,13 +41,8 @@ class SecurityMultistream(ABC): for an inbound connection (i.e. we are not the initiator) :return: secure connection object (that implements secure_conn_interface) """ - - # Select a secure transport transport = await self.select_transport(conn, False) - - # Create secured connection secure_conn = await transport.secure_inbound(conn) - return secure_conn async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn: @@ -63,13 +51,8 @@ class SecurityMultistream(ABC): for an inbound connection (i.e. we are the initiator) :return: secure connection object (that implements secure_conn_interface) """ - - # Select a secure transport transport = await self.select_transport(conn, True) - - # Create secured connection secure_conn = await transport.secure_outbound(conn, peer_id) - return secure_conn async def select_transport( diff --git a/libp2p/transport/upgrader.py b/libp2p/transport/upgrader.py index 28d4a51b..2aac45ef 100644 --- a/libp2p/transport/upgrader.py +++ b/libp2p/transport/upgrader.py @@ -54,7 +54,5 @@ class TransportUpgrader: """ Upgrade raw connection to muxed connection """ - - # For PoC, no security, default to mplex # TODO do exchange to determine multiplexer return Mplex(conn, generic_protocol_handler, peer_id) From 1e5357a1e16f07b9b8f4806d7bda17da00c5f424 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 2 Aug 2019 16:04:46 -0700 Subject: [PATCH 04/18] Update the `ISecureConn` interface following the reference and simplify accordingly --- libp2p/__init__.py | 6 ++-- libp2p/security/insecure/transport.py | 36 ++---------------------- libp2p/security/secure_conn_interface.py | 28 +++++++++++------- libp2p/security/security_multistream.py | 5 +++- libp2p/security/simple/transport.py | 31 ++------------------ libp2p/stream_muxer/mplex/mplex.py | 24 +++++++--------- libp2p/transport/upgrader.py | 13 ++++----- 7 files changed, 45 insertions(+), 98 deletions(-) diff --git a/libp2p/__init__.py b/libp2p/__init__.py index 391897f3..11fa2a9f 100644 --- a/libp2p/__init__.py +++ b/libp2p/__init__.py @@ -92,8 +92,10 @@ def initialize_default_swarm( # TODO TransportUpgrader is not doing anything really # TODO parse muxer and sec to pass into TransportUpgrader muxer = muxer_opt or ["mplex/6.7.0"] - sec = sec_opt or {TProtocol("insecure/1.0.0"): InsecureTransport("insecure")} - upgrader = TransportUpgrader(sec, muxer) + security_transports_by_protocol = sec_opt or { + TProtocol("insecure/1.0.0"): InsecureTransport() + } + upgrader = TransportUpgrader(security_transports_by_protocol, muxer) peerstore = peerstore_opt or PeerStore() # TODO: Initialize discovery if not presented diff --git a/libp2p/security/insecure/transport.py b/libp2p/security/insecure/transport.py index 7e1b77e5..4ec378b8 100644 --- a/libp2p/security/insecure/transport.py +++ b/libp2p/security/insecure/transport.py @@ -1,10 +1,7 @@ -from typing import cast - from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.peer.id import ID from libp2p.security.secure_conn_interface import ISecureConn from libp2p.security.secure_transport_interface import ISecureTransport -from libp2p.security.typing import TSecurityDetails class InsecureTransport(ISecureTransport): @@ -13,19 +10,13 @@ class InsecureTransport(ISecureTransport): i.e. the upgraded transport does not add any additional security. """ - transport_id: str - - def __init__(self, transport_id: str) -> None: - self.transport_id = transport_id - async def secure_inbound(self, conn: IRawConnection) -> ISecureConn: """ Secure the connection, either locally or by communicating with opposing node via conn, for an inbound connection (i.e. we are not the initiator) :return: secure connection object (that implements secure_conn_interface) """ - insecure_conn = InsecureConn(conn, self.transport_id) - return insecure_conn + return conn async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn: """ @@ -33,27 +24,4 @@ class InsecureTransport(ISecureTransport): for an inbound connection (i.e. we are the initiator) :return: secure connection object (that implements secure_conn_interface) """ - insecure_conn = InsecureConn(conn, self.transport_id) - return insecure_conn - - -class InsecureConn(ISecureConn): - conn: IRawConnection - details: TSecurityDetails - - def __init__(self, conn: IRawConnection, conn_id: str) -> None: - self.conn = conn - self.details = cast(TSecurityDetails, {}) - self.details["id"] = conn_id - - def get_conn(self) -> IRawConnection: - """ - :return: connection object that has been made secure - """ - return self.conn - - def get_security_details(self) -> TSecurityDetails: - """ - :return: map containing details about the connections security - """ - return self.details + return conn diff --git a/libp2p/security/secure_conn_interface.py b/libp2p/security/secure_conn_interface.py index 67d8706e..7b88e802 100644 --- a/libp2p/security/secure_conn_interface.py +++ b/libp2p/security/secure_conn_interface.py @@ -1,7 +1,7 @@ from abc import ABC, abstractmethod +from libp2p.peer.id import ID from libp2p.network.connection.raw_connection_interface import IRawConnection -from libp2p.security.typing import TSecurityDetails """ @@ -12,15 +12,23 @@ Relevant go repo: https://github.com/libp2p/go-conn-security/blob/master/interfa """ -class ISecureConn(ABC): +class AbstractSecureConn(ABC): @abstractmethod - def get_conn(self) -> IRawConnection: - """ - :return: the underlying raw connection - """ + def get_local_peer(self) -> ID: + pass @abstractmethod - def get_security_details(self) -> TSecurityDetails: - """ - :return: map containing details about the connections security - """ + def get_local_private_key(self) -> bytes: + pass + + @abstractmethod + def get_remote_peer(self) -> ID: + pass + + @abstractmethod + def get_remote_public_key(self) -> bytes: + pass + + +class ISecureConn(AbstractSecureConn, IRawConnection): + pass diff --git a/libp2p/security/security_multistream.py b/libp2p/security/security_multistream.py index 9f25fab4..43c5dbf3 100644 --- a/libp2p/security/security_multistream.py +++ b/libp2p/security/security_multistream.py @@ -23,11 +23,14 @@ class SecurityMultistream(ABC): multiselect: Multiselect multiselect_client: MultiselectClient - def __init__(self) -> None: + def __init__(self, secure_transports_by_protocol) -> None: self.transports = {} self.multiselect = Multiselect() self.multiselect_client = MultiselectClient() + for protocol, transport in secure_transports_by_protocol.items(): + self.add_transport(protocol, transport) + def add_transport(self, protocol: TProtocol, transport: ISecureTransport) -> None: self.transports[protocol] = transport diff --git a/libp2p/security/simple/transport.py b/libp2p/security/simple/transport.py index 8860ab57..87883998 100644 --- a/libp2p/security/simple/transport.py +++ b/libp2p/security/simple/transport.py @@ -1,11 +1,9 @@ import asyncio -from typing import cast from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.peer.id import ID from libp2p.security.secure_conn_interface import ISecureConn from libp2p.security.secure_transport_interface import ISecureTransport -from libp2p.security.typing import TSecurityDetails class SimpleSecurityTransport(ISecureTransport): @@ -28,8 +26,7 @@ class SimpleSecurityTransport(ISecureTransport): "Key phrase differed between nodes. Expected " + self.key_phrase ) - secure_conn = SimpleSecureConn(conn, self.key_phrase) - return secure_conn + return conn async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn: """ @@ -49,28 +46,4 @@ class SimpleSecurityTransport(ISecureTransport): "Key phrase differed between nodes. Expected " + self.key_phrase ) - secure_conn = SimpleSecureConn(conn, self.key_phrase) - return secure_conn - - -class SimpleSecureConn(ISecureConn): - conn: IRawConnection - key_phrase: str - details: TSecurityDetails - - def __init__(self, conn: IRawConnection, key_phrase: str) -> None: - self.conn = conn - self.details = cast(TSecurityDetails, {}) - self.details["key_phrase"] = key_phrase - - def get_conn(self) -> IRawConnection: - """ - :return: connection object that has been made secure - """ - return self.conn - - def get_security_details(self) -> TSecurityDetails: - """ - :return: map containing details about the connections security - """ - return self.details + return conn diff --git a/libp2p/stream_muxer/mplex/mplex.py b/libp2p/stream_muxer/mplex/mplex.py index 16d36134..60db1d2d 100644 --- a/libp2p/stream_muxer/mplex/mplex.py +++ b/libp2p/stream_muxer/mplex/mplex.py @@ -1,13 +1,12 @@ import asyncio from typing import Dict, Tuple -from multiaddr import Multiaddr - from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.network.typing import GenericProtocolHandlerFn from libp2p.peer.id import ID from libp2p.security.secure_conn_interface import ISecureConn from libp2p.stream_muxer.abc import IMuxedConn, IMuxedStream +from multiaddr import Multiaddr from .constants import HeaderTags from .mplex_stream import MplexStream @@ -39,11 +38,8 @@ class Mplex(IMuxedConn): for new muxed streams :param peer_id: peer_id of peer the connection is to """ - super().__init__(secured_conn, generic_protocol_handler, peer_id) - - self.secured_conn = secured_conn - self.raw_conn = secured_conn.get_conn() - self.initiator = self.raw_conn.initiator + self.conn = secured_conn + self.initiator = self.conn.initiator # Store generic protocol handler self.generic_protocol_handler = generic_protocol_handler @@ -63,7 +59,7 @@ class Mplex(IMuxedConn): """ close the stream muxer and underlying raw connection """ - self.raw_conn.close() + self.conn.close() def is_closed(self) -> bool: """ @@ -99,7 +95,7 @@ class Mplex(IMuxedConn): :param multi_addr: multi_addr that stream connects to :return: a new stream """ - stream_id = self.raw_conn.next_stream_id() + stream_id = self.conn.next_stream_id() stream = MplexStream(stream_id, multi_addr, self) self.buffers[stream_id] = asyncio.Queue() await self.send_message(HeaderTags.NewStream, None, stream_id) @@ -139,8 +135,8 @@ class Mplex(IMuxedConn): :param _bytes: byte array to write :return: length written """ - self.raw_conn.writer.write(_bytes) - await self.raw_conn.writer.drain() + self.conn.writer.write(_bytes) + await self.conn.writer.drain() return len(_bytes) async def handle_incoming(self) -> None: @@ -177,10 +173,10 @@ class Mplex(IMuxedConn): # loop in handle_incoming timeout = 0.1 try: - header = await decode_uvarint_from_stream(self.raw_conn.reader, timeout) - length = await decode_uvarint_from_stream(self.raw_conn.reader, timeout) + header = await decode_uvarint_from_stream(self.conn.reader, timeout) + length = await decode_uvarint_from_stream(self.conn.reader, timeout) message = await asyncio.wait_for( - self.raw_conn.reader.read(length), timeout=timeout + self.conn.reader.read(length), timeout=timeout ) except asyncio.TimeoutError: return None, None, None diff --git a/libp2p/transport/upgrader.py b/libp2p/transport/upgrader.py index 2aac45ef..f727767c 100644 --- a/libp2p/transport/upgrader.py +++ b/libp2p/transport/upgrader.py @@ -18,14 +18,11 @@ class TransportUpgrader: muxer: Sequence[str] def __init__( - self, secOpt: Mapping[TProtocol, ISecureTransport], muxerOpt: Sequence[str] - ) -> None: - # Store security option - self.security_multistream = SecurityMultistream() - for key in secOpt: - self.security_multistream.add_transport(key, secOpt[key]) - - # Store muxer option + self, + secure_transports_by_protocol: Mapping[TProtocol, ISecureTransport], + muxerOpt: Sequence[str], + ): + self.security_multistream = SecurityMultistream(secure_transports_by_protocol) self.muxer = muxerOpt def upgrade_listener(self, transport: ITransport, listeners: IListener) -> None: From fb437286615e5ecf718136c7b4882848075f7b01 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 2 Aug 2019 16:48:43 -0700 Subject: [PATCH 05/18] Mark some slow tests as such --- tests/pubsub/test_dummyaccount_demo.py | 1 + tests/pubsub/test_floodsub.py | 1 + tests/pubsub/test_gossipsub.py | 1 + tests/pubsub/test_gossipsub_backward_compatibility.py | 1 + 4 files changed, 4 insertions(+) diff --git a/tests/pubsub/test_dummyaccount_demo.py b/tests/pubsub/test_dummyaccount_demo.py index 6a604e54..b365134f 100644 --- a/tests/pubsub/test_dummyaccount_demo.py +++ b/tests/pubsub/test_dummyaccount_demo.py @@ -189,6 +189,7 @@ async def test_set_then_send_from_diff_nodes_five_nodes_ring_topography(): @pytest.mark.asyncio +@pytest.mark.slow async def test_set_then_send_from_five_diff_nodes_five_nodes_ring_topography(): num_nodes = 5 adj_map = {0: [1], 1: [2], 2: [3], 3: [4], 4: [0]} diff --git a/tests/pubsub/test_floodsub.py b/tests/pubsub/test_floodsub.py index c6599293..0a67c654 100644 --- a/tests/pubsub/test_floodsub.py +++ b/tests/pubsub/test_floodsub.py @@ -87,5 +87,6 @@ async def test_lru_cache_two_nodes(pubsubs_fsub, monkeypatch): @pytest.mark.parametrize("test_case_obj", floodsub_protocol_pytest_params) @pytest.mark.asyncio +@pytest.mark.slow async def test_gossipsub_run_with_floodsub_tests(test_case_obj): await perform_test_from_obj(test_case_obj, FloodsubFactory) diff --git a/tests/pubsub/test_gossipsub.py b/tests/pubsub/test_gossipsub.py index 83ab7868..e091f669 100644 --- a/tests/pubsub/test_gossipsub.py +++ b/tests/pubsub/test_gossipsub.py @@ -268,6 +268,7 @@ async def test_fanout(hosts, pubsubs_gsub): @pytest.mark.parametrize("num_hosts", (10,)) @pytest.mark.asyncio +@pytest.mark.slow async def test_fanout_maintenance(hosts, pubsubs_gsub): num_msgs = 5 diff --git a/tests/pubsub/test_gossipsub_backward_compatibility.py b/tests/pubsub/test_gossipsub_backward_compatibility.py index 05b6c402..e76ce049 100644 --- a/tests/pubsub/test_gossipsub_backward_compatibility.py +++ b/tests/pubsub/test_gossipsub_backward_compatibility.py @@ -17,6 +17,7 @@ async def test_gossipsub_initialize_with_floodsub_protocol(): @pytest.mark.parametrize("test_case_obj", floodsub_protocol_pytest_params) @pytest.mark.asyncio +@pytest.mark.slow async def test_gossipsub_run_with_floodsub_tests(test_case_obj): await perform_test_from_obj( test_case_obj, From 879cbf1abd57186370ae44b88f40994a49ccd958 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 2 Aug 2019 16:50:44 -0700 Subject: [PATCH 06/18] Add an "insecure session" that satisfies the `ISecureConn` interface --- libp2p/security/base_session.py | 32 +++++++++++++++++++++++++++ libp2p/security/base_transport.py | 13 +++++++++++ libp2p/security/insecure/transport.py | 22 ++++++++++++++---- 3 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 libp2p/security/base_session.py create mode 100644 libp2p/security/base_transport.py diff --git a/libp2p/security/base_session.py b/libp2p/security/base_session.py new file mode 100644 index 00000000..3cfd0190 --- /dev/null +++ b/libp2p/security/base_session.py @@ -0,0 +1,32 @@ +from libp2p.network.connection.raw_connection_interface import IRawConnection +from libp2p.peer.id import ID +from libp2p.security.base_transport import BaseSecureTransport +from libp2p.security.secure_conn_interface import ISecureConn + + +class BaseSession(ISecureConn, IRawConnection): + """ + ``BaseSession`` is not fully instantiated from its abstract classes as it + is only meant to be used in clases that derive from it. + """ + + def __init__( + self, transport: BaseSecureTransport, conn: IRawConnection, peer_id: ID + ) -> None: + self.local_peer = self.transport.local_peer + self.local_private_key = self.transport.local_private_key + self.insecure_conn = conn + self.remote_peer_id = peer_id + self.remote_permanent_pubkey = b"" + + def get_local_peer(self) -> ID: + return self.local_peer + + def get_local_private_key(self) -> bytes: + return self.local_private_key + + def get_remote_peer(self) -> ID: + return self.remote_peer_id + + def get_remote_public_key(self) -> bytes: + return self.remote_permanent_pubkey diff --git a/libp2p/security/base_transport.py b/libp2p/security/base_transport.py new file mode 100644 index 00000000..65c9757a --- /dev/null +++ b/libp2p/security/base_transport.py @@ -0,0 +1,13 @@ +from libp2p.peer.id import ID +from libp2p.security.secure_transport_interface import ISecureTransport + + +class BaseSecureTransport(ISecureTransport): + """ + ``BaseSecureTransport`` is not fully instantiated from its abstract classes as it + is only meant to be used in clases that derive from it. + """ + + def __init__(self, local_private_key: bytes) -> None: + self.local_private_key = local_private_key + self.local_peer = ID.from_privkey(local_private_key) diff --git a/libp2p/security/insecure/transport.py b/libp2p/security/insecure/transport.py index 4ec378b8..262b61a8 100644 --- a/libp2p/security/insecure/transport.py +++ b/libp2p/security/insecure/transport.py @@ -1,10 +1,24 @@ from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.peer.id import ID +from libp2p.security.base_session import BaseSession +from libp2p.security.base_transport import BaseSecureTransport from libp2p.security.secure_conn_interface import ISecureConn -from libp2p.security.secure_transport_interface import ISecureTransport -class InsecureTransport(ISecureTransport): +class InsecureSession(BaseSession): + def __init__( + self, transport: BaseSecureTransport, conn: IRawConnection, peer_id: ID + ) -> None: + super(InsecureSession, self).__init__(transport, conn, peer_id) + + async def write(self, data: bytes) -> None: + await self.insecure_conn.write(data) + + async def read(self) -> bytes: + return await self.insecure_conn.read() + + +class InsecureTransport(BaseSecureTransport): """ ``InsecureTransport`` provides the "identity" upgrader for a ``IRawConnection``, i.e. the upgraded transport does not add any additional security. @@ -16,7 +30,7 @@ class InsecureTransport(ISecureTransport): for an inbound connection (i.e. we are not the initiator) :return: secure connection object (that implements secure_conn_interface) """ - return conn + return InsecureSession(self, conn, ID(b"")) async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn: """ @@ -24,4 +38,4 @@ class InsecureTransport(ISecureTransport): for an inbound connection (i.e. we are the initiator) :return: secure connection object (that implements secure_conn_interface) """ - return conn + return InsecureSession(self, conn, peer_id) From 02e073d85a14fa274e393b386adbb69e873de0ef Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 2 Aug 2019 17:39:19 -0700 Subject: [PATCH 07/18] Keep the host's private key for use in transports --- libp2p/__init__.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/libp2p/__init__.py b/libp2p/__init__.py index 11fa2a9f..68b65e61 100644 --- a/libp2p/__init__.py +++ b/libp2p/__init__.py @@ -1,6 +1,7 @@ import asyncio from typing import Mapping, Sequence +from libp2p.crypto.keys import KeyPair from libp2p.crypto.rsa import create_new_key_pair from libp2p.host.basic_host import BasicHost from libp2p.kademlia.network import KademliaServer @@ -33,11 +34,15 @@ async def cleanup_done_tasks() -> None: await asyncio.sleep(3) -def generate_peer_id_from_rsa_identity() -> ID: - new_key_pair = create_new_key_pair() - new_public_key = new_key_pair.public_key - new_id = ID.from_pubkey(new_public_key) - return new_id +def generate_new_rsa_identity() -> KeyPair: + return create_new_key_pair() + + +def generate_peer_id_from_rsa_identity(key_pair=None) -> ID: + if not key_pair: + key_pair = generate_new_rsa_identity() + public_key = key_pair.public_key + return ID.from_pubkey(public_key) def initialize_default_kademlia_router( @@ -64,6 +69,7 @@ def initialize_default_kademlia_router( def initialize_default_swarm( + private_key: bytes, id_opt: ID = None, transport_opt: Sequence[str] = None, muxer_opt: Sequence[str] = None, @@ -92,8 +98,9 @@ def initialize_default_swarm( # TODO TransportUpgrader is not doing anything really # TODO parse muxer and sec to pass into TransportUpgrader muxer = muxer_opt or ["mplex/6.7.0"] + private_key_bytes = private_key.export_key("DER") security_transports_by_protocol = sec_opt or { - TProtocol("insecure/1.0.0"): InsecureTransport() + TProtocol("insecure/1.0.0"): InsecureTransport(private_key_bytes) } upgrader = TransportUpgrader(security_transports_by_protocol, muxer) @@ -105,6 +112,7 @@ def initialize_default_swarm( async def new_node( + private_key=None, swarm_opt: INetwork = None, id_opt: ID = None, transport_opt: Sequence[str] = None, @@ -125,11 +133,16 @@ async def new_node( :return: return a host instance """ + if not private_key: + key_pair = generate_new_rsa_identity() + private_key = key_pair.private_key + if not id_opt: - id_opt = generate_peer_id_from_rsa_identity() + id_opt = generate_peer_id_from_rsa_identity(key_pair) if not swarm_opt: swarm_opt = initialize_default_swarm( + private_key=private_key, id_opt=id_opt, transport_opt=transport_opt, muxer_opt=muxer_opt, From 0ebc8ffb21a80b54fbde098ec47e73f648a21933 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 2 Aug 2019 17:41:29 -0700 Subject: [PATCH 08/18] Wire some missing properties up --- libp2p/security/base_session.py | 13 +++++++++++-- libp2p/security/simple/transport.py | 19 +++++++++++++++---- libp2p/stream_muxer/mplex/mplex.py | 2 +- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/libp2p/security/base_session.py b/libp2p/security/base_session.py index 3cfd0190..5b23ba64 100644 --- a/libp2p/security/base_session.py +++ b/libp2p/security/base_session.py @@ -13,12 +13,21 @@ class BaseSession(ISecureConn, IRawConnection): def __init__( self, transport: BaseSecureTransport, conn: IRawConnection, peer_id: ID ) -> None: - self.local_peer = self.transport.local_peer - self.local_private_key = self.transport.local_private_key + self.local_peer = transport.local_peer + self.local_private_key = transport.local_private_key self.insecure_conn = conn self.remote_peer_id = peer_id self.remote_permanent_pubkey = b"" + # TODO clean up how this is passed around? + @property + def initiator(self) -> bool: + return self.insecure_conn.initiator + + # TODO clean up how this is passed around? + def next_stream_id(self) -> int: + return self.insecure_conn.next_stream_id() + def get_local_peer(self) -> ID: return self.local_peer diff --git a/libp2p/security/simple/transport.py b/libp2p/security/simple/transport.py index 87883998..8a9c6dbb 100644 --- a/libp2p/security/simple/transport.py +++ b/libp2p/security/simple/transport.py @@ -2,11 +2,12 @@ import asyncio from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.peer.id import ID +from libp2p.security.base_transport import BaseSecureTransport +from libp2p.security.insecure.transport import InsecureSession from libp2p.security.secure_conn_interface import ISecureConn -from libp2p.security.secure_transport_interface import ISecureTransport -class SimpleSecurityTransport(ISecureTransport): +class SimpleSecurityTransport(BaseSecureTransport): key_phrase: str def __init__(self, key_phrase: str) -> None: @@ -26,7 +27,12 @@ class SimpleSecurityTransport(ISecureTransport): "Key phrase differed between nodes. Expected " + self.key_phrase ) - return conn + session = InsecureSession(self, conn, ID(b"")) + # NOTE: this is abusing the abstraction we have here + # but this code may be deprecated soon and this exists + # mainly to satisfy a test that will go along w/ it + session.key_phrase = self.key_phrase + return session async def secure_outbound(self, conn: IRawConnection, peer_id: ID) -> ISecureConn: """ @@ -46,4 +52,9 @@ class SimpleSecurityTransport(ISecureTransport): "Key phrase differed between nodes. Expected " + self.key_phrase ) - return conn + session = InsecureSession(self, conn, peer_id) + # NOTE: this is abusing the abstraction we have here + # but this code may be deprecated soon and this exists + # mainly to satisfy a test that will go along w/ it + session.key_phrase = self.key_phrase + return session diff --git a/libp2p/stream_muxer/mplex/mplex.py b/libp2p/stream_muxer/mplex/mplex.py index 60db1d2d..00dc25c3 100644 --- a/libp2p/stream_muxer/mplex/mplex.py +++ b/libp2p/stream_muxer/mplex/mplex.py @@ -39,7 +39,7 @@ class Mplex(IMuxedConn): :param peer_id: peer_id of peer the connection is to """ self.conn = secured_conn - self.initiator = self.conn.initiator + self.initiator = secured_conn.initiator # Store generic protocol handler self.generic_protocol_handler = generic_protocol_handler From 20dd7d777a89d1bc3f654682efc5f92a8a486d79 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 2 Aug 2019 18:00:41 -0700 Subject: [PATCH 09/18] More efficiently remove trailing newline from message --- libp2p/network/connection/raw_connection.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libp2p/network/connection/raw_connection.py b/libp2p/network/connection/raw_connection.py index abde0066..3d12f0d5 100644 --- a/libp2p/network/connection/raw_connection.py +++ b/libp2p/network/connection/raw_connection.py @@ -34,11 +34,7 @@ class RawConnection(IRawConnection): async def read(self) -> bytes: line = await self.reader.readline() - adjusted_line = line.decode().rstrip("\n") - - # TODO: figure out a way to remove \n without going back and forth with - # encoding and decoding - return adjusted_line.encode() + return line.rstrip(b"\n") def close(self) -> None: self.writer.close() From 7942b7eaa76eece04f4897857e4a6c0653afbe85 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 2 Aug 2019 18:36:42 -0700 Subject: [PATCH 10/18] Expose writer --- libp2p/security/insecure/transport.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libp2p/security/insecure/transport.py b/libp2p/security/insecure/transport.py index 262b61a8..6ce6a4ef 100644 --- a/libp2p/security/insecure/transport.py +++ b/libp2p/security/insecure/transport.py @@ -6,10 +6,13 @@ from libp2p.security.secure_conn_interface import ISecureConn class InsecureSession(BaseSession): - def __init__( - self, transport: BaseSecureTransport, conn: IRawConnection, peer_id: ID - ) -> None: - super(InsecureSession, self).__init__(transport, conn, peer_id) + @property + def writer(self): + return self.insecure_conn.writer + + @property + def reader(self): + return self.insecure_conn.reader async def write(self, data: bytes) -> None: await self.insecure_conn.write(data) From 9e18d7561d7e37532a12483a1bf38671905d0858 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 2 Aug 2019 21:55:37 -0700 Subject: [PATCH 11/18] Supply local priv and pub key when upgrading to a secure transport --- libp2p/__init__.py | 5 ++++- libp2p/security/base_transport.py | 4 ++-- libp2p/security/simple/transport.py | 5 ++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libp2p/__init__.py b/libp2p/__init__.py index 68b65e61..92474ad4 100644 --- a/libp2p/__init__.py +++ b/libp2p/__init__.py @@ -99,8 +99,11 @@ def initialize_default_swarm( # TODO parse muxer and sec to pass into TransportUpgrader muxer = muxer_opt or ["mplex/6.7.0"] private_key_bytes = private_key.export_key("DER") + public_key_bytes = private_key.publickey().export_key("DER") security_transports_by_protocol = sec_opt or { - TProtocol("insecure/1.0.0"): InsecureTransport(private_key_bytes) + TProtocol("insecure/1.0.0"): InsecureTransport( + private_key_bytes, public_key_bytes + ) } upgrader = TransportUpgrader(security_transports_by_protocol, muxer) diff --git a/libp2p/security/base_transport.py b/libp2p/security/base_transport.py index 65c9757a..135454e1 100644 --- a/libp2p/security/base_transport.py +++ b/libp2p/security/base_transport.py @@ -8,6 +8,6 @@ class BaseSecureTransport(ISecureTransport): is only meant to be used in clases that derive from it. """ - def __init__(self, local_private_key: bytes) -> None: + def __init__(self, local_private_key: bytes, local_public_key: bytes) -> None: self.local_private_key = local_private_key - self.local_peer = ID.from_privkey(local_private_key) + self.local_peer = ID.from_pubkey(local_public_key) diff --git a/libp2p/security/simple/transport.py b/libp2p/security/simple/transport.py index 8a9c6dbb..ac9c01e4 100644 --- a/libp2p/security/simple/transport.py +++ b/libp2p/security/simple/transport.py @@ -10,7 +10,10 @@ from libp2p.security.secure_conn_interface import ISecureConn class SimpleSecurityTransport(BaseSecureTransport): key_phrase: str - def __init__(self, key_phrase: str) -> None: + def __init__( + self, local_private_key: bytes, local_public_key: bytes, key_phrase: str + ) -> None: + super().__init__(local_private_key, local_public_key) self.key_phrase = key_phrase async def secure_inbound(self, conn: IRawConnection) -> ISecureConn: From cda74dd3829b86a9330a8366ed8708f4d6ce68dd Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Fri, 2 Aug 2019 18:36:58 -0700 Subject: [PATCH 12/18] Update tests for new logic --- tests/libp2p/test_notify.py | 9 +- tests/pubsub/factories.py | 14 +- tests/security/test_security_multistream.py | 141 ++++++++++++++------ tests/utils.py | 7 + 4 files changed, 122 insertions(+), 49 deletions(-) diff --git a/tests/libp2p/test_notify.py b/tests/libp2p/test_notify.py index 7dd3ccbc..31029499 100644 --- a/tests/libp2p/test_notify.py +++ b/tests/libp2p/test_notify.py @@ -19,6 +19,7 @@ from tests.utils import ( cleanup, echo_stream_handler, perform_two_host_set_up_custom_handler, + generate_new_private_key, ) @@ -172,14 +173,18 @@ async def test_one_notifier_on_two_nodes(): async def test_one_notifier_on_two_nodes_with_listen(): events_b = [] + node_a_key = generate_new_private_key() node_a_transport_opt = ["/ip4/127.0.0.1/tcp/0"] - node_a = await new_node(transport_opt=node_a_transport_opt) + node_a = await new_node(node_a_key, transport_opt=node_a_transport_opt) await node_a.get_network().listen(multiaddr.Multiaddr(node_a_transport_opt[0])) # Set up node_b swarm to pass into host + node_b_key = generate_new_private_key() node_b_transport_opt = ["/ip4/127.0.0.1/tcp/0"] node_b_multiaddr = multiaddr.Multiaddr(node_b_transport_opt[0]) - node_b_swarm = initialize_default_swarm(transport_opt=node_b_transport_opt) + node_b_swarm = initialize_default_swarm( + node_b_key, transport_opt=node_b_transport_opt + ) node_b = BasicHost(node_b_swarm) async def my_stream_handler(stream): diff --git a/tests/pubsub/factories.py b/tests/pubsub/factories.py index 5572ce12..2b3aefff 100644 --- a/tests/pubsub/factories.py +++ b/tests/pubsub/factories.py @@ -1,17 +1,21 @@ import factory - from libp2p import initialize_default_swarm from libp2p.host.basic_host import BasicHost from libp2p.pubsub.floodsub import FloodSub from libp2p.pubsub.gossipsub import GossipSub from libp2p.pubsub.pubsub import Pubsub -from tests.configs import LISTEN_MADDR - -from .configs import FLOODSUB_PROTOCOL_ID, GOSSIPSUB_PARAMS, GOSSIPSUB_PROTOCOL_ID +from tests.configs import ( + FLOODSUB_PROTOCOL_ID, + GOSSIPSUB_PARAMS, + GOSSIPSUB_PROTOCOL_ID, + LISTEN_MADDR, +) +from tests.utils import generate_new_private_key def swarm_factory(): - return initialize_default_swarm(transport_opt=[str(LISTEN_MADDR)]) + private_key = generate_new_private_key() + return initialize_default_swarm(private_key, transport_opt=[str(LISTEN_MADDR)]) class HostFactory(factory.Factory): diff --git a/tests/security/test_security_multistream.py b/tests/security/test_security_multistream.py index 6abf534a..d2e9ea9f 100644 --- a/tests/security/test_security_multistream.py +++ b/tests/security/test_security_multistream.py @@ -3,11 +3,11 @@ import asyncio from libp2p import new_node from libp2p.peer.peerinfo import info_from_p2p_addr from libp2p.protocol_muxer.multiselect_client import MultiselectClientError -from libp2p.security.insecure.transport import InsecureTransport +from libp2p.security.insecure.transport import InsecureSession, InsecureTransport from libp2p.security.simple.transport import SimpleSecurityTransport import multiaddr import pytest -from tests.utils import cleanup, connect +from tests.utils import cleanup, connect, generate_new_private_key # TODO: Add tests for multiple streams being opened on different # protocols through the same connection @@ -19,6 +19,15 @@ def peer_id_for_node(node): return info.peer_id +initiator_private_key = generate_new_private_key() +initiator_private_key_bytes = initiator_private_key.export_key("DER") +initiator_public_key_bytes = initiator_private_key.publickey().export_key("DER") + +noninitiator_private_key = generate_new_private_key() +noninitiator_private_key_bytes = noninitiator_private_key.export_key("DER") +noninitiator_public_key_bytes = noninitiator_private_key.publickey().export_key("DER") + + async def perform_simple_test( assertion_func, transports_for_initiator, transports_for_noninitiator ): @@ -49,8 +58,8 @@ async def perform_simple_test( node2_conn = node2.get_network().connections[peer_id_for_node(node1)] # Perform assertion - assertion_func(node1_conn.secured_conn.get_security_details()) - assertion_func(node2_conn.secured_conn.get_security_details()) + assertion_func(node1_conn.conn) + assertion_func(node2_conn.conn) # Success, terminate pending tasks. await cleanup() @@ -58,11 +67,19 @@ async def perform_simple_test( @pytest.mark.asyncio async def test_single_insecure_security_transport_succeeds(): - transports_for_initiator = {"foo": InsecureTransport("foo")} - transports_for_noninitiator = {"foo": InsecureTransport("foo")} + transports_for_initiator = { + "foo": InsecureTransport( + initiator_private_key_bytes, initiator_public_key_bytes + ) + } + transports_for_noninitiator = { + "foo": InsecureTransport( + noninitiator_private_key_bytes, noninitiator_public_key_bytes + ) + } - def assertion_func(details): - assert details["id"] == "foo" + def assertion_func(conn): + assert isinstance(conn, InsecureSession) await perform_simple_test( assertion_func, transports_for_initiator, transports_for_noninitiator @@ -71,11 +88,19 @@ async def test_single_insecure_security_transport_succeeds(): @pytest.mark.asyncio async def test_single_simple_test_security_transport_succeeds(): - transports_for_initiator = {"tacos": SimpleSecurityTransport("tacos")} - transports_for_noninitiator = {"tacos": SimpleSecurityTransport("tacos")} + transports_for_initiator = { + "tacos": SimpleSecurityTransport( + initiator_private_key_bytes, initiator_public_key_bytes, "tacos" + ) + } + transports_for_noninitiator = { + "tacos": SimpleSecurityTransport( + noninitiator_private_key_bytes, noninitiator_public_key_bytes, "tacos" + ) + } - def assertion_func(details): - assert details["key_phrase"] == "tacos" + def assertion_func(conn): + assert conn.key_phrase == "tacos" await perform_simple_test( assertion_func, transports_for_initiator, transports_for_noninitiator @@ -85,13 +110,21 @@ async def test_single_simple_test_security_transport_succeeds(): @pytest.mark.asyncio async def test_two_simple_test_security_transport_for_initiator_succeeds(): transports_for_initiator = { - "tacos": SimpleSecurityTransport("tacos"), - "shleep": SimpleSecurityTransport("shleep"), + "tacos": SimpleSecurityTransport( + initiator_private_key_bytes, initiator_public_key_bytes, "tacos" + ), + "shleep": SimpleSecurityTransport( + initiator_private_key_bytes, initiator_public_key_bytes, "shleep" + ), + } + transports_for_noninitiator = { + "shleep": SimpleSecurityTransport( + noninitiator_private_key_bytes, noninitiator_public_key_bytes, "shleep" + ) } - transports_for_noninitiator = {"shleep": SimpleSecurityTransport("shleep")} - def assertion_func(details): - assert details["key_phrase"] == "shleep" + def assertion_func(conn): + assert conn.key_phrase == "shleep" await perform_simple_test( assertion_func, transports_for_initiator, transports_for_noninitiator @@ -100,14 +133,22 @@ async def test_two_simple_test_security_transport_for_initiator_succeeds(): @pytest.mark.asyncio async def test_two_simple_test_security_transport_for_noninitiator_succeeds(): - transports_for_initiator = {"tacos": SimpleSecurityTransport("tacos")} + transports_for_initiator = { + "tacos": SimpleSecurityTransport( + initiator_private_key_bytes, initiator_public_key_bytes, "tacos" + ) + } transports_for_noninitiator = { - "shleep": SimpleSecurityTransport("shleep"), - "tacos": SimpleSecurityTransport("tacos"), + "shleep": SimpleSecurityTransport( + noninitiator_private_key_bytes, noninitiator_public_key_bytes, "shleep" + ), + "tacos": SimpleSecurityTransport( + noninitiator_private_key_bytes, noninitiator_public_key_bytes, "tacos" + ), } - def assertion_func(details): - assert details["key_phrase"] == "tacos" + def assertion_func(conn): + assert conn.key_phrase == "tacos" await perform_simple_test( assertion_func, transports_for_initiator, transports_for_noninitiator @@ -117,16 +158,24 @@ async def test_two_simple_test_security_transport_for_noninitiator_succeeds(): @pytest.mark.asyncio async def test_two_simple_test_security_transport_for_both_succeeds(): transports_for_initiator = { - "a": SimpleSecurityTransport("a"), - "b": SimpleSecurityTransport("b"), + "a": SimpleSecurityTransport( + initiator_private_key_bytes, initiator_public_key_bytes, "a" + ), + "b": SimpleSecurityTransport( + initiator_private_key_bytes, initiator_public_key_bytes, "b" + ), } transports_for_noninitiator = { - "c": SimpleSecurityTransport("c"), - "b": SimpleSecurityTransport("b"), + "b": SimpleSecurityTransport( + noninitiator_private_key_bytes, noninitiator_public_key_bytes, "b" + ), + "c": SimpleSecurityTransport( + noninitiator_private_key_bytes, noninitiator_public_key_bytes, "c" + ), } - def assertion_func(details): - assert details["key_phrase"] == "b" + def assertion_func(conn): + assert conn.key_phrase == "b" await perform_simple_test( assertion_func, transports_for_initiator, transports_for_noninitiator @@ -136,12 +185,20 @@ async def test_two_simple_test_security_transport_for_both_succeeds(): @pytest.mark.asyncio async def test_multiple_security_none_the_same_fails(): transports_for_initiator = { - "a": SimpleSecurityTransport("a"), - "b": SimpleSecurityTransport("b"), + "a": SimpleSecurityTransport( + initiator_private_key_bytes, initiator_public_key_bytes, "a" + ), + "b": SimpleSecurityTransport( + initiator_private_key_bytes, initiator_public_key_bytes, "b" + ), } transports_for_noninitiator = { - "c": SimpleSecurityTransport("c"), - "d": SimpleSecurityTransport("d"), + "d": SimpleSecurityTransport( + noninitiator_private_key_bytes, noninitiator_public_key_bytes, "d" + ), + "c": SimpleSecurityTransport( + noninitiator_private_key_bytes, noninitiator_public_key_bytes, "c" + ), } def assertion_func(_): @@ -160,18 +217,18 @@ async def test_default_insecure_security(): transports_for_initiator = None transports_for_noninitiator = None - details1 = None - details2 = None + conn1 = None + conn2 = None - def assertion_func(details): - nonlocal details1 - nonlocal details2 - if not details1: - details1 = details - elif not details2: - details2 = details + def assertion_func(conn): + nonlocal conn1 + nonlocal conn2 + if not conn1: + conn1 = conn + elif not conn2: + conn2 = conn else: - assert details1 == details2 + assert conn1 == conn2 await perform_simple_test( assertion_func, transports_for_initiator, transports_for_noninitiator diff --git a/tests/utils.py b/tests/utils.py index 58a08807..6a6336d2 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -3,6 +3,8 @@ from contextlib import suppress import multiaddr +from Crypto.PublicKey import RSA + from libp2p import new_node from libp2p.peer.peerinfo import info_from_p2p_addr @@ -53,3 +55,8 @@ async def perform_two_host_set_up_custom_handler(handler): # Associate the peer with local ip address (see default parameters of Libp2p()) node_a.get_peerstore().add_addrs(node_b.get_id(), node_b.get_addrs(), 10) return node_a, node_b + + +def generate_new_private_key(): + new_key = RSA.generate(2048, e=65537) + return new_key From e7d2681fc08292afd24adaf0d783419ac3660e11 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 13 Aug 2019 15:19:22 -0700 Subject: [PATCH 13/18] Move base implementations into `BaseSession` --- libp2p/security/base_session.py | 23 ++++++++++++++++++++--- libp2p/security/insecure/transport.py | 14 +------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/libp2p/security/base_session.py b/libp2p/security/base_session.py index 5b23ba64..b319ea9f 100644 --- a/libp2p/security/base_session.py +++ b/libp2p/security/base_session.py @@ -15,18 +15,35 @@ class BaseSession(ISecureConn, IRawConnection): ) -> None: self.local_peer = transport.local_peer self.local_private_key = transport.local_private_key - self.insecure_conn = conn + self.conn = conn self.remote_peer_id = peer_id self.remote_permanent_pubkey = b"" # TODO clean up how this is passed around? @property def initiator(self) -> bool: - return self.insecure_conn.initiator + return self.conn.initiator # TODO clean up how this is passed around? def next_stream_id(self) -> int: - return self.insecure_conn.next_stream_id() + return self.conn.next_stream_id() + + @property + def writer(self): + return self.conn.writer + + @property + def reader(self): + return self.conn.reader + + async def write(self, data: bytes) -> None: + await self.conn.write(data) + + async def read(self) -> bytes: + return await self.conn.read() + + def close(self) -> None: + self.conn.close() def get_local_peer(self) -> ID: return self.local_peer diff --git a/libp2p/security/insecure/transport.py b/libp2p/security/insecure/transport.py index 6ce6a4ef..2d8a5a83 100644 --- a/libp2p/security/insecure/transport.py +++ b/libp2p/security/insecure/transport.py @@ -6,19 +6,7 @@ from libp2p.security.secure_conn_interface import ISecureConn class InsecureSession(BaseSession): - @property - def writer(self): - return self.insecure_conn.writer - - @property - def reader(self): - return self.insecure_conn.reader - - async def write(self, data: bytes) -> None: - await self.insecure_conn.write(data) - - async def read(self) -> bytes: - return await self.insecure_conn.read() + pass class InsecureTransport(BaseSecureTransport): From 2e3ffb9d5355752816cf1028f78c93c2b2da746b Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 15 Aug 2019 16:26:22 -0700 Subject: [PATCH 14/18] Use types for {Private,Public}Key and address other missing type hints --- libp2p/__init__.py | 12 +++++------- libp2p/security/base_session.py | 24 +++++++++--------------- libp2p/security/base_transport.py | 5 ++++- libp2p/security/secure_conn_interface.py | 7 ++++--- libp2p/security/security_multistream.py | 6 ++++-- 5 files changed, 26 insertions(+), 28 deletions(-) diff --git a/libp2p/__init__.py b/libp2p/__init__.py index 92474ad4..659c0eea 100644 --- a/libp2p/__init__.py +++ b/libp2p/__init__.py @@ -1,7 +1,7 @@ import asyncio from typing import Mapping, Sequence -from libp2p.crypto.keys import KeyPair +from libp2p.crypto.keys import KeyPair, PrivateKey from libp2p.crypto.rsa import create_new_key_pair from libp2p.host.basic_host import BasicHost from libp2p.kademlia.network import KademliaServer @@ -38,7 +38,7 @@ def generate_new_rsa_identity() -> KeyPair: return create_new_key_pair() -def generate_peer_id_from_rsa_identity(key_pair=None) -> ID: +def generate_peer_id_from_rsa_identity(key_pair: KeyPair = None) -> ID: if not key_pair: key_pair = generate_new_rsa_identity() public_key = key_pair.public_key @@ -69,7 +69,7 @@ def initialize_default_kademlia_router( def initialize_default_swarm( - private_key: bytes, + private_key: PrivateKey, id_opt: ID = None, transport_opt: Sequence[str] = None, muxer_opt: Sequence[str] = None, @@ -98,11 +98,9 @@ def initialize_default_swarm( # TODO TransportUpgrader is not doing anything really # TODO parse muxer and sec to pass into TransportUpgrader muxer = muxer_opt or ["mplex/6.7.0"] - private_key_bytes = private_key.export_key("DER") - public_key_bytes = private_key.publickey().export_key("DER") security_transports_by_protocol = sec_opt or { TProtocol("insecure/1.0.0"): InsecureTransport( - private_key_bytes, public_key_bytes + private_key, private_key.get_public_key() ) } upgrader = TransportUpgrader(security_transports_by_protocol, muxer) @@ -115,7 +113,7 @@ def initialize_default_swarm( async def new_node( - private_key=None, + private_key: PrivateKey = None, swarm_opt: INetwork = None, id_opt: ID = None, transport_opt: Sequence[str] = None, diff --git a/libp2p/security/base_session.py b/libp2p/security/base_session.py index b319ea9f..8fc4dabe 100644 --- a/libp2p/security/base_session.py +++ b/libp2p/security/base_session.py @@ -1,3 +1,6 @@ +from typing import Optional + +from libp2p.crypto.keys import PrivateKey, PublicKey from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.peer.id import ID from libp2p.security.base_transport import BaseSecureTransport @@ -17,25 +20,16 @@ class BaseSession(ISecureConn, IRawConnection): self.local_private_key = transport.local_private_key self.conn = conn self.remote_peer_id = peer_id - self.remote_permanent_pubkey = b"" + self.remote_permanent_pubkey = None - # TODO clean up how this is passed around? - @property - def initiator(self) -> bool: - return self.conn.initiator + self.initiator = self.conn.initiator + self.writer = self.conn.writer + self.reader = self.conn.reader # TODO clean up how this is passed around? def next_stream_id(self) -> int: return self.conn.next_stream_id() - @property - def writer(self): - return self.conn.writer - - @property - def reader(self): - return self.conn.reader - async def write(self, data: bytes) -> None: await self.conn.write(data) @@ -48,11 +42,11 @@ class BaseSession(ISecureConn, IRawConnection): def get_local_peer(self) -> ID: return self.local_peer - def get_local_private_key(self) -> bytes: + def get_local_private_key(self) -> PrivateKey: return self.local_private_key def get_remote_peer(self) -> ID: return self.remote_peer_id - def get_remote_public_key(self) -> bytes: + def get_remote_public_key(self) -> Optional[PublicKey]: return self.remote_permanent_pubkey diff --git a/libp2p/security/base_transport.py b/libp2p/security/base_transport.py index 135454e1..3c1e1542 100644 --- a/libp2p/security/base_transport.py +++ b/libp2p/security/base_transport.py @@ -1,3 +1,4 @@ +from libp2p.crypto.keys import PrivateKey, PublicKey from libp2p.peer.id import ID from libp2p.security.secure_transport_interface import ISecureTransport @@ -8,6 +9,8 @@ class BaseSecureTransport(ISecureTransport): is only meant to be used in clases that derive from it. """ - def __init__(self, local_private_key: bytes, local_public_key: bytes) -> None: + def __init__( + self, local_private_key: PrivateKey, local_public_key: PublicKey + ) -> None: self.local_private_key = local_private_key self.local_peer = ID.from_pubkey(local_public_key) diff --git a/libp2p/security/secure_conn_interface.py b/libp2p/security/secure_conn_interface.py index 7b88e802..ab69a6d0 100644 --- a/libp2p/security/secure_conn_interface.py +++ b/libp2p/security/secure_conn_interface.py @@ -1,7 +1,8 @@ from abc import ABC, abstractmethod -from libp2p.peer.id import ID +from libp2p.crypto.keys import PrivateKey, PublicKey from libp2p.network.connection.raw_connection_interface import IRawConnection +from libp2p.peer.id import ID """ @@ -18,7 +19,7 @@ class AbstractSecureConn(ABC): pass @abstractmethod - def get_local_private_key(self) -> bytes: + def get_local_private_key(self) -> PrivateKey: pass @abstractmethod @@ -26,7 +27,7 @@ class AbstractSecureConn(ABC): pass @abstractmethod - def get_remote_public_key(self) -> bytes: + def get_remote_public_key(self) -> PublicKey: pass diff --git a/libp2p/security/security_multistream.py b/libp2p/security/security_multistream.py index 43c5dbf3..fcb85a73 100644 --- a/libp2p/security/security_multistream.py +++ b/libp2p/security/security_multistream.py @@ -1,5 +1,5 @@ from abc import ABC -from typing import Dict +from typing import Dict, Mapping from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.peer.id import ID @@ -23,7 +23,9 @@ class SecurityMultistream(ABC): multiselect: Multiselect multiselect_client: MultiselectClient - def __init__(self, secure_transports_by_protocol) -> None: + def __init__( + self, secure_transports_by_protocol: Mapping[TProtocol, ISecureTransport] + ) -> None: self.transports = {} self.multiselect = Multiselect() self.multiselect_client = MultiselectClient() From 82bae341a7d9c3a8f6e6e89971a6da52a87826cc Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 15 Aug 2019 16:26:59 -0700 Subject: [PATCH 15/18] Run isort over files that were missing it --- libp2p/stream_muxer/mplex/mplex.py | 3 ++- tests/libp2p/test_notify.py | 2 +- tests/pubsub/factories.py | 1 + tests/security/test_security_multistream.py | 5 +++-- tests/utils.py | 3 +-- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libp2p/stream_muxer/mplex/mplex.py b/libp2p/stream_muxer/mplex/mplex.py index 00dc25c3..95336d94 100644 --- a/libp2p/stream_muxer/mplex/mplex.py +++ b/libp2p/stream_muxer/mplex/mplex.py @@ -1,12 +1,13 @@ import asyncio from typing import Dict, Tuple +from multiaddr import Multiaddr + from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.network.typing import GenericProtocolHandlerFn from libp2p.peer.id import ID from libp2p.security.secure_conn_interface import ISecureConn from libp2p.stream_muxer.abc import IMuxedConn, IMuxedStream -from multiaddr import Multiaddr from .constants import HeaderTags from .mplex_stream import MplexStream diff --git a/tests/libp2p/test_notify.py b/tests/libp2p/test_notify.py index 31029499..f1262a1f 100644 --- a/tests/libp2p/test_notify.py +++ b/tests/libp2p/test_notify.py @@ -18,8 +18,8 @@ from libp2p.network.notifee_interface import INotifee from tests.utils import ( cleanup, echo_stream_handler, - perform_two_host_set_up_custom_handler, generate_new_private_key, + perform_two_host_set_up_custom_handler, ) diff --git a/tests/pubsub/factories.py b/tests/pubsub/factories.py index 2b3aefff..e35839dc 100644 --- a/tests/pubsub/factories.py +++ b/tests/pubsub/factories.py @@ -1,4 +1,5 @@ import factory + from libp2p import initialize_default_swarm from libp2p.host.basic_host import BasicHost from libp2p.pubsub.floodsub import FloodSub diff --git a/tests/security/test_security_multistream.py b/tests/security/test_security_multistream.py index d2e9ea9f..bf4929ba 100644 --- a/tests/security/test_security_multistream.py +++ b/tests/security/test_security_multistream.py @@ -1,12 +1,13 @@ import asyncio +import multiaddr +import pytest + from libp2p import new_node from libp2p.peer.peerinfo import info_from_p2p_addr from libp2p.protocol_muxer.multiselect_client import MultiselectClientError from libp2p.security.insecure.transport import InsecureSession, InsecureTransport from libp2p.security.simple.transport import SimpleSecurityTransport -import multiaddr -import pytest from tests.utils import cleanup, connect, generate_new_private_key # TODO: Add tests for multiple streams being opened on different diff --git a/tests/utils.py b/tests/utils.py index 6a6336d2..39368694 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,9 +1,8 @@ import asyncio from contextlib import suppress -import multiaddr - from Crypto.PublicKey import RSA +import multiaddr from libp2p import new_node from libp2p.peer.peerinfo import info_from_p2p_addr From 9a4e23a803f245997cc00fb6c3193a2e7503cf0c Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 15 Aug 2019 16:36:32 -0700 Subject: [PATCH 16/18] mypy protobuf plugin requires keyword-based initializers --- libp2p/crypto/keys.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libp2p/crypto/keys.py b/libp2p/crypto/keys.py index 4a43b41f..b0dec3d9 100644 --- a/libp2p/crypto/keys.py +++ b/libp2p/crypto/keys.py @@ -46,11 +46,9 @@ class PublicKey(Key): ... def serialize_to_protobuf(self) -> protobuf.PublicKey: - _type = self.get_type() + key_type = self.get_type().value data = self.to_bytes() - protobuf_key = protobuf.PublicKey() - protobuf_key.key_type = _type.value - protobuf_key.data = data + protobuf_key = protobuf.PublicKey(key_type=key_type, data=data) return protobuf_key @@ -68,11 +66,9 @@ class PrivateKey(Key): ... def serialize_to_protobuf(self) -> protobuf.PrivateKey: - _type = self.get_type() + key_type = self.get_type().value data = self.to_bytes() - protobuf_key = protobuf.PrivateKey() - protobuf_key.key_type = _type.value - protobuf_key.data = data + protobuf_key = protobuf.PrivateKey(key_type=key_type, data=data) return protobuf_key From d17e6f339234a06a568cf810c65d948905e08321 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 15 Aug 2019 16:40:31 -0700 Subject: [PATCH 17/18] Fix some test imports that got botched in rebase --- tests/pubsub/conftest.py | 10 +++++++--- tests/pubsub/factories.py | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/pubsub/conftest.py b/tests/pubsub/conftest.py index 3c4a34b5..82b77828 100644 --- a/tests/pubsub/conftest.py +++ b/tests/pubsub/conftest.py @@ -3,9 +3,13 @@ import asyncio import pytest from tests.configs import LISTEN_MADDR - -from .configs import GOSSIPSUB_PARAMS -from .factories import FloodsubFactory, GossipsubFactory, HostFactory, PubsubFactory +from tests.pubsub.configs import GOSSIPSUB_PARAMS +from tests.pubsub.factories import ( + FloodsubFactory, + GossipsubFactory, + HostFactory, + PubsubFactory, +) @pytest.fixture diff --git a/tests/pubsub/factories.py b/tests/pubsub/factories.py index e35839dc..d25c2784 100644 --- a/tests/pubsub/factories.py +++ b/tests/pubsub/factories.py @@ -5,11 +5,11 @@ from libp2p.host.basic_host import BasicHost from libp2p.pubsub.floodsub import FloodSub from libp2p.pubsub.gossipsub import GossipSub from libp2p.pubsub.pubsub import Pubsub -from tests.configs import ( +from tests.configs import LISTEN_MADDR +from tests.pubsub.configs import ( FLOODSUB_PROTOCOL_ID, GOSSIPSUB_PARAMS, GOSSIPSUB_PROTOCOL_ID, - LISTEN_MADDR, ) from tests.utils import generate_new_private_key From 7535a02da77bfc1749eca232af1adb8102534fbf Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 15 Aug 2019 18:36:50 -0700 Subject: [PATCH 18/18] Clean up key gen --- libp2p/__init__.py | 18 ++--- libp2p/security/base_transport.py | 10 +-- libp2p/security/simple/transport.py | 7 +- tests/libp2p/test_notify.py | 10 +-- tests/pubsub/factories.py | 4 +- tests/security/test_security_multistream.py | 87 ++++++--------------- tests/utils.py | 6 -- 7 files changed, 44 insertions(+), 98 deletions(-) diff --git a/libp2p/__init__.py b/libp2p/__init__.py index 659c0eea..a69f6f61 100644 --- a/libp2p/__init__.py +++ b/libp2p/__init__.py @@ -1,7 +1,7 @@ import asyncio from typing import Mapping, Sequence -from libp2p.crypto.keys import KeyPair, PrivateKey +from libp2p.crypto.keys import KeyPair from libp2p.crypto.rsa import create_new_key_pair from libp2p.host.basic_host import BasicHost from libp2p.kademlia.network import KademliaServer @@ -69,7 +69,7 @@ def initialize_default_kademlia_router( def initialize_default_swarm( - private_key: PrivateKey, + key_pair: KeyPair, id_opt: ID = None, transport_opt: Sequence[str] = None, muxer_opt: Sequence[str] = None, @@ -89,7 +89,7 @@ def initialize_default_swarm( """ if not id_opt: - id_opt = generate_peer_id_from_rsa_identity() + id_opt = generate_peer_id_from_rsa_identity(key_pair) # TODO parse transport_opt to determine transport transport_opt = transport_opt or ["/ip4/127.0.0.1/tcp/8001"] @@ -99,9 +99,7 @@ def initialize_default_swarm( # TODO parse muxer and sec to pass into TransportUpgrader muxer = muxer_opt or ["mplex/6.7.0"] security_transports_by_protocol = sec_opt or { - TProtocol("insecure/1.0.0"): InsecureTransport( - private_key, private_key.get_public_key() - ) + TProtocol("insecure/1.0.0"): InsecureTransport(key_pair) } upgrader = TransportUpgrader(security_transports_by_protocol, muxer) @@ -113,7 +111,7 @@ def initialize_default_swarm( async def new_node( - private_key: PrivateKey = None, + key_pair: KeyPair = None, swarm_opt: INetwork = None, id_opt: ID = None, transport_opt: Sequence[str] = None, @@ -124,6 +122,7 @@ async def new_node( ) -> BasicHost: """ create new libp2p node + :param key_pair: key pair for deriving an identity :param swarm_opt: optional swarm :param id_opt: optional id for host :param transport_opt: optional choice of transport upgrade @@ -134,16 +133,15 @@ async def new_node( :return: return a host instance """ - if not private_key: + if not key_pair: key_pair = generate_new_rsa_identity() - private_key = key_pair.private_key if not id_opt: id_opt = generate_peer_id_from_rsa_identity(key_pair) if not swarm_opt: swarm_opt = initialize_default_swarm( - private_key=private_key, + key_pair=key_pair, id_opt=id_opt, transport_opt=transport_opt, muxer_opt=muxer_opt, diff --git a/libp2p/security/base_transport.py b/libp2p/security/base_transport.py index 3c1e1542..0f096bfc 100644 --- a/libp2p/security/base_transport.py +++ b/libp2p/security/base_transport.py @@ -1,4 +1,4 @@ -from libp2p.crypto.keys import PrivateKey, PublicKey +from libp2p.crypto.keys import KeyPair from libp2p.peer.id import ID from libp2p.security.secure_transport_interface import ISecureTransport @@ -9,8 +9,6 @@ class BaseSecureTransport(ISecureTransport): is only meant to be used in clases that derive from it. """ - def __init__( - self, local_private_key: PrivateKey, local_public_key: PublicKey - ) -> None: - self.local_private_key = local_private_key - self.local_peer = ID.from_pubkey(local_public_key) + def __init__(self, local_key_pair: KeyPair) -> None: + self.local_private_key = local_key_pair.private_key + self.local_peer = ID.from_pubkey(local_key_pair.public_key) diff --git a/libp2p/security/simple/transport.py b/libp2p/security/simple/transport.py index ac9c01e4..5ff07cdd 100644 --- a/libp2p/security/simple/transport.py +++ b/libp2p/security/simple/transport.py @@ -1,5 +1,6 @@ import asyncio +from libp2p.crypto.keys import KeyPair from libp2p.network.connection.raw_connection_interface import IRawConnection from libp2p.peer.id import ID from libp2p.security.base_transport import BaseSecureTransport @@ -10,10 +11,8 @@ from libp2p.security.secure_conn_interface import ISecureConn class SimpleSecurityTransport(BaseSecureTransport): key_phrase: str - def __init__( - self, local_private_key: bytes, local_public_key: bytes, key_phrase: str - ) -> None: - super().__init__(local_private_key, local_public_key) + def __init__(self, local_key_pair: KeyPair, key_phrase: str) -> None: + super().__init__(local_key_pair) self.key_phrase = key_phrase async def secure_inbound(self, conn: IRawConnection) -> ISecureConn: diff --git a/tests/libp2p/test_notify.py b/tests/libp2p/test_notify.py index f1262a1f..f4bd2efc 100644 --- a/tests/libp2p/test_notify.py +++ b/tests/libp2p/test_notify.py @@ -13,12 +13,12 @@ import multiaddr import pytest from libp2p import initialize_default_swarm, new_node +from libp2p.crypto.rsa import create_new_key_pair from libp2p.host.basic_host import BasicHost from libp2p.network.notifee_interface import INotifee from tests.utils import ( cleanup, echo_stream_handler, - generate_new_private_key, perform_two_host_set_up_custom_handler, ) @@ -173,17 +173,17 @@ async def test_one_notifier_on_two_nodes(): async def test_one_notifier_on_two_nodes_with_listen(): events_b = [] - node_a_key = generate_new_private_key() + node_a_key_pair = create_new_key_pair() node_a_transport_opt = ["/ip4/127.0.0.1/tcp/0"] - node_a = await new_node(node_a_key, transport_opt=node_a_transport_opt) + node_a = await new_node(node_a_key_pair, transport_opt=node_a_transport_opt) await node_a.get_network().listen(multiaddr.Multiaddr(node_a_transport_opt[0])) # Set up node_b swarm to pass into host - node_b_key = generate_new_private_key() + node_b_key_pair = create_new_key_pair() node_b_transport_opt = ["/ip4/127.0.0.1/tcp/0"] node_b_multiaddr = multiaddr.Multiaddr(node_b_transport_opt[0]) node_b_swarm = initialize_default_swarm( - node_b_key, transport_opt=node_b_transport_opt + node_b_key_pair, transport_opt=node_b_transport_opt ) node_b = BasicHost(node_b_swarm) diff --git a/tests/pubsub/factories.py b/tests/pubsub/factories.py index d25c2784..b57c29bc 100644 --- a/tests/pubsub/factories.py +++ b/tests/pubsub/factories.py @@ -1,6 +1,7 @@ import factory from libp2p import initialize_default_swarm +from libp2p.crypto.rsa import create_new_key_pair from libp2p.host.basic_host import BasicHost from libp2p.pubsub.floodsub import FloodSub from libp2p.pubsub.gossipsub import GossipSub @@ -11,11 +12,10 @@ from tests.pubsub.configs import ( GOSSIPSUB_PARAMS, GOSSIPSUB_PROTOCOL_ID, ) -from tests.utils import generate_new_private_key def swarm_factory(): - private_key = generate_new_private_key() + private_key = create_new_key_pair() return initialize_default_swarm(private_key, transport_opt=[str(LISTEN_MADDR)]) diff --git a/tests/security/test_security_multistream.py b/tests/security/test_security_multistream.py index bf4929ba..ddbae8e3 100644 --- a/tests/security/test_security_multistream.py +++ b/tests/security/test_security_multistream.py @@ -4,11 +4,12 @@ import multiaddr import pytest from libp2p import new_node +from libp2p.crypto.rsa import create_new_key_pair from libp2p.peer.peerinfo import info_from_p2p_addr from libp2p.protocol_muxer.multiselect_client import MultiselectClientError from libp2p.security.insecure.transport import InsecureSession, InsecureTransport from libp2p.security.simple.transport import SimpleSecurityTransport -from tests.utils import cleanup, connect, generate_new_private_key +from tests.utils import cleanup, connect # TODO: Add tests for multiple streams being opened on different # protocols through the same connection @@ -20,13 +21,9 @@ def peer_id_for_node(node): return info.peer_id -initiator_private_key = generate_new_private_key() -initiator_private_key_bytes = initiator_private_key.export_key("DER") -initiator_public_key_bytes = initiator_private_key.publickey().export_key("DER") +initiator_key_pair = create_new_key_pair() -noninitiator_private_key = generate_new_private_key() -noninitiator_private_key_bytes = noninitiator_private_key.export_key("DER") -noninitiator_public_key_bytes = noninitiator_private_key.publickey().export_key("DER") +noninitiator_key_pair = create_new_key_pair() async def perform_simple_test( @@ -68,16 +65,8 @@ async def perform_simple_test( @pytest.mark.asyncio async def test_single_insecure_security_transport_succeeds(): - transports_for_initiator = { - "foo": InsecureTransport( - initiator_private_key_bytes, initiator_public_key_bytes - ) - } - transports_for_noninitiator = { - "foo": InsecureTransport( - noninitiator_private_key_bytes, noninitiator_public_key_bytes - ) - } + transports_for_initiator = {"foo": InsecureTransport(initiator_key_pair)} + transports_for_noninitiator = {"foo": InsecureTransport(noninitiator_key_pair)} def assertion_func(conn): assert isinstance(conn, InsecureSession) @@ -90,14 +79,10 @@ async def test_single_insecure_security_transport_succeeds(): @pytest.mark.asyncio async def test_single_simple_test_security_transport_succeeds(): transports_for_initiator = { - "tacos": SimpleSecurityTransport( - initiator_private_key_bytes, initiator_public_key_bytes, "tacos" - ) + "tacos": SimpleSecurityTransport(initiator_key_pair, "tacos") } transports_for_noninitiator = { - "tacos": SimpleSecurityTransport( - noninitiator_private_key_bytes, noninitiator_public_key_bytes, "tacos" - ) + "tacos": SimpleSecurityTransport(noninitiator_key_pair, "tacos") } def assertion_func(conn): @@ -111,17 +96,11 @@ async def test_single_simple_test_security_transport_succeeds(): @pytest.mark.asyncio async def test_two_simple_test_security_transport_for_initiator_succeeds(): transports_for_initiator = { - "tacos": SimpleSecurityTransport( - initiator_private_key_bytes, initiator_public_key_bytes, "tacos" - ), - "shleep": SimpleSecurityTransport( - initiator_private_key_bytes, initiator_public_key_bytes, "shleep" - ), + "tacos": SimpleSecurityTransport(initiator_key_pair, "tacos"), + "shleep": SimpleSecurityTransport(initiator_key_pair, "shleep"), } transports_for_noninitiator = { - "shleep": SimpleSecurityTransport( - noninitiator_private_key_bytes, noninitiator_public_key_bytes, "shleep" - ) + "shleep": SimpleSecurityTransport(noninitiator_key_pair, "shleep") } def assertion_func(conn): @@ -135,17 +114,11 @@ async def test_two_simple_test_security_transport_for_initiator_succeeds(): @pytest.mark.asyncio async def test_two_simple_test_security_transport_for_noninitiator_succeeds(): transports_for_initiator = { - "tacos": SimpleSecurityTransport( - initiator_private_key_bytes, initiator_public_key_bytes, "tacos" - ) + "tacos": SimpleSecurityTransport(initiator_key_pair, "tacos") } transports_for_noninitiator = { - "shleep": SimpleSecurityTransport( - noninitiator_private_key_bytes, noninitiator_public_key_bytes, "shleep" - ), - "tacos": SimpleSecurityTransport( - noninitiator_private_key_bytes, noninitiator_public_key_bytes, "tacos" - ), + "shleep": SimpleSecurityTransport(noninitiator_key_pair, "shleep"), + "tacos": SimpleSecurityTransport(noninitiator_key_pair, "tacos"), } def assertion_func(conn): @@ -159,20 +132,12 @@ async def test_two_simple_test_security_transport_for_noninitiator_succeeds(): @pytest.mark.asyncio async def test_two_simple_test_security_transport_for_both_succeeds(): transports_for_initiator = { - "a": SimpleSecurityTransport( - initiator_private_key_bytes, initiator_public_key_bytes, "a" - ), - "b": SimpleSecurityTransport( - initiator_private_key_bytes, initiator_public_key_bytes, "b" - ), + "a": SimpleSecurityTransport(initiator_key_pair, "a"), + "b": SimpleSecurityTransport(initiator_key_pair, "b"), } transports_for_noninitiator = { - "b": SimpleSecurityTransport( - noninitiator_private_key_bytes, noninitiator_public_key_bytes, "b" - ), - "c": SimpleSecurityTransport( - noninitiator_private_key_bytes, noninitiator_public_key_bytes, "c" - ), + "b": SimpleSecurityTransport(noninitiator_key_pair, "b"), + "c": SimpleSecurityTransport(noninitiator_key_pair, "c"), } def assertion_func(conn): @@ -186,20 +151,12 @@ async def test_two_simple_test_security_transport_for_both_succeeds(): @pytest.mark.asyncio async def test_multiple_security_none_the_same_fails(): transports_for_initiator = { - "a": SimpleSecurityTransport( - initiator_private_key_bytes, initiator_public_key_bytes, "a" - ), - "b": SimpleSecurityTransport( - initiator_private_key_bytes, initiator_public_key_bytes, "b" - ), + "a": SimpleSecurityTransport(initiator_key_pair, "a"), + "b": SimpleSecurityTransport(initiator_key_pair, "b"), } transports_for_noninitiator = { - "d": SimpleSecurityTransport( - noninitiator_private_key_bytes, noninitiator_public_key_bytes, "d" - ), - "c": SimpleSecurityTransport( - noninitiator_private_key_bytes, noninitiator_public_key_bytes, "c" - ), + "d": SimpleSecurityTransport(noninitiator_key_pair, "d"), + "c": SimpleSecurityTransport(noninitiator_key_pair, "c"), } def assertion_func(_): diff --git a/tests/utils.py b/tests/utils.py index 39368694..58a08807 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,7 +1,6 @@ import asyncio from contextlib import suppress -from Crypto.PublicKey import RSA import multiaddr from libp2p import new_node @@ -54,8 +53,3 @@ async def perform_two_host_set_up_custom_handler(handler): # Associate the peer with local ip address (see default parameters of Libp2p()) node_a.get_peerstore().add_addrs(node_b.get_id(), node_b.get_addrs(), 10) return node_a, node_b - - -def generate_new_private_key(): - new_key = RSA.generate(2048, e=65537) - return new_key