Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Data type links in doc cmts
Browse files Browse the repository at this point in the history
rrybarczyk committed Sep 12, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent bea943a commit 424f8c8
Showing 6 changed files with 144 additions and 139 deletions.
21 changes: 11 additions & 10 deletions protocols/v2/noise-sv2/src/aed_cipher.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//! # AEAD Cipher Trait
//!
//! Defines the `AeadCipher` trait which standardizes the interface for Authenticated Encryption
//! Defines the [`AeadCipher`] trait which standardizes the interface for Authenticated Encryption
//! with Associated Data (AEAD) ciphers used within the Noise protocol implementation. The trait is
//! implemented for two common cipher, `ChaCha20Poly1305` and `Aes256Gcm`, providing encryption and
//! decryption functionality with authenticated data.
//! implemented for two common cipher, [`ChaCha20Poly1305`] and [`Aes256Gcm`], providing encryption
//! and decryption functionality with authenticated data.
//!
//! ## Overview
//!
@@ -13,22 +13,23 @@
//!
//! ## Usage
//!
//! The `AeadCipher` trait is used by the `HandshakeOp` trait to perform cryptographic operations
//! during the Noise protocol handshake, ensuring secure communication between parties.
//! The [`AeadCipher`] trait is used by the [`crate::handshake::HandshakeOp`] trait to perform
//! cryptographic operations during the Noise protocol handshake, ensuring secure communication
//! between parties.
use aes_gcm::Aes256Gcm;
use chacha20poly1305::{aead::Buffer, AeadInPlace, ChaCha20Poly1305, ChaChaPoly1305, KeyInit};

