This repository supplies a simplified implementation of the Noise handshake such that it only supports the XX handshake compatible with libp2p nodes (such as those on the IPFS network).
Connections are generic objects that can manage an underlying byte stream over the network. The Multistream connection has been implemented for the purposes of this repository.
HandShakes represent the logic for authentication handshakes that can take place over the network to secure a connection. This repository only allows you to read and write from a SecureChannel.
See tests/ for examples on the usage of the library.
Library defines the following traits to implement Connections and HandShakes:
pub trait Connection {
/// Connect to a remote peer using their [std::net::SocketAddr]
fn connect(address: SocketAddr) -> Result<Self, Box<dyn Error>>
where
Self: Sized;
/// Upgrade the connection to a [SecureChannel] for communication
fn upgrade<'a, H: HandShake<'a, Self> + 'a>(
connection: Self,
peer_id: Keypair,
) -> Result<Box<dyn SecureChannel + 'a>, Box<dyn Error>>
where
Self: Sized + 'a;
}pub trait HandShake<'a, C: Connection> {
/// Channel lifetime is tied to the lifetime of the Connection
type Channel<'channel>: SecureChannel;
/// Upgrade a connection into a secure channel, this method takes ownershup of the connection
/// so the raw connection can never be used to communicate.
/// [`Reader`] is a function that takes a connection and reads content from the underlying stream.
/// [`Writer`] is a function that takes a connection and and some encrypted content and write it to the underlying stream.
fn upgrade<Reader, Writer>(
connection: C,
peer_id: Keypair,
reader: Reader,
writer: Writer,
) -> Result<Self::Channel<'a>, Box<dyn Error>>
where
C: Connection,
Reader: Fn(&mut C) -> Result<Vec<u8>, Box<dyn Error>> + 'a,
Writer: Fn(&mut C, &[u8]) -> Result<(), Box<dyn Error>> + 'a;
}
pub trait SecureChannel {
/// A function that allows a secure channel to securely write to the underlying stream.
fn write(&mut self, data: &[u8]) -> Result<(), Box<dyn Error>>;
/// A function that allows a secure channel to read securely from the underlying stream.
fn read(&mut self) -> Result<Vec<u8>, Box<dyn Error>>;
}Known working peers (tested):
- 147.75.84.175:4001 (Web3 Storage) https://github.com/web3-storage/web3.storage/blob/main/PEERS
- 139.178.88.145:4001 (Web3 Storage)
- 5.161.92.43:4001 (StorJ) https://docs.ipfs.tech/how-to/peering-with-content-providers/#content-provider-list
cargo testcargo test -- -nocaptureexport PEER_ADDR="139.178.88.145:4001"
cargo test --package noise_handshake --test noise_handshake_integration -- noise::test_handshake --exact --nocaptureThe integration test should print out YAMUX RESP: "\u{13}/multistream/1.0.0\n\u{f}/ipfs/id/1.0.0\n" upon successful connection to a peer to
indicate that the authentication handshake and multiplexer has been negotiated.
- The
CipherStateimplemention is barebones and likely lacks quite a few security checks (such as bounds on theNonces) - At the moment there is no implementation for
async Connections, these could straightforwardly be support by theTokioTcpStreamas opposed to thestd::net::TcpStreamin use now. - Multiplexing is not implemented correctly outside of the integration test, support for
Yamuxand more general multiplexing should be developed - There are alot of
heapallocations throughout, the hot-paths can likely be optimised to work more directly with slice references, it would be best to review this after implementingasync Connectionsto ensure we don't run into borrower semantics indirectly.
- https://docs.ipfs.tech/how-to/peering-with-content-providers/#content-provider-list
- https://github.com/web3-storage/web3.storage/blob/main/PEERS
- https://ipfs.io/ipfs/QmR7GSQM93Cx5eAg6a6yRzNde1FQv7uL6X1o4k7zrJa3LX/ipfs.draft3.pdf
- https://github.com/libp2p/specs/blob/master/connections/README.md
- https://github.com/libp2p/specs/blob/master/noise/README.md
- https://noiseprotocol.org/noise.html
- https://github.com/mcginty/snow
- https://github.com/libp2p/rust-libp2p/tree/master/transports/noise
- https://github.com/libp2p/go-libp2p/tree/master/p2p/security/noise