mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-05-28 10:11:19 +00:00
protocols/noise: Add NoiseConfig::with_prologue
(#2903)
This commit is contained in:
parent
39d63513d4
commit
ed1b89902a
@ -46,6 +46,8 @@
|
||||
# 0.49.0 - [unreleased]
|
||||
|
||||
- Update to [`libp2p-tcp` `v0.37.0`](transports/tcp/CHANGELOG.md#0370).
|
||||
-
|
||||
- Update to [`libp2p-noise` `v0.39.1`](transports/noise/CHANGELOG.md#0391).
|
||||
|
||||
- Update to [`libp2p-swarm-derive` `v0.30.1`](swarm-derive/CHANGELOG.md#0301).
|
||||
|
||||
|
@ -2,8 +2,10 @@
|
||||
|
||||
- Introduce `NoiseAuthenticated::xx` constructor, assuming a X25519 DH key exchange. An XX key exchange and X25519 keys
|
||||
are the most common way of using noise in libp2p and thus deserve a convenience constructor. See [PR 2887].
|
||||
- Add `NoiseConfig::with_prologue` which allows users to set the noise prologue of the handshake. See [PR 2903].
|
||||
|
||||
[PR 2887]: https://github.com/libp2p/rust-libp2p/pull/2887
|
||||
[PR 2903]: https://github.com/libp2p/rust-libp2p/pull/2903
|
||||
|
||||
# 0.39.0
|
||||
|
||||
|
@ -67,6 +67,7 @@ pub use protocol::{Protocol, ProtocolParams, IK, IX, XX};
|
||||
|
||||
use futures::prelude::*;
|
||||
use libp2p_core::{identity, InboundUpgrade, OutboundUpgrade, PeerId, UpgradeInfo};
|
||||
use snow::HandshakeState;
|
||||
use std::pin::Pin;
|
||||
use zeroize::Zeroize;
|
||||
|
||||
@ -78,6 +79,14 @@ pub struct NoiseConfig<P, C: Zeroize, R = ()> {
|
||||
legacy: LegacyConfig,
|
||||
remote: R,
|
||||
_marker: std::marker::PhantomData<P>,
|
||||
|
||||
/// Prologue to use in the noise handshake.
|
||||
///
|
||||
/// The prologue can contain arbitrary data that will be hashed into the noise handshake.
|
||||
/// For the handshake to succeed, both parties must set the same prologue.
|
||||
///
|
||||
/// For further information, see <https://noiseprotocol.org/noise.html#prologue>.
|
||||
prologue: Vec<u8>,
|
||||
}
|
||||
|
||||
impl<H, C: Zeroize, R> NoiseConfig<H, C, R> {
|
||||
@ -87,6 +96,11 @@ impl<H, C: Zeroize, R> NoiseConfig<H, C, R> {
|
||||
NoiseAuthenticated { config: self }
|
||||
}
|
||||
|
||||
/// Set the noise prologue.
|
||||
pub fn with_prologue(self, prologue: Vec<u8>) -> Self {
|
||||
Self { prologue, ..self }
|
||||
}
|
||||
|
||||
/// Sets the legacy configuration options to use, if any.
|
||||
pub fn set_legacy_config(&mut self, cfg: LegacyConfig) -> &mut Self {
|
||||
self.legacy = cfg;
|
||||
@ -94,6 +108,35 @@ impl<H, C: Zeroize, R> NoiseConfig<H, C, R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, C, R> NoiseConfig<H, C, R>
|
||||
where
|
||||
C: Zeroize + AsRef<[u8]>,
|
||||
{
|
||||
fn into_responder(self) -> Result<HandshakeState, NoiseError> {
|
||||
let state = self
|
||||
.params
|
||||
.into_builder()
|
||||
.prologue(self.prologue.as_ref())
|
||||
.local_private_key(self.dh_keys.secret().as_ref())
|
||||
.build_responder()
|
||||
.map_err(NoiseError::from)?;
|
||||
|
||||
Ok(state)
|
||||
}
|
||||
|
||||
fn into_initiator(self) -> Result<HandshakeState, NoiseError> {
|
||||
let state = self
|
||||
.params
|
||||
.into_builder()
|
||||
.prologue(self.prologue.as_ref())
|
||||
.local_private_key(self.dh_keys.secret().as_ref())
|
||||
.build_initiator()
|
||||
.map_err(NoiseError::from)?;
|
||||
|
||||
Ok(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> NoiseConfig<IX, C>
|
||||
where
|
||||
C: Protocol<C> + Zeroize,
|
||||
@ -106,6 +149,7 @@ where
|
||||
legacy: LegacyConfig::default(),
|
||||
remote: (),
|
||||
_marker: std::marker::PhantomData,
|
||||
prologue: Vec::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -122,6 +166,7 @@ where
|
||||
legacy: LegacyConfig::default(),
|
||||
remote: (),
|
||||
_marker: std::marker::PhantomData,
|
||||
prologue: Vec::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -141,6 +186,7 @@ where
|
||||
legacy: LegacyConfig::default(),
|
||||
remote: (),
|
||||
_marker: std::marker::PhantomData,
|
||||
prologue: Vec::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -164,6 +210,7 @@ where
|
||||
legacy: LegacyConfig::default(),
|
||||
remote: (remote_dh, remote_id),
|
||||
_marker: std::marker::PhantomData,
|
||||
prologue: Vec::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,25 +221,22 @@ impl<T, C> InboundUpgrade<T> for NoiseConfig<IX, C>
|
||||
where
|
||||
NoiseConfig<IX, C>: UpgradeInfo,
|
||||
T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
|
||||
C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
|
||||
C: Protocol<C> + AsRef<[u8]> + Zeroize + Clone + Send + 'static,
|
||||
{
|
||||
type Output = (RemoteIdentity<C>, NoiseOutput<T>);
|
||||
type Error = NoiseError;
|
||||
type Future = Handshake<T, C>;
|
||||
|
||||
fn upgrade_inbound(self, socket: T, _: Self::Info) -> Self::Future {
|
||||
let session = self
|
||||
.params
|
||||
.into_builder()
|
||||
.local_private_key(self.dh_keys.secret().as_ref())
|
||||
.build_responder()
|
||||
.map_err(NoiseError::from);
|
||||
let config = self.legacy;
|
||||
let identity = self.dh_keys.clone().into_identity();
|
||||
|
||||
handshake::rt1_responder(
|
||||
socket,
|
||||
session,
|
||||
self.dh_keys.into_identity(),
|
||||
self.into_responder(),
|
||||
identity,
|
||||
IdentityExchange::Mutual,
|
||||
self.legacy,
|
||||
config,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -201,25 +245,22 @@ impl<T, C> OutboundUpgrade<T> for NoiseConfig<IX, C>
|
||||
where
|
||||
NoiseConfig<IX, C>: UpgradeInfo,
|
||||
T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
|
||||
C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
|
||||
C: Protocol<C> + AsRef<[u8]> + Zeroize + Clone + Send + 'static,
|
||||
{
|
||||
type Output = (RemoteIdentity<C>, NoiseOutput<T>);
|
||||
type Error = NoiseError;
|
||||
type Future = Handshake<T, C>;
|
||||
|
||||
fn upgrade_outbound(self, socket: T, _: Self::Info) -> Self::Future {
|
||||
let session = self
|
||||
.params
|
||||
.into_builder()
|
||||
.local_private_key(self.dh_keys.secret().as_ref())
|
||||
.build_initiator()
|
||||
.map_err(NoiseError::from);
|
||||
let legacy = self.legacy;
|
||||
let identity = self.dh_keys.clone().into_identity();
|
||||
|
||||
handshake::rt1_initiator(
|
||||
socket,
|
||||
session,
|
||||
self.dh_keys.into_identity(),
|
||||
self.into_initiator(),
|
||||
identity,
|
||||
IdentityExchange::Mutual,
|
||||
self.legacy,
|
||||
legacy,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -230,25 +271,22 @@ impl<T, C> InboundUpgrade<T> for NoiseConfig<XX, C>
|
||||
where
|
||||
NoiseConfig<XX, C>: UpgradeInfo,
|
||||
T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
|
||||
C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
|
||||
C: Protocol<C> + AsRef<[u8]> + Zeroize + Clone + Send + 'static,
|
||||
{
|
||||
type Output = (RemoteIdentity<C>, NoiseOutput<T>);
|
||||
type Error = NoiseError;
|
||||
type Future = Handshake<T, C>;
|
||||
|
||||
fn upgrade_inbound(self, socket: T, _: Self::Info) -> Self::Future {
|
||||
let session = self
|
||||
.params
|
||||
.into_builder()
|
||||
.local_private_key(self.dh_keys.secret().as_ref())
|
||||
.build_responder()
|
||||
.map_err(NoiseError::from);
|
||||
let legacy = self.legacy;
|
||||
let identity = self.dh_keys.clone().into_identity();
|
||||
|
||||
handshake::rt15_responder(
|
||||
socket,
|
||||
session,
|
||||
self.dh_keys.into_identity(),
|
||||
self.into_responder(),
|
||||
identity,
|
||||
IdentityExchange::Mutual,
|
||||
self.legacy,
|
||||
legacy,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -257,25 +295,22 @@ impl<T, C> OutboundUpgrade<T> for NoiseConfig<XX, C>
|
||||
where
|
||||
NoiseConfig<XX, C>: UpgradeInfo,
|
||||
T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
|
||||
C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
|
||||
C: Protocol<C> + AsRef<[u8]> + Zeroize + Clone + Send + 'static,
|
||||
{
|
||||
type Output = (RemoteIdentity<C>, NoiseOutput<T>);
|
||||
type Error = NoiseError;
|
||||
type Future = Handshake<T, C>;
|
||||
|
||||
fn upgrade_outbound(self, socket: T, _: Self::Info) -> Self::Future {
|
||||
let session = self
|
||||
.params
|
||||
.into_builder()
|
||||
.local_private_key(self.dh_keys.secret().as_ref())
|
||||
.build_initiator()
|
||||
.map_err(NoiseError::from);
|
||||
let legacy = self.legacy;
|
||||
let identity = self.dh_keys.clone().into_identity();
|
||||
|
||||
handshake::rt15_initiator(
|
||||
socket,
|
||||
session,
|
||||
self.dh_keys.into_identity(),
|
||||
self.into_initiator(),
|
||||
identity,
|
||||
IdentityExchange::Mutual,
|
||||
self.legacy,
|
||||
legacy,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -286,25 +321,22 @@ impl<T, C, R> InboundUpgrade<T> for NoiseConfig<IK, C, R>
|
||||
where
|
||||
NoiseConfig<IK, C, R>: UpgradeInfo,
|
||||
T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
|
||||
C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
|
||||
C: Protocol<C> + AsRef<[u8]> + Zeroize + Clone + Send + 'static,
|
||||
{
|
||||
type Output = (RemoteIdentity<C>, NoiseOutput<T>);
|
||||
type Error = NoiseError;
|
||||
type Future = Handshake<T, C>;
|
||||
|
||||
fn upgrade_inbound(self, socket: T, _: Self::Info) -> Self::Future {
|
||||
let session = self
|
||||
.params
|
||||
.into_builder()
|
||||
.local_private_key(self.dh_keys.secret().as_ref())
|
||||
.build_responder()
|
||||
.map_err(NoiseError::from);
|
||||
let legacy = self.legacy;
|
||||
let identity = self.dh_keys.clone().into_identity();
|
||||
|
||||
handshake::rt1_responder(
|
||||
socket,
|
||||
session,
|
||||
self.dh_keys.into_identity(),
|
||||
self.into_responder(),
|
||||
identity,
|
||||
IdentityExchange::Receive,
|
||||
self.legacy,
|
||||
legacy,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -313,7 +345,7 @@ impl<T, C> OutboundUpgrade<T> for NoiseConfig<IK, C, (PublicKey<C>, identity::Pu
|
||||
where
|
||||
NoiseConfig<IK, C, (PublicKey<C>, identity::PublicKey)>: UpgradeInfo,
|
||||
T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
|
||||
C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
|
||||
C: Protocol<C> + AsRef<[u8]> + Zeroize + Clone + Send + 'static,
|
||||
{
|
||||
type Output = (RemoteIdentity<C>, NoiseOutput<T>);
|
||||
type Error = NoiseError;
|
||||
@ -323,10 +355,12 @@ where
|
||||
let session = self
|
||||
.params
|
||||
.into_builder()
|
||||
.prologue(self.prologue.as_ref())
|
||||
.local_private_key(self.dh_keys.secret().as_ref())
|
||||
.remote_public_key(self.remote.0.as_ref())
|
||||
.build_initiator()
|
||||
.map_err(NoiseError::from);
|
||||
|
||||
handshake::rt1_initiator(
|
||||
socket,
|
||||
session,
|
||||
@ -432,7 +466,7 @@ where
|
||||
}
|
||||
|
||||
/// Legacy configuration options.
|
||||
#[derive(Clone, Default)]
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct LegacyConfig {
|
||||
/// Whether to continue sending legacy handshake payloads,
|
||||
/// i.e. length-prefixed protobuf payloads inside a length-prefixed
|
||||
@ -445,3 +479,51 @@ pub struct LegacyConfig {
|
||||
/// libp2p implementations.
|
||||
pub recv_legacy_handshake: bool,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn handshake_hashes_disagree_if_prologue_differs() {
|
||||
let alice = new_xx_config()
|
||||
.with_prologue(b"alice prologue".to_vec())
|
||||
.into_initiator()
|
||||
.unwrap();
|
||||
let bob = new_xx_config()
|
||||
.with_prologue(b"bob prologue".to_vec())
|
||||
.into_responder()
|
||||
.unwrap();
|
||||
|
||||
let alice_handshake_hash = alice.get_handshake_hash();
|
||||
let bob_handshake_hash = bob.get_handshake_hash();
|
||||
|
||||
assert_ne!(alice_handshake_hash, bob_handshake_hash)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handshake_hashes_agree_if_prologue_is_the_same() {
|
||||
let alice = new_xx_config()
|
||||
.with_prologue(b"shared knowledge".to_vec())
|
||||
.into_initiator()
|
||||
.unwrap();
|
||||
let bob = new_xx_config()
|
||||
.with_prologue(b"shared knowledge".to_vec())
|
||||
.into_responder()
|
||||
.unwrap();
|
||||
|
||||
let alice_handshake_hash = alice.get_handshake_hash();
|
||||
let bob_handshake_hash = bob.get_handshake_hash();
|
||||
|
||||
assert_eq!(alice_handshake_hash, bob_handshake_hash)
|
||||
}
|
||||
|
||||
fn new_xx_config() -> NoiseConfig<XX, X25519> {
|
||||
let dh_keys = Keypair::<X25519>::new();
|
||||
let noise_keys = dh_keys
|
||||
.into_authentic(&identity::Keypair::generate_ed25519())
|
||||
.unwrap();
|
||||
|
||||
NoiseConfig::xx(noise_keys)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user