/// Defines the interface for AEAD ciphers.
///
/// The `AeadCipher` trait provides a standard interface for initializing AEAD ciphers, and for
/// The [`AeadCipher`] trait provides a standard interface for initializing AEAD ciphers, and for
/// performing encryption and decryption operations with additional AAD. This trait is implemented
/// by either the `ChaCha20Poly1305` or `Aes256Gcm` specific cipher types, allowing them to be used
/// interchangeably in cryptographic protocols. It is utilized by the `HandshakeOp` trait to secure
/// the handshake process.
/// by either the [`ChaCha20Poly1305`] or [`Aes256Gcm`] specific cipher types, allowing them to be
/// used interchangeably in cryptographic protocols. It is utilized by the
/// [`crate::handshake::HandshakeOp`] trait to secure the handshake process.
///
/// The `T: Buffer` represents the data buffer to be encrypted or decrypted. The buffer must
/// implement the `Buffer` trait, which provides necessary operations for in-place encryption and
/// implement the [`Buffer`] trait, which provides necessary operations for in-place encryption and
/// decryption.
pub trait AeadCipher {
/// Creates a new instance of the cipher from a 32-byte key.
59 changes: 30 additions & 29 deletions protocols/v2/noise-sv2/src/cipher_state.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! # AEAD Cipher Management
//!
//! The `CipherState` trait manages the state and operations of Authenticated Encryption with
//! The [`CipherState`] trait manages the state and operations of Authenticated Encryption with
//! Associated Data (AEAD) ciphers within cryptographic protocols.
//!
//! ## Overview
@@ -9,19 +9,19 @@
//! ensuring the underlying cryptographic details are consistently handled across different cipher
//! implementations.
//!
//! The module also includes the `GenericCipher` enum, which allows for the use of different AEAD
//! The module also includes the [`GenericCipher`] enum, which allows for the use of different AEAD
//! cipher implementations in a generic manner.
//!
//! ## Usage
//!
//! The `CipherState` trait is used by the `HandshakeOp` trait to handle the stateful encryption
//! and decryption tasks required during the Noise protocol handshake. By implementing
//! `CipherState`, handshake operations securely manage cryptographic material and perform
//! necessary transformations on messages exchanged between the initiator and responder.
//! The [`CipherState`] trait is used by the [`crate::handshake::HandshakeOp`] trait to handle the
//! stateful encryption and decryption tasks required during the Noise protocol handshake. By
//! implementing [`CipherState`], handshake operations securely manage cryptographic material and
//! perform necessary transformations on messages exchanged between the initiator and responder.
//!
//! The `Initiator` and `Responder` structs use `GenericCipher` instances (`c1` and `c2`) to
//! perform symmetric encryption and decryption once the Noise handshake is complete. These
//! ciphers, initialized and managed through the `CipherState` trait, ensure that ongoing
//! The [`crate::Initiator`] and [`crate::Responder`] structs use [`GenericCipher`] instances (`c1`
//! and `c2`) to perform symmetric encryption and decryption once the Noise handshake is complete.
//! These ciphers, initialized and managed through the [`CipherState`] trait, ensure that ongoing
//! communication remains confidential and authenticated.
use std::ptr;
@@ -36,8 +36,8 @@ use chacha20poly1305::{aead::Buffer, ChaCha20Poly1305};
/// encryption key (`k`), nonce (`n`), and the cipher instance itself. It also provides methods for
/// encrypting and decrypting data with additional associated data (AAD) using the managed cipher.
///
/// `CipherState` is typically implemented by structs that need to manage cipher state as part of a
/// the Noise protocol handshake.
/// [`CipherState`] is typically implemented by structs that need to manage cipher state as part of
/// a the Noise protocol handshake.
pub trait CipherState<Cipher_: AeadCipher>
where
Self: Sized,
@@ -152,15 +152,15 @@ where

/// An enum representing a generic cipher state.
///
/// `GenericCipher` abstracts over different AEAD cipher implementations, allowing
/// for flexible use of either `ChaCha20Poly1305` or `Aes256Gcm`. It provides methods
/// for encryption, decryption, and key erasure.
/// [`GenericCipher`] abstracts over different AEAD cipher implementations, allowing for flexible
/// use of either [`ChaCha20Poly1305`] or [`Aes256Gcm`]. It provides methods for encryption,
/// decryption, and key erasure.
///
/// A generic cipher that can be either `ChaCha20Poly1305` or `Aes256Gcm`.
/// A generic cipher that can be either [`ChaCha20Poly1305`] or [`Aes256Gcm`].
///
/// The `GenericCipher` enum allows for flexibility in choosing between different AEAD ciphers. It
/// provides methods for encrypting, decrypting, and securely erasing the encryption key, ensuring
/// that sensitive cryptographic material is handled correctly.
/// The [`GenericCipher`] enum allows for flexibility in choosing between different AEAD ciphers.
/// It provides methods for encrypting, decrypting, and securely erasing the encryption key,
/// ensuring that sensitive cryptographic material is handled correctly.
#[allow(clippy::large_enum_variant)]
pub enum GenericCipher {
ChaCha20Poly1305(Cipher<ChaCha20Poly1305>),
@@ -169,9 +169,9 @@ pub enum GenericCipher {
}

impl Drop for GenericCipher {
/// Securely erases the encryption key when the `GenericCipher` is dropped.
/// Securely erases the encryption key when the [`GenericCipher`] is dropped.
///
/// Ensures that the encryption key is securely erased from memory when the `GenericCipher`
/// Ensures that the encryption key is securely erased from memory when the [`GenericCipher`]
/// instance is dropped, preventing any potential leakage of sensitive cryptographic material.
fn drop(&mut self) {
self.erase_k();
@@ -205,8 +205,8 @@ impl GenericCipher {

/// Securely erases the encryption key (`k`) from memory.
///
/// Overwrites the encryption key stored within the `GenericCipher` with zeros and sets it to
/// `None`, ensuring that the key cannot be recovered after the `GenericCipher` is dropped or
/// Overwrites the encryption key stored within the [`GenericCipher`] with zeros and sets it to
/// `None`, ensuring that the key cannot be recovered after the [`GenericCipher`] is dropped or
/// no longer needed.
pub fn erase_k(&mut self) {
match self {
@@ -245,13 +245,14 @@ impl GenericCipher {
}
}

/// Represents the state of an AEAD cipher when using `Aes256Gcm`, including the encryption key and
/// nonce.
/// Represents the state of an AEAD cipher when using [`Aes256Gcm`], including the encryption key
/// and nonce.
///
/// The `Cipher` struct manages the cryptographic state required to perform AEAD encryption and
/// The [`Cipher`] struct manages the cryptographic state required to perform AEAD encryption and
/// decryption operations. It stores the optional 32-byte encryption key (`k`), the nonce (`n`),
/// and the optional cipher instance itself. The `CipherState` trait is implemented for this struct
/// to provide a consistent interface for managing cipher state across different AEAD ciphers.
/// and the optional cipher instance itself. The [`CipherState`] trait is implemented for this
/// struct to provide a consistent interface for managing cipher state across different AEAD
/// ciphers.
impl CipherState<Aes256Gcm> for GenericCipher {
fn get_k(&mut self) -> &mut Option<[u8; 32]> {
match self {
@@ -294,8 +295,8 @@ impl CipherState<Aes256Gcm> for GenericCipher {
///
/// Manages the cryptographic state required to perform AEAD encryption and decryption operations.
/// It stores the optional encryption key, the nonce, and the optional cipher instance itself. The
/// `CipherState` trait is implemented to provide a consistent interface for managing cipher state
/// across different AEAD ciphers.
/// [`CipherState`] trait is implemented to provide a consistent interface for managing cipher
/// state across different AEAD ciphers.
pub struct Cipher<C: AeadCipher> {
/// Optional 32-byte encryption key.
k: Option<[u8; 32]>,
41 changes: 21 additions & 20 deletions protocols/v2/noise-sv2/src/handshake.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
//! # Noise Protocol Handshake Operations
//!
//! The `HandshakeOp` trait defines the essential operations required for executing the Noise
//! The [`HandshakeOp`] trait defines the essential operations required for executing the Noise
//! protocol handshake, a cryptographic procedure used to establish secure communication channels.
//!
//! ## Overview
//!
//! The trait abstracts away the complexities of key management, encryption, and hashing,
//! ensuring consistent and secure operations across different handshake implementations.
//! The trait abstracts away the complexities of key management, encryption, and hashing, ensuring
//! consistent and secure operations across different handshake implementations.
//!
//! The `HandshakeOp` trait is central to managing the cryptographic state during the handshake,
//! The [`HandshakeOp`] trait is central to managing the cryptographic state during the handshake,
//! including the handling of keys, nonces, and encryption tasks necessary to authenticate and
//! secure the communication between parties.
//!
//! ## Usage
//!
//! The `HandshakeOp` trait is typically implemented by roles in the Noise protocol handshake,
//! such as the `Initiator` and `Responder`. These roles leverage the trait to securely manage
//! cryptographic material and perform operations like mixing hashes, encrypting/decrypting
//! messages, and deriving new keys as the handshake progresses.
//! The [`HandshakeOp`] trait is typically implemented by roles in the Noise protocol handshake,
//! such as the [`crate::Initiator`] and [`crate::Responder`]. These roles leverage the trait to
//! securely manage cryptographic material and perform operations like mixing hashes,
//! encrypting/decrypting messages, and deriving new keys as the handshake progresses.
//!
//! Implementation of `HandshakeOp` handles the updating of the handshake hash (`h`), the
//! Implementation of [`HandshakeOp`] handles the updating of the handshake hash (`h`), the
//! chaining key (`ck`), and the encryption key (`k`), ensuring that the cryptographic state
//! remains consistent and secure throughout the handshake process.
//!
//! For example, an `Initiator` and `Responder` would use `HandshakeOp` implementations to perform
//! the necessary steps of the handshake, including the encryption and decryption of messages,
//! while maintaining the integrity and confidentiality of the exchange.
//! For example, an [`crate::Initiator`] and [`crate::Responder`] would use [`HandshakeOp`]
//! implementations to perform the necessary steps of the handshake, including the encryption and
//! decryption of messages, while maintaining the integrity and confidentiality of the exchange.
//!
use crate::{aed_cipher::AeadCipher, cipher_state::CipherState, NOISE_HASHED_PROTOCOL_NAME_CHACHA};
@@ -38,20 +38,21 @@ use secp256k1::{

/// Represents the operations needed during a Noise protocol handshake.
///
/// The `HandshakeOp` trait defines the necessary functions for managing the state and
/// The [`HandshakeOp`] trait defines the necessary functions for managing the state and
/// cryptographic operations required during the Noise protocol handshake. It provides methods for
/// key generation, hash mixing, encryption, decryption, and key derivation, ensuring that the
/// handshake process is secure and consistent.
///
/// ## Associated Types
///
/// * `Cipher: AeadCipher`: Represents the cipher used during the handshake, typically an
/// authenticated encryption with associated data (AEAD) cipher like `ChaCha20Poly1305`.
/// * [`crate::cipher_state::Cipher`]: [`AeadCipher`]: Represents the cipher used during the
/// handshake, typically an authenticated encryption with associated data (AEAD) cipher like
/// [`ChaCha20Poly1305`].
///
/// ## Example
///
/// This trait is implemented for both the `Initiator` and `Responder` structs, allowing them
/// to perform their respective roles in the Noise protocol handshake.
/// This trait is implemented for both the [`crate::Initiator`] and [`crate::Responder`] structs,
/// allowing them to perform their respective roles in the Noise protocol handshake.
///
/// ```rs
/// impl HandshakeOp<ChaCha20Poly1305> for Initiator {
@@ -112,11 +113,11 @@ pub trait HandshakeOp<Cipher: AeadCipher>: CipherState<Cipher> {
*h = Sha256Hash::hash(&to_hash).to_byte_array();
}

/// Generates a new cryptographic key pair using the Secp256k1 curve.
/// Generates a new cryptographic key pair using the [`Secp256k1`] curve.
///
/// Generates a fresh key pair, consisting of a secret key and a corresponding public key,
/// using the Secp256k1 elliptic curve. If the generated public key does not match the expected
/// parity, a new key pair is generated to ensure consistency.
/// using the [`Secp256k1`] elliptic curve. If the generated public key does not match the
/// expected parity, a new key pair is generated to ensure consistency.
fn generate_key() -> Keypair {
let secp = Secp256k1::new();
let (secret_key, _) = secp.generate_keypair(&mut rand::thread_rng());
85 changes: 43 additions & 42 deletions protocols/v2/noise-sv2/src/initiator.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,35 @@
//! # Noise NX Protocol Initiator
//!
//! This module manages the state and operations of the initiator within the Noise NX
//! protocol. This struct plays a crucial role in the cryptographic handshake, establishing a
//! secure communication channel with the responder by performing key exchanges, deriving shared
//! secrets, and encrypting/decrypting handshake messages.
//! This module manages the state and operations of the initiator within the Noise NX protocol.
//! This struct plays a crucial role in the cryptographic handshake, establishing a secure
//! communication channel with the responder by performing key exchanges, deriving shared secrets,
//! and encrypting/decrypting handshake messages.
//!
//! ## Overview
//!
//! The `Initiator` is responsible for generating and managing the necessary cryptographic keys,
//! The [`Initiator`] is responsible for generating and managing the necessary cryptographic keys,
//! including ephemeral and optional static keys, as well as maintaining the state of the handshake
//! process. It interacts with the responder to derive shared secrets and set up secure cipher
//! states that protect subsequent communication. The struct implements the `CipherState` and
//! `HandshakeOp` traits to manage the cryptographic state and operations throughout the handshake.
//! states that protect subsequent communication. The struct implements the
//! [`CipherState`] and [`HandshakeOp`] traits to manage the cryptographic state and operations
//! throughout the handshake.
//!
//! The module utilizes cryptographic components such as ChaCha20Poly1305 for encryption, Elligator
//! Swift for key obfuscation, and Secp256k1 for key generation, ensuring that the handshake is
//! both secure and efficient.
//! The module utilizes cryptographic components such as [`ChaCha20Poly1305`] for encryption,
//! Elligator Swift for key obfuscation, and Secp256k1 for key generation, ensuring that the
//! handshake is both secure and efficient.
//!
//! ## Usage
//!
//! The `Initiator` can be instantiated with or without knowledge of the responder's public key.
//! The [`Initiator`] can be instantiated with or without knowledge of the responder's public key.
//! The handshake process is executed in multiple steps, starting with the generation of an
//! ephemeral keypair and encoding the public key, followed by processing messages exchanged with
//! the responder to derive shared secrets and authenticate the responder. Upon successful
//! completion of the handshake, the `Initiator` sets up cipher states that are used for encrypted
//! completion of the handshake, the [`Initiator`] sets up cipher states that are used for encrypted
//! communication with the responder.
//!
//! ### Example
//!
//! This example demonstrates how to initialize an `Initiator`, perform the first step of the
//! This example demonstrates how to initialize an [`Initiator`], perform the first step of the
//! Noise NX handshake, and handle the responder's reply.
//!
//! ```rust
@@ -59,12 +60,12 @@
//!
//! ## Secure Data Erasure
//!
//! The `Initiator` includes methods to securely erase sensitive cryptographic material,
//! The [`Initiator`] includes methods to securely erase sensitive cryptographic material,
//! preventing any accidental leakage or misuse. This functionality is essential when the instance
//! is no longer needed or is being deallocated.
//!
//! The `Drop` trait is implemented to ensure that this erasure happens automatically when the
//! `Initiator` goes out of scope.
//! The [`Drop`] trait is implemented to ensure that this erasure happens automatically when the
//! [`Initiator`] goes out of scope.
use std::{convert::TryInto, ptr};

@@ -115,11 +116,11 @@ pub struct Initiator {
/// handshake.
#[allow(unused)]
responder_authority_pk: Option<XOnlyPublicKey>,
/// First `CipherState` used for encrypting messages from the initiator to the responder after
/// the handshake is complete.
/// First [`CipherState`] used for encrypting messages from the initiator to the responder
/// after the handshake is complete.
c1: Option<GenericCipher>,
/// Second `CipherState` used for encrypting messages from the responder to the initiator after
/// the handshake is complete.
/// Second [`CipherState`] used for encrypting messages from the responder to the initiator
/// after the handshake is complete.
c2: Option<GenericCipher>,
}

@@ -129,8 +130,8 @@ impl std::fmt::Debug for Initiator {
}
}

// Make sure that Initiator is not sync so we do not need to worry about what other memory accessor see
// after that we zeroize k is send cause if we send it the original thread can not access
// Make sure that Initiator is not sync so we do not need to worry about what other memory accessor
// see after that we zeroize k is send cause if we send it the original thread can not access
// anymore it
//impl<C: AeadCipher> !Sync for Initiator<C> {}
//impl<C: AeadCipher> !Copy for Initiator<C> {}
@@ -184,7 +185,7 @@ impl HandshakeOp<ChaCha20Poly1305> for Initiator {
}

impl Initiator {
/// Creates a new `Initiator` instance with an optional responder public key.
/// Creates a new [`Initiator`] instance with an optional responder public key.
///
/// If the responder public key is provided, the initiator uses this key to authenticate the
/// responder during the handshake. The initial initiator state is instantiated with the
@@ -205,11 +206,11 @@ impl Initiator {
Box::new(self_)
}

/// Creates a new `Initiator` instance using a raw 32-byte public key.
/// Creates a new [`Initiator`] instance using a raw 32-byte public key.
///
/// Constructs a `XOnlyPublicKey` from the provided raw key slice and initializes a new
/// `Initiator` with the derived public key. If the provided key cannot be converted into a
/// valid `XOnlyPublicKey`, an `InvalidRawPublicKey` error is returned.
/// Constructs a [`XOnlyPublicKey`] from the provided raw key slice and initializes a new
/// [`Initiator`] with the derived public key. If the provided key cannot be converted into a
/// valid [`XOnlyPublicKey`], an [`Error::InvalidRawPublicKey`] error is returned.
///
/// Typically used when the initiator is aware of the responder's public key in advance.
pub fn from_raw_k(key: [u8; 32]) -> Result<Box<Self>, Error> {
@@ -218,8 +219,8 @@ impl Initiator {
Ok(Self::new(Some(pk)))
}

/// Creates a new `Initiator` without specifying a responder's public key.
/// This function initializes the `Initiator` with a default empty state.
/// Creates a new [`Initiator`] without specifying a responder's public key.
/// This function initializes the [`Initiator`] with a default empty state.
pub fn without_pk() -> Result<Box<Self>, Error> {
Ok(Self::new(None))
}
@@ -234,7 +235,7 @@ impl Initiator {
/// the responder.
///
/// On success, the function returns a 64-byte array containing the encoded public key.
/// If an error occurs during encryption, it returns an `aes_gcm::Error`.
/// If an error occurs during encryption, it returns an [`aes_gcm::Error`].
pub fn step_0(&mut self) -> Result<[u8; ELLSWIFT_ENCODING_SIZE], aes_gcm::Error> {
let elliswift_enc_pubkey = ElligatorSwift::from_pubkey(self.e.public_key()).to_array();
self.mix_hash(&elliswift_enc_pubkey);
@@ -247,22 +248,22 @@ impl Initiator {

/// Processes the second step of the Noise NX protocol handshake for the initiator.
///
/// This method handles the responder's reply in the Noise NX protocol handshake, processing the
/// message to derive shared secrets and authenticate the responder. It interprets the first 64
/// bytes of the message as the responder's ephemeral public key, decodes it, and mixes it into the
/// handshake state. It then derives a shared secret from the ephemeral keys and updates the state
/// accordingly.
/// This method handles the responder's reply in the Noise NX protocol handshake, processing
/// the message to derive shared secrets and authenticate the responder. It interprets the
/// first 64 bytes of the message as the responder's ephemeral public key, decodes it, and
/// mixes it into the handshake state. It then derives a shared secret from the ephemeral keys
/// and updates the state accordingly.
///
/// The next 80 bytes of the message contain the responder's static public key, encrypted and
/// authenticated. The method decrypts this segment and derives another shared secret using the
/// responder's static public key, further securing the handshake state. Finally, the method
/// decrypts and verifies the signature included in the message to ensure the responder's
/// authenticity.
///
/// On success, this method returns a `NoiseCodec` instance initialized with session ciphers for
/// secure communication. If the provided `message` has an incorrect length, it returns an
/// `Error::InvalidMessageLength`. If decryption or signature verification fails, it returns an
/// `Error::InvalidCertificate`.
/// On success, this method returns a [`NoiseCodec`] instance initialized with session ciphers
/// for secure communication. If the provided `message` has an incorrect length, it returns an
/// [`Error::InvalidMessageLength`]. If decryption or signature verification fails, it returns
/// an [`Error::InvalidCertificate`].
pub fn step_2(
&mut self,
message: [u8; INITIATOR_EXPECTED_HANDSHAKE_MESSAGE_SIZE],
@@ -354,10 +355,10 @@ impl Initiator {

/// Securely erases sensitive data in the initiator's memory.
///
/// Clears all sensitive cryptographic material within the `Initiator` to prevent any
/// Clears all sensitive cryptographic material within the [`Initiator`] to prevent any
/// accidental leakage or misuse. It overwrites the stored keys, chaining key, handshake hash,
/// and session ciphers with zeros or other non-sensitive values. This method is typically
/// called when the `Initiator` instance is no longer needed or before deallocation.
/// called when the [`Initiator`] instance is no longer needed or before deallocation.
fn erase(&mut self) {
if let Some(k) = self.k.as_mut() {
for b in k {
@@ -380,7 +381,7 @@ impl Initiator {
}
}
impl Drop for Initiator {
/// Ensures that sensitive data is securely erased when the `Initiator` instance is dropped,
/// Ensures that sensitive data is securely erased when the [`Initiator`] instance is dropped,
/// preventing any potential leakage of cryptographic material.
fn drop(&mut self) {
self.erase();
56 changes: 28 additions & 28 deletions protocols/v2/noise-sv2/src/responder.rs
Original file line number Diff line number Diff line change
@@ -6,32 +6,32 @@
//!
//! ## Overview
//!
//! The `Responder` is responsible for handling the cryptographic handshake with an initiator,
//! The [`Responder`] is responsible for handling the cryptographic handshake with an initiator,
//! including the generation and management of ephemeral and static keys, the derivation of shared
//! secrets, and the encryption and decryption of handshake messages. Once the handshake is
//! complete, the `Responder` facilitates secure communication by managing the necessary cipher
//! complete, the [`Responder`] facilitates secure communication by managing the necessary cipher
//! states.
//!
//! The module integrates various cryptographic components, such as ChaCha20Poly1305 for
//! encryption, Secp256k1 for key generation, and ElligatorSwift for key obfuscation, ensuring
//! The module integrates various cryptographic components, such as [`ChaCha20Poly1305`] for
//! encryption, [`Secp256k1`] for key generation, and ElligatorSwift for key obfuscation, ensuring
//! robust security throughout the handshake and subsequent message exchanges.
//!
//! ## Usage
//!
//! The `Responder` is typically instantiated with an authority keypair and a certificate validity
//! The [`Responder`] is typically instantiated with an authority keypair and a certificate validity
//! duration. The handshake process is initiated by receiving an ephemeral public key from the
//! initiator, after which the responder generates the necessary response message, including its
//! own ephemeral public key and encrypted static key. The handshake concludes with the derivation
//! of session keys used for ongoing encrypted communication.
//!
//! The `Responder` struct implements the `CipherState` and `HandshakeOp` traits to manage its
//! internal cryptographic state, including key management, nonce generation, and message
//! The [`Responder`] struct implements the [`CipherState`] and [`HandshakeOp`] traits to manage
//! its internal cryptographic state, including key management, nonce generation, and message
//! encryption/decryption. These traits abstract away the underlying cryptographic operations,
//! ensuring that the protocol's security guarantees are consistently enforced.
//!
//! ### Example
//!
//! In this example, the `Responder` is initialized, and the first step of the Noise NX handshake
//! In this example, the [`Responder`] is initialized, and the first step of the Noise NX handshake
//! is performed, resulting in a response message to be sent to the initiator and the setup of
//! session ciphers for secure communication.
//!
@@ -113,11 +113,11 @@ pub struct Responder {
///
/// Used to sign messages and verify the identity of the responder.
a: Keypair,
/// First `CipherState` used for encrypting messages from the initiator to the responder after
/// the handshake is complete.
/// First [`CipherState`] used for encrypting messages from the initiator to the responder
/// after the handshake is complete.
c1: Option<GenericCipher>,
/// Second `CipherState` used for encrypting messages from the responder to the initiator after
/// the handshake is complete.
/// Second [`CipherState`] used for encrypting messages from the responder to the initiator
/// after the handshake is complete.
c2: Option<GenericCipher>,
/// Validity duration of the responder's certificate, in seconds.
cert_validity: u32,
@@ -189,10 +189,10 @@ impl HandshakeOp<ChaCha20Poly1305> for Responder {
}

impl Responder {
/// Creates a new `Responder` instance with the provided authority keypair and certificate
/// Creates a new [`Responder`] instance with the provided authority keypair and certificate
/// validity.
///
/// Constructs a new `Responder` with the necessary cryptographic state for the Noise NX protocol
/// Constructs a new [`Responder`] with the necessary cryptographic state for the Noise NX protocol
/// handshake. It generates ephemeral and static key pairs for the responder and prepares the
/// handshake state. The authority keypair and certificate validity period are also configured.
pub fn new(a: Keypair, cert_validity: u32) -> Box<Self> {
@@ -213,9 +213,9 @@ impl Responder {
Box::new(self_)
}

/// Creates a new `Responder` instance with the provided 32-byte authority key pair.
/// Creates a new [`Responder`] instance with the provided 32-byte authority key pair.
///
/// Constructs a new `Responder` with a given public and private key pair, which represents
/// Constructs a new [`Responder`] with a given public and private key pair, which represents
/// the responder's authority credentials. It verifies that the provided public key matches the
/// corresponding private key, ensuring the authenticity of the authority key pair. The
/// certificate validity duration is also set here. Fails if the key pair is mismatched.
@@ -238,18 +238,18 @@ impl Responder {
/// Processes the first step of the Noise NX protocol handshake for the responder.
///
/// This function manages the responder's side of the handshake after receiving the initiator's
/// initial message. It processes the ephemeral public key provided by the initiator, derives the
/// necessary shared secrets, and constructs the response message. The response includes the
/// responder's ephemeral public key (in its ElligatorSwift-encoded form), the encrypted static
/// public key, and a signature noise message. Additionally, it establishes the session ciphers
/// for encrypting and decrypting further communication.
/// initial message. It processes the ephemeral public key provided by the initiator, derives
/// the necessary shared secrets, and constructs the response message. The response includes
/// the responder's ephemeral public key (in its ElligatorSwift-encoded form), the encrypted
/// static public key, and a signature noise message. Additionally, it establishes the session
/// ciphers for encrypting and decrypting further communication.
///
/// On success, it returns a tuple containing the response message to be sent back to the
/// initiator and a `NoiseCodec` instance, which is configured with the session ciphers for secure
/// transmission of subsequent messages.
/// initiator and a [`NoiseCodec`] instance, which is configured with the session ciphers for
/// secure transmission of subsequent messages.
///
/// On failure, the method returns an error if there is an issue during encryption, decryption, or
/// any other step of the handshake process.
/// On failure, the method returns an error if there is an issue during encryption, decryption,
/// or any other step of the handshake process.
pub fn step_1(
&mut self,
elligatorswift_theirs_ephemeral_serialized: [u8; ELLSWIFT_ENCODING_SIZE],
@@ -374,10 +374,10 @@ impl Responder {

/// Securely erases sensitive data in the responder's memory.
///
/// Clears all sensitive cryptographic material within the `Responder` to prevent any
/// Clears all sensitive cryptographic material within the [`Responder`] to prevent any
/// accidental leakage or misuse. It overwrites the stored keys, chaining key, handshake hash,
/// and session ciphers with zeros or other non-sensitive values. This function is typically
/// called when the `Responder` instance is no longer needed or before deallocation.
/// called when the [`Responder`] instance is no longer needed or before deallocation.
fn erase(&mut self) {
if let Some(k) = self.k.as_mut() {
for b in k {
@@ -403,7 +403,7 @@ impl Responder {
}

impl Drop for Responder {
/// Ensures that sensitive data is securely erased when the `Responder` instance is dropped,
/// Ensures that sensitive data is securely erased when the [`Responder`] instance is dropped,
/// preventing any potential leakage of cryptographic material.
fn drop(&mut self) {
self.erase();
21 changes: 11 additions & 10 deletions protocols/v2/noise-sv2/src/signature_message.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
//! # Signature-Based Messages Handling
//!
//! Defines the `SignatureNoiseMessage` struct, which represents a signed message used in the
//! Defines the [`SignatureNoiseMessage`] struct, which represents a signed message used in the
//! Noise protocol to authenticate and verify the identity of a party during the handshake. It
//! includes functionality for signing and verifying messages using Schnorr signatures with the
//! `secp256k1` elliptic curve.
//! [`secp256k1`] elliptic curve.
//!
//! ## Usage
//!
//! The `SignatureNoiseMessage` is used in both the `Responder` and `Initiator` during the Noise
//! handshake to ensure that messages are authentic and have not been tampered with.
//! The [`SignatureNoiseMessage`] is used in both the [`crate::Responder`] and [`crate::Initiator`]
//! during the Noise handshake to ensure that messages are authentic and have not been tampered
//! with.
use secp256k1::{hashes::sha256, schnorr::Signature, Keypair, Message, Secp256k1, XOnlyPublicKey};
use std::{convert::TryInto, time::SystemTime};

/// `SignatureNoiseMessage` is a structure that encapsulates a cryptographic signature message
/// [`SignatureNoiseMessage`] is a structure that encapsulates a cryptographic signature message
/// used in the Noise NX protocol. This message includes versioning and timestamp information,
/// ensuring that the signature is valid only within a specific time window.
pub struct SignatureNoiseMessage {
@@ -28,9 +29,9 @@ pub struct SignatureNoiseMessage {
}

impl From<[u8; 74]> for SignatureNoiseMessage {
/// Converts a 74-byte array into a `SignatureNoiseMessage`.
/// Converts a 74-byte array into a [`SignatureNoiseMessage`].
///
/// Allows a raw 74-byte array to be converted into a `SignatureNoiseMessage`, extracting the
/// Allows a raw 74-byte array to be converted into a [`SignatureNoiseMessage`], extracting the
/// version, validity periods, and signature from the provided data. Panics if the byte array
/// cannot be correctly converted into the struct fields.
fn from(value: [u8; 74]) -> Self {
@@ -48,7 +49,7 @@ impl From<[u8; 74]> for SignatureNoiseMessage {
}

impl SignatureNoiseMessage {
/// Verifies the `SignatureNoiseMessage` against the provided public key and an optional
/// Verifies the [`SignatureNoiseMessage`] against the provided public key and an optional
/// authority public key. The verification checks that the message is currently valid
/// (i.e., within the `valid_from` and `not_valid_after` time window) and that the signature
/// is correctly signed by the authority.
@@ -80,7 +81,7 @@ impl SignatureNoiseMessage {
}
}

/// Signs a `SignatureNoiseMessage` using the provided keypair (`kp`).
/// Signs a [`SignatureNoiseMessage`] using the provided keypair (`kp`).
///
/// Creates a Schnorr signature for the message, combining the version, validity period, and
/// the static public key of the server (`static_pk`). The resulting signature is then written
@@ -95,7 +96,7 @@ impl SignatureNoiseMessage {
}
}

/// Splits the `SignatureNoiseMessage` into its component parts: the message hash and the
/// Splits the [`SignatureNoiseMessage`] into its component parts: the message hash and the
/// signature.
///
/// Separates the message into the first 10 bytes (containing the version and validity period)

0 comments on commit 424f8c8

Please sign in to comment.