Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 48 additions & 73 deletions aead/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub use arrayvec;
#[cfg(feature = "bytes")]
pub use bytes;
#[cfg(feature = "rand_core")]
pub use crypto_common::rand_core;
pub use crypto_common::{Generate, rand_core};
pub use inout;

use core::fmt;
Expand All @@ -40,10 +40,6 @@ use inout::InOutBuf;
use alloc::vec::Vec;
#[cfg(feature = "bytes")]
use bytes::BytesMut;
#[cfg(feature = "getrandom")]
use crypto_common::getrandom;
#[cfg(feature = "rand_core")]
use rand_core::{CryptoRng, TryCryptoRng};

/// Error type.
///
Expand All @@ -63,7 +59,53 @@ impl fmt::Display for Error {

impl core::error::Error for Error {}

/// Nonce: single-use value for ensuring ciphertexts are unique
/// Nonce: single-use value for ensuring ciphertexts are unique.
///
/// AEAD algorithms accept a parameter to encryption/decryption called
/// a "nonce" which must be unique every time encryption is performed and
/// never repeated for the same key. The nonce is often prepended to the
/// ciphertext, a.k.a. an explicit nonce, but may also be an implicit counter.
///
/// AEAD decryption takes the nonce which was originally used to produce a
/// given ciphertext as a parameter along with the ciphertext itself.
///
/// # Generating random nonces
///
/// Nonces don't necessarily have to be random, but it is a simple strategy
/// which can be implemented as follows using the [`Generate`] trait
/// (requires `getrandom` feature):
///
/// ```text
/// use aead::{Nonce, Generate};
///
/// let nonce = Nonce::<AeadAlg>::generate();
/// ```
///
/// <div class="warning">
/// AEAD algorithms often fail catastrophically if nonces are ever repeated
/// (with SIV modes being an exception).
///
/// Using random nonces runs the risk of repeating them unless the nonce
/// size is particularly large, e.g. 192-bit extended nonces used by the
/// `XChaCha20Poly1305` and `XSalsa20Poly1305` constructions.
///
/// [NIST SP 800-38D] recommends the following:
///
/// > The total number of invocations of the authenticated encryption
/// > function shall not exceed 2<sup>32</sup>, including all IV lengths and all
/// > instances of the authenticated encryption function with the given key.
///
/// Following this guideline, only 4,294,967,296 messages with random
/// nonces can be encrypted under a given key. While this bound is high,
/// it's possible to encounter in practice, and systems which might
/// reach it should consider alternatives to purely random nonces, like
/// a counter or a combination of a random nonce + counter.
///
/// See the [`aead-stream`] crate for a ready-made implementation of the latter.
/// </div>
///
/// [NIST SP 800-38D]: https://csrc.nist.gov/publications/detail/sp/800-38d/final
/// [`aead-stream`]: https://docs.rs/aead-stream
pub type Nonce<A> = Array<u8, <A as AeadCore>::NonceSize>;

/// Tag: authentication code which ensures ciphertexts are authentic
Expand All @@ -88,73 +130,6 @@ pub trait AeadCore {

/// The AEAD tag position.
const TAG_POSITION: TagPosition;

/// Generate a random nonce for this AEAD algorithm.
///
/// AEAD algorithms accept a parameter to encryption/decryption called
/// a "nonce" which must be unique every time encryption is performed and
/// never repeated for the same key. The nonce is often prepended to the
/// ciphertext. The nonce used to produce a given ciphertext must be passed
/// to the decryption function in order for it to decrypt correctly.
///
/// Nonces don't necessarily have to be random, but it is one strategy
/// which is implemented by this function.
///
/// # ⚠️Security Warning
///
/// AEAD algorithms often fail catastrophically if nonces are ever repeated
/// (with SIV modes being an exception).
///
/// Using random nonces runs the risk of repeating them unless the nonce
/// size is particularly large (e.g. 192-bit extended nonces used by the
/// `XChaCha20Poly1305` and `XSalsa20Poly1305` constructions.
///
/// [NIST SP 800-38D] recommends the following:
///
/// > The total number of invocations of the authenticated encryption
/// > function shall not exceed 2^32, including all IV lengths and all
/// > instances of the authenticated encryption function with the given key.
///
/// Following this guideline, only 4,294,967,296 messages with random
/// nonces can be encrypted under a given key. While this bound is high,
/// it's possible to encounter in practice, and systems which might
/// reach it should consider alternatives to purely random nonces, like
/// a counter or a combination of a random nonce + counter.
///
/// See the [`aead-stream`] crate for a ready-made implementation of the latter.
///
/// [NIST SP 800-38D]: https://csrc.nist.gov/publications/detail/sp/800-38d/final
/// [`aead-stream`]: https://docs.rs/aead-stream
#[cfg(feature = "getrandom")]
fn generate_nonce() -> core::result::Result<Nonce<Self>, getrandom::Error> {
let mut nonce = Nonce::<Self>::default();
getrandom::fill(&mut nonce)?;
Ok(nonce)
}

/// Generate a random nonce for this AEAD algorithm using the specified [`CryptoRng`].
///
/// See [`AeadCore::generate_nonce`] documentation for requirements for
/// random nonces.
#[cfg(feature = "rand_core")]
fn generate_nonce_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Nonce<Self> {
let mut nonce = Nonce::<Self>::default();
rng.fill_bytes(&mut nonce);
nonce
}

/// Generate a random nonce for this AEAD algorithm using the specified [`TryCryptoRng`].
///
/// See [`AeadCore::generate_nonce`] documentation for requirements for
/// random nonces.
#[cfg(feature = "rand_core")]
fn try_generate_nonce_with_rng<R: TryCryptoRng + ?Sized>(
rng: &mut R,
) -> core::result::Result<Nonce<Self>, R::Error> {
let mut nonce = Nonce::<Self>::default();
rng.try_fill_bytes(&mut nonce)?;
Ok(nonce)
}
}

/// Authenticated Encryption with Associated Data (AEAD) algorithm.
Expand Down
4 changes: 2 additions & 2 deletions crypto-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ mod generate;
pub use hybrid_array as array;
pub use hybrid_array::typenum;

#[cfg(feature = "getrandom")]
pub use getrandom::Error as RngError;
#[cfg(feature = "rand_core")]
pub use {generate::Generate, rand_core};
#[cfg(feature = "getrandom")]
pub use {getrandom, getrandom::Error as RngError};

use core::fmt;
use hybrid_array::{
Expand Down