#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![allow(deprecated)] mod io;
mod protocol;
pub use io::handshake::RemoteIdentity;
pub use io::Output;
pub use protocol::Protocol;
#[deprecated(
note = "This type will be made private in the future. Use `libp2p_noise::Config::new` instead to use the noise protocol."
)]
pub type X25519Spec = protocol::x25519_spec::X25519Spec;
#[deprecated(
note = "This type will be made private in the future. Use `libp2p_noise::Config::new` instead to use the noise protocol."
)]
pub type X25519 = protocol::x25519::X25519;
#[deprecated(
note = "This type will be made private in the future. Use `libp2p_noise::Config::new` instead to use the noise protocol."
)]
pub type AuthenticKeypair<T> = protocol::AuthenticKeypair<T>;
#[deprecated(
note = "This type will be made private in the future. Use `libp2p_noise::Config::new` instead to use the noise protocol."
)]
pub type Keypair<T> = protocol::Keypair<T>;
#[deprecated(
note = "This type will be made private in the future. Use `libp2p_noise::Config::new` instead to use the noise protocol."
)]
pub type KeypairIdentity = protocol::KeypairIdentity;
#[deprecated(
note = "This type will be made private in the future. Use `libp2p_noise::Config::new` instead to use the noise protocol."
)]
pub type PublicKey<T> = protocol::PublicKey<T>;
#[deprecated(
note = "This type will be made private in the future. Use `libp2p_noise::Config::new` instead to use the noise protocol."
)]
pub type SecretKey<T> = protocol::SecretKey<T>;
#[deprecated(
note = "This type will be made private in the future. Use `libp2p_noise::Config::new` instead to use the noise protocol."
)]
pub type ProtocolParams = protocol::ProtocolParams;
#[deprecated(
note = "This type will be made private in the future. Use `libp2p_noise::Config::new` instead to use the noise protocol."
)]
pub type IK = protocol::IK;
#[deprecated(
note = "This type will be made private in the future. Use `libp2p_noise::Config::new` instead to use the noise protocol."
)]
pub type IX = protocol::IX;
#[deprecated(
note = "This type will be made private in the future. Use `libp2p_noise::Config::new` instead to use the noise protocol."
)]
pub type XX = protocol::XX;
#[deprecated(
note = "This type has been renamed to drop the `Noise` prefix, refer to it as `noise::Error` instead."
)]
pub type NoiseError = Error;
#[deprecated(
note = "This type has been renamed to drop the `Noise` prefix, refer to it as `noise::Output` instead."
)]
pub type NoiseOutput<T> = Output<T>;
use crate::handshake::State;
use crate::io::handshake;
use futures::future::BoxFuture;
use futures::prelude::*;
use libp2p_core::{InboundUpgrade, OutboundUpgrade, UpgradeInfo};
use libp2p_identity as identity;
use libp2p_identity::PeerId;
use std::fmt;
use std::fmt::Formatter;
use std::pin::Pin;
use zeroize::Zeroize;
#[derive(Clone)]
pub struct Config {
inner: NoiseAuthenticated<XX, X25519Spec, ()>,
}
impl Config {
pub fn new(identity: &identity::Keypair) -> Result<Self, Error> {
Ok(Config {
inner: NoiseAuthenticated::xx(identity)?,
})
}
pub fn with_prologue(mut self, prologue: Vec<u8>) -> Self {
self.inner.config.prologue = prologue;
self
}
}
impl UpgradeInfo for Config {
type Info = &'static [u8];
type InfoIter = std::iter::Once<Self::Info>;
fn protocol_info(&self) -> Self::InfoIter {
std::iter::once(b"/noise")
}
}
impl<T> InboundUpgrade<T> for Config
where
T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
{
type Output = (PeerId, Output<T>);
type Error = Error;
type Future = Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>> + Send>>;
fn upgrade_inbound(self, socket: T, info: Self::Info) -> Self::Future {
self.inner.upgrade_inbound(socket, info)
}
}
impl<T> OutboundUpgrade<T> for Config
where
T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
{
type Output = (PeerId, Output<T>);
type Error = Error;
type Future = Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>> + Send>>;
fn upgrade_outbound(self, socket: T, info: Self::Info) -> Self::Future {
self.inner.upgrade_outbound(socket, info)
}
}
#[deprecated(
note = "Use `libp2p_noise::Config` instead. All other handshake patterns are deprecated and will be removed."
)]
#[derive(Clone)]
pub struct NoiseConfig<P, C: Zeroize, R = ()> {
dh_keys: AuthenticKeypair<C>,
params: ProtocolParams,
legacy: LegacyConfig,
remote: R,
_marker: std::marker::PhantomData<P>,
prologue: Vec<u8>,
}
impl<H, C: Zeroize, R> NoiseConfig<H, C, R> {
pub fn into_authenticated(self) -> NoiseAuthenticated<H, C, R> {
NoiseAuthenticated { config: self }
}
pub fn with_prologue(self, prologue: Vec<u8>) -> Self {
Self { prologue, ..self }
}
#[deprecated(
since = "0.42.0",
note = "`LegacyConfig` will be removed without replacement."
)]
pub fn set_legacy_config(&mut self, cfg: LegacyConfig) -> &mut Self {
self.legacy = cfg;
self
}
}
impl<H, C> NoiseConfig<H, C, ()>
where
C: Zeroize + Protocol<C> + AsRef<[u8]>,
{
fn into_responder<S>(self, socket: S) -> Result<State<S>, Error> {
let session = self
.params
.into_builder(&self.prologue, self.dh_keys.keypair.secret(), None)
.build_responder()?;
let state = State::new(socket, session, self.dh_keys.identity, None, self.legacy);
Ok(state)
}
fn into_initiator<S>(self, socket: S) -> Result<State<S>, Error> {
let session = self
.params
.into_builder(&self.prologue, self.dh_keys.keypair.secret(), None)
.build_initiator()?;
let state = State::new(socket, session, self.dh_keys.identity, None, self.legacy);
Ok(state)
}
}
impl<C> NoiseConfig<IX, C>
where
C: Protocol<C> + Zeroize,
{
pub fn ix(dh_keys: AuthenticKeypair<C>) -> Self {
NoiseConfig {
dh_keys,
params: C::params_ix(),
legacy: { LegacyConfig::default() },
remote: (),
_marker: std::marker::PhantomData,
prologue: Vec::default(),
}
}
}
impl<C> NoiseConfig<XX, C>
where
C: Protocol<C> + Zeroize,
{
pub fn xx(dh_keys: AuthenticKeypair<C>) -> Self {
NoiseConfig {
dh_keys,
params: C::params_xx(),
legacy: { LegacyConfig::default() },
remote: (),
_marker: std::marker::PhantomData,
prologue: Vec::default(),
}
}
}
impl<C> NoiseConfig<IK, C>
where
C: Protocol<C> + Zeroize,
{
pub fn ik_listener(dh_keys: AuthenticKeypair<C>) -> Self {
NoiseConfig {
dh_keys,
params: C::params_ik(),
legacy: { LegacyConfig::default() },
remote: (),
_marker: std::marker::PhantomData,
prologue: Vec::default(),
}
}
}
impl<C> NoiseConfig<IK, C, (PublicKey<C>, identity::PublicKey)>
where
C: Protocol<C> + Zeroize + AsRef<[u8]>,
{
pub fn ik_dialer(
dh_keys: AuthenticKeypair<C>,
remote_id: identity::PublicKey,
remote_dh: PublicKey<C>,
) -> Self {
NoiseConfig {
dh_keys,
params: C::params_ik(),
legacy: { LegacyConfig::default() },
remote: (remote_dh, remote_id),
_marker: std::marker::PhantomData,
prologue: Vec::default(),
}
}
fn into_initiator<S>(self, socket: S) -> Result<State<S>, Error> {
let session = self
.params
.into_builder(
&self.prologue,
self.dh_keys.keypair.secret(),
Some(&self.remote.0),
)
.build_initiator()?;
let state = State::new(
socket,
session,
self.dh_keys.identity,
Some(self.remote.1),
self.legacy,
);
Ok(state)
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[error(transparent)]
Io(#[from] std::io::Error),
#[error(transparent)]
Noise(#[from] snow::Error),
#[error("Invalid public key")]
InvalidKey(#[from] libp2p_identity::DecodingError),
#[error("Only keys of length 32 bytes are supported")]
InvalidLength,
#[error("Remote authenticated with an unexpected public key")]
UnexpectedKey,
#[error("The signature of the remote identity's public key does not verify")]
BadSignature,
#[error("Authentication failed")]
AuthenticationFailed,
#[error(transparent)]
InvalidPayload(DecodeError),
#[error(transparent)]
SigningError(#[from] libp2p_identity::SigningError),
}
#[derive(Debug, thiserror::Error)]
pub struct DecodeError(String);
impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<quick_protobuf::Error> for DecodeError {
fn from(e: quick_protobuf::Error) -> Self {
Self(e.to_string())
}
}
impl From<quick_protobuf::Error> for Error {
fn from(e: quick_protobuf::Error) -> Self {
Error::InvalidPayload(e.into())
}
}
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 + Clone + Send + 'static,
{
type Output = (RemoteIdentity<C>, Output<T>);
type Error = Error;
type Future = BoxFuture<'static, Result<(RemoteIdentity<C>, Output<T>), Error>>;
fn upgrade_inbound(self, socket: T, _: Self::Info) -> Self::Future {
async move {
let mut state = self.into_responder(socket)?;
handshake::recv_identity(&mut state).await?;
handshake::send_identity(&mut state).await?;
state.finish()
}
.boxed()
}
}
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 + Clone + Send + 'static,
{
type Output = (RemoteIdentity<C>, Output<T>);
type Error = Error;
type Future = BoxFuture<'static, Result<(RemoteIdentity<C>, Output<T>), Error>>;
fn upgrade_outbound(self, socket: T, _: Self::Info) -> Self::Future {
async move {
let mut state = self.into_initiator(socket)?;
handshake::send_identity(&mut state).await?;
handshake::recv_identity(&mut state).await?;
state.finish()
}
.boxed()
}
}
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 + Clone + Send + 'static,
{
type Output = (RemoteIdentity<C>, Output<T>);
type Error = Error;
type Future = BoxFuture<'static, Result<(RemoteIdentity<C>, Output<T>), Error>>;
fn upgrade_inbound(self, socket: T, _: Self::Info) -> Self::Future {
async move {
let mut state = self.into_responder(socket)?;
handshake::recv_empty(&mut state).await?;
handshake::send_identity(&mut state).await?;
handshake::recv_identity(&mut state).await?;
state.finish()
}
.boxed()
}
}
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 + Clone + Send + 'static,
{
type Output = (RemoteIdentity<C>, Output<T>);
type Error = Error;
type Future = BoxFuture<'static, Result<(RemoteIdentity<C>, Output<T>), Error>>;
fn upgrade_outbound(self, socket: T, _: Self::Info) -> Self::Future {
async move {
let mut state = self.into_initiator(socket)?;
handshake::send_empty(&mut state).await?;
handshake::recv_identity(&mut state).await?;
handshake::send_identity(&mut state).await?;
state.finish()
}
.boxed()
}
}
impl<T, C> InboundUpgrade<T> for NoiseConfig<IK, C>
where
NoiseConfig<IK, C>: UpgradeInfo,
T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
C: Protocol<C> + AsRef<[u8]> + Zeroize + Clone + Send + 'static,
{
type Output = (RemoteIdentity<C>, Output<T>);
type Error = Error;
type Future = BoxFuture<'static, Result<(RemoteIdentity<C>, Output<T>), Error>>;
fn upgrade_inbound(self, socket: T, _: Self::Info) -> Self::Future {
async move {
let mut state = self.into_responder(socket)?;
handshake::recv_identity(&mut state).await?;
handshake::send_signature_only(&mut state).await?;
state.finish()
}
.boxed()
}
}
impl<T, C> OutboundUpgrade<T> for NoiseConfig<IK, C, (PublicKey<C>, identity::PublicKey)>
where
NoiseConfig<IK, C, (PublicKey<C>, identity::PublicKey)>: UpgradeInfo,
T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
C: Protocol<C> + AsRef<[u8]> + Zeroize + Clone + Send + 'static,
{
type Output = (RemoteIdentity<C>, Output<T>);
type Error = Error;
type Future = BoxFuture<'static, Result<(RemoteIdentity<C>, Output<T>), Error>>;
fn upgrade_outbound(self, socket: T, _: Self::Info) -> Self::Future {
async move {
let mut state = self.into_initiator(socket)?;
handshake::send_identity(&mut state).await?;
handshake::recv_identity(&mut state).await?;
state.finish()
}
.boxed()
}
}
#[derive(Clone)]
#[deprecated(
note = "Use `libp2p_noise::Config` instead. All other handshake patterns are deprecated and will be removed."
)]
pub struct NoiseAuthenticated<P, C: Zeroize, R> {
config: NoiseConfig<P, C, R>,
}
impl NoiseAuthenticated<XX, X25519Spec, ()> {
#[deprecated(note = "Use `libp2p_noise::Config::new` instead.")]
pub fn xx(id_keys: &identity::Keypair) -> Result<Self, Error> {
let dh_keys = Keypair::<X25519Spec>::new();
let noise_keys = dh_keys.into_authentic(id_keys)?;
let config = NoiseConfig::xx(noise_keys);
Ok(config.into_authenticated())
}
}
impl<P, C: Zeroize, R> UpgradeInfo for NoiseAuthenticated<P, C, R>
where
NoiseConfig<P, C, R>: UpgradeInfo,
{
type Info = <NoiseConfig<P, C, R> as UpgradeInfo>::Info;
type InfoIter = <NoiseConfig<P, C, R> as UpgradeInfo>::InfoIter;
fn protocol_info(&self) -> Self::InfoIter {
self.config.protocol_info()
}
}
impl<T, P, C, R> InboundUpgrade<T> for NoiseAuthenticated<P, C, R>
where
NoiseConfig<P, C, R>: UpgradeInfo
+ InboundUpgrade<T, Output = (RemoteIdentity<C>, Output<T>), Error = Error>
+ 'static,
<NoiseConfig<P, C, R> as InboundUpgrade<T>>::Future: Send,
T: AsyncRead + AsyncWrite + Send + 'static,
C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
{
type Output = (PeerId, Output<T>);
type Error = Error;
type Future = Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>> + Send>>;
fn upgrade_inbound(self, socket: T, info: Self::Info) -> Self::Future {
Box::pin(
self.config
.upgrade_inbound(socket, info)
.and_then(|(remote, io)| match remote {
RemoteIdentity::IdentityKey(pk) => future::ok((pk.to_peer_id(), io)),
_ => future::err(Error::AuthenticationFailed),
}),
)
}
}
impl<T, P, C, R> OutboundUpgrade<T> for NoiseAuthenticated<P, C, R>
where
NoiseConfig<P, C, R>: UpgradeInfo
+ OutboundUpgrade<T, Output = (RemoteIdentity<C>, Output<T>), Error = Error>
+ 'static,
<NoiseConfig<P, C, R> as OutboundUpgrade<T>>::Future: Send,
T: AsyncRead + AsyncWrite + Send + 'static,
C: Protocol<C> + AsRef<[u8]> + Zeroize + Send + 'static,
{
type Output = (PeerId, Output<T>);
type Error = Error;
type Future = Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>> + Send>>;
fn upgrade_outbound(self, socket: T, info: Self::Info) -> Self::Future {
Box::pin(
self.config
.upgrade_outbound(socket, info)
.and_then(|(remote, io)| match remote {
RemoteIdentity::IdentityKey(pk) => future::ok((pk.to_peer_id(), io)),
_ => future::err(Error::AuthenticationFailed),
}),
)
}
}
#[derive(Clone, Copy, Default)]
#[deprecated(
since = "0.42.0",
note = "`LegacyConfig` will be removed without replacement."
)]
pub struct LegacyConfig {
pub send_legacy_handshake: bool,
pub recv_legacy_handshake: bool,
}