Skip to content

Commit

Permalink
Merge pull request #406 from mhchia/feature/noise-patterxx
Browse files Browse the repository at this point in the history
Noise: `PatternXX` and testing with go
  • Loading branch information
mhchia authored Feb 28, 2020
2 parents 1f881e0 + ec8c109 commit 9d68de8
Show file tree
Hide file tree
Showing 48 changed files with 1,183 additions and 601 deletions.
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ matrix:
env: TOXENV=docs
- python: 3.7
dist: xenial
env: TOXENV=py37-interop
env: TOXENV=py37-interop GOBINPKG=go1.13.8.linux-amd64.tar.gz
sudo: true
before_install:
- wget https://dl.google.com/go/go1.12.6.linux-amd64.tar.gz
- sudo tar -C /usr/local -xzf go1.12.6.linux-amd64.tar.gz
- wget https://dl.google.com/go/$GOBINPKG
- sudo tar -C /usr/local -xzf $GOBINPKG
- export GOPATH=$HOME/go
- export GOROOT=/usr/local/go
- export PATH=$GOROOT/bin:$GOPATH/bin:$PATH
Expand Down
20 changes: 18 additions & 2 deletions docs/libp2p.security.noise.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,26 @@ Subpackages
Submodules
----------

libp2p.security.noise.connection module
libp2p.security.noise.exceptions module
---------------------------------------

.. automodule:: libp2p.security.noise.connection
.. automodule:: libp2p.security.noise.exceptions
:members:
:undoc-members:
:show-inheritance:

libp2p.security.noise.io module
-------------------------------

.. automodule:: libp2p.security.noise.io
:members:
:undoc-members:
:show-inheritance:

libp2p.security.noise.messages module
-------------------------------------

.. automodule:: libp2p.security.noise.messages
:members:
:undoc-members:
:show-inheritance:
Expand Down
31 changes: 31 additions & 0 deletions libp2p/io/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


class Closer(ABC):
@abstractmethod
async def close(self) -> None:
...

Expand Down Expand Up @@ -32,3 +33,33 @@ class ReadWriter(Reader, Writer):

class ReadWriteCloser(Reader, Writer, Closer):
pass


class MsgReader(ABC):
@abstractmethod
async def read_msg(self) -> bytes:
...


class MsgWriter(ABC):
@abstractmethod
async def write_msg(self, msg: bytes) -> None:
...


class MsgReadWriteCloser(MsgReader, MsgWriter, Closer):
pass


class Encrypter(ABC):
@abstractmethod
def encrypt(self, data: bytes) -> bytes:
...

@abstractmethod
def decrypt(self, data: bytes) -> bytes:
...


class EncryptedMsgReadWriter(MsgReadWriteCloser, Encrypter):
"""Read/write message with encryption/decryption."""
4 changes: 4 additions & 0 deletions libp2p/io/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,7 @@ class MissingMessageException(MsgioException):

class DecryptionFailedException(MsgioException):
pass


class MessageTooLarge(MsgioException):
pass
106 changes: 56 additions & 50 deletions libp2p/io/msgio.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,79 +5,85 @@
NOTE: currently missing the capability to indicate lengths by "varint" method.
"""
# TODO unify w/ https://github.com/libp2p/py-libp2p/blob/1aed52856f56a4b791696bbcbac31b5f9c2e88c9/libp2p/utils.py#L85-L99 # noqa: E501
from typing import Optional, cast
from abc import abstractmethod

from libp2p.io.abc import Closer, ReadCloser, Reader, ReadWriteCloser, WriteCloser
from libp2p.io.abc import MsgReadWriteCloser, Reader, ReadWriteCloser
from libp2p.io.utils import read_exactly
from libp2p.utils import decode_uvarint_from_stream, encode_varint_prefixed

from .exceptions import MessageTooLarge

SIZE_LEN_BYTES = 4
BYTE_ORDER = "big"


async def read_length(reader: Reader) -> int:
length_bytes = await read_exactly(reader, SIZE_LEN_BYTES)
async def read_length(reader: Reader, size_len_bytes: int) -> int:
length_bytes = await read_exactly(reader, size_len_bytes)
return int.from_bytes(length_bytes, byteorder=BYTE_ORDER)


def encode_msg_with_length(msg_bytes: bytes) -> bytes:
len_prefix = len(msg_bytes).to_bytes(SIZE_LEN_BYTES, "big")
def encode_msg_with_length(msg_bytes: bytes, size_len_bytes: int) -> bytes:
try:
len_prefix = len(msg_bytes).to_bytes(size_len_bytes, byteorder=BYTE_ORDER)
except OverflowError:
raise ValueError(
"msg_bytes is too large for `size_len_bytes` bytes length: "
f"msg_bytes={msg_bytes!r}, size_len_bytes={size_len_bytes}"
)
return len_prefix + msg_bytes


class MsgIOWriter(WriteCloser):
write_closer: WriteCloser

def __init__(self, write_closer: WriteCloser) -> None:
self.write_closer = write_closer

async def write(self, data: bytes) -> None:
await self.write_msg(data)
class BaseMsgReadWriter(MsgReadWriteCloser):
read_write_closer: ReadWriteCloser
size_len_bytes: int

async def write_msg(self, msg: bytes) -> None:
data = encode_msg_with_length(msg)
await self.write_closer.write(data)
def __init__(self, read_write_closer: ReadWriteCloser) -> None:
self.read_write_closer = read_write_closer

async def close(self) -> None:
await self.write_closer.close()
async def read_msg(self) -> bytes:
length = await self.next_msg_len()
return await read_exactly(self.read_write_closer, length)

@abstractmethod
async def next_msg_len(self) -> int:
...

class MsgIOReader(ReadCloser):
read_closer: ReadCloser
next_length: Optional[int]
@abstractmethod
def encode_msg(self, msg: bytes) -> bytes:
...

def __init__(self, read_closer: ReadCloser) -> None:
# NOTE: the following line is required to satisfy the
# multiple inheritance but `mypy` does not like it...
super().__init__(read_closer) # type: ignore
self.read_closer = read_closer
self.next_length = None
async def close(self) -> None:
await self.read_write_closer.close()

async def read(self, n: int = None) -> bytes:
return await self.read_msg()
async def write_msg(self, msg: bytes) -> None:
encoded_msg = self.encode_msg(msg)
await self.read_write_closer.write(encoded_msg)

async def read_msg(self) -> bytes:
length = await self.next_msg_len()

data = await read_exactly(self.read_closer, length)
if len(data) < length:
self.next_length = length - len(data)
else:
self.next_length = None
return data
class FixedSizeLenMsgReadWriter(BaseMsgReadWriter):
size_len_bytes: int

async def next_msg_len(self) -> int:
if self.next_length is None:
self.next_length = await read_length(self.read_closer)
return self.next_length
return await read_length(self.read_write_closer, self.size_len_bytes)

async def close(self) -> None:
await self.read_closer.close()
def encode_msg(self, msg: bytes) -> bytes:
return encode_msg_with_length(msg, self.size_len_bytes)


class MsgIOReadWriter(MsgIOReader, MsgIOWriter, Closer):
def __init__(self, read_write_closer: ReadWriteCloser) -> None:
super().__init__(cast(ReadCloser, read_write_closer))
class VarIntLengthMsgReadWriter(BaseMsgReadWriter):
max_msg_size: int

async def close(self) -> None:
await self.read_closer.close()
async def next_msg_len(self) -> int:
msg_len = await decode_uvarint_from_stream(self.read_write_closer)
if msg_len > self.max_msg_size:
raise MessageTooLarge(
f"msg_len={msg_len} > max_msg_size={self.max_msg_size}"
)
return msg_len

def encode_msg(self, msg: bytes) -> bytes:
msg_len = len(msg)
if msg_len > self.max_msg_size:
raise MessageTooLarge(
f"msg_len={msg_len} > max_msg_size={self.max_msg_size}"
)
return encode_varint_prefixed(msg)
12 changes: 7 additions & 5 deletions libp2p/security/base_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,22 @@ class BaseSession(ISecureConn):

local_peer: ID
local_private_key: PrivateKey
remote_peer_id: ID
remote_peer: ID
remote_permanent_pubkey: PublicKey

def __init__(
self,
*,
local_peer: ID,
local_private_key: PrivateKey,
remote_peer: ID,
remote_permanent_pubkey: PublicKey,
is_initiator: bool,
peer_id: Optional[ID] = None,
) -> None:
self.local_peer = local_peer
self.local_private_key = local_private_key
self.remote_peer_id = peer_id
self.remote_permanent_pubkey = None
self.remote_peer = remote_peer
self.remote_permanent_pubkey = remote_permanent_pubkey
self.is_initiator = is_initiator

def get_local_peer(self) -> ID:
Expand All @@ -34,7 +36,7 @@ def get_local_private_key(self) -> PrivateKey:
return self.local_private_key

def get_remote_peer(self) -> ID:
return self.remote_peer_id
return self.remote_peer

def get_remote_public_key(self) -> Optional[PublicKey]:
return self.remote_permanent_pubkey
17 changes: 8 additions & 9 deletions libp2p/security/insecure/pb/plaintext_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 9d68de8

Please sign in to comment.