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
9 changes: 5 additions & 4 deletions .github/workflows/crypto-common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ jobs:
targets: ${{ matrix.target }}
- run: cargo build --target ${{ matrix.target }}

minimal-versions:
uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master
with:
working-directory: ${{ github.workflow }}
# TODO(tarcieri): re-enable when `getrandom` has a crate release with `sys_rng`
# minimal-versions:
# uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master
# with:
# working-directory: ${{ github.workflow }}

test:
runs-on: ubuntu-latest
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ members = [
[patch.crates-io]
digest = { path = "digest" }
signature = { path = "signature" }

getrandom = { git = "https://github.com/rust-random/getrandom" }
6 changes: 6 additions & 0 deletions crypto-common/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## 0.2.0 (UNRELEASED)
### Added
- Sealed `BlockSizes` trait implemented for types from `U1` to `U255`
- `Generate` trait ([#2096])

### Changed
- `BlockUser::BlockSize` is now bounded by the `BlockSizes` trait
- Edition changed to 2024 and MSRV bumped to 1.85 ([#1759])

### Removed
- `generate_*` and `try_generate_*` methods from KeyInit and KeyIvInit traits.
See the newly added Generate trait for replacement ([#2096])

[#1759]: https://github.com/RustCrypto/traits/pull/1759
[#2096]: https://github.com/RustCrypto/traits/pull/2096

## 0.1.7 (2025-11-12)
### Changed
Expand Down
4 changes: 2 additions & 2 deletions crypto-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ description = "Common cryptographic traits"
hybrid-array = "0.4"

# optional dependencies
getrandom = { version = "0.3", optional = true, default-features = false }
getrandom = { version = "0.3", optional = true, features = ["sys_rng"] }
rand_core = { version = "0.10.0-rc-2", optional = true }

[features]
getrandom = ["dep:getrandom"]
getrandom = ["rand_core", "dep:getrandom"]
rand_core = ["dep:rand_core"]
zeroize = ["hybrid-array/zeroize"]

Expand Down
86 changes: 86 additions & 0 deletions crypto-common/src/generate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use hybrid_array::{Array, ArraySize};
use rand_core::{CryptoRng, TryCryptoRng};

#[cfg(feature = "getrandom")]
use crate::RngError;

/// Secure random generation.
pub trait Generate: Sized {
/// Generate random key using the provided [`TryCryptoRng`].
fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error>;

/// Generate random key using the provided [`CryptoRng`].
fn from_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
let Ok(ret) = Self::try_from_rng(rng);
ret
}

/// Randomly generate a value of this type using the system's ambient cryptographically secure
/// random number generator.
///
/// # Errors
/// Returns [`RngError`] in the event the system's ambient RNG experiences an internal failure.
#[cfg(feature = "getrandom")]
fn try_generate() -> Result<Self, RngError> {
Self::try_from_rng(&mut getrandom::SysRng)
}

/// Randomly generate a value of this type using the system's ambient cryptographically secure
/// random number generator.
///
/// # Panics
/// This method will panic in the event the system's ambient RNG experiences an internal
/// failure.
///
/// This shouldn't happen on most modern operating systems.
#[cfg(feature = "getrandom")]
fn generate() -> Self {
Self::try_generate().expect("RNG failure")
}
}

impl Generate for u32 {
#[inline]
fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
rng.try_next_u32()
}
}

impl Generate for u64 {
#[inline]
fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
rng.try_next_u64()
}
}

impl<const N: usize> Generate for [u8; N] {
#[inline]
fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
let mut ret = [0u8; N];
rng.try_fill_bytes(&mut ret)?;
Ok(ret)
}
}

impl<U: ArraySize> Generate for Array<u8, U> {
#[inline]
fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
let mut ret = Self::default();
rng.try_fill_bytes(&mut ret)?;
Ok(ret)
}
}

impl<U: ArraySize> Generate for Array<u32, U> {
#[inline]
fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
Self::try_from_fn(|_| rng.try_next_u32())
}
}

impl<U: ArraySize> Generate for Array<u64, U> {
#[inline]
fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
Self::try_from_fn(|_| rng.try_next_u64())
}
}
159 changes: 7 additions & 152 deletions crypto-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,24 @@
/// Hazardous materials.
pub mod hazmat;

#[cfg(feature = "getrandom")]
pub use getrandom;

/// Secure random generation.
#[cfg(feature = "rand_core")]
pub use rand_core;
mod generate;

pub use hybrid_array as array;
pub use hybrid_array::typenum;

#[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::{
Array, ArraySize,
typenum::{Diff, Sum, Unsigned},
};

#[cfg(feature = "rand_core")]
use rand_core::{CryptoRng, TryCryptoRng};

/// Block on which [`BlockSizeUser`] implementors operate.
pub type Block<B> = Array<u8, <B as BlockSizeUser>::BlockSize>;

Expand Down Expand Up @@ -178,35 +178,6 @@ pub trait KeyInit: KeySizeUser + Sized {
.map(Self::new)
.map_err(|_| InvalidLength)
}

/// Generate random key using the operating system's secure RNG.
#[cfg(feature = "getrandom")]
#[inline]
fn generate_key() -> Result<Key<Self>, getrandom::Error> {
let mut key = Key::<Self>::default();
getrandom::fill(&mut key)?;
Ok(key)
}

/// Generate random key using the provided [`CryptoRng`].
#[cfg(feature = "rand_core")]
#[inline]
fn generate_key_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Key<Self> {
let mut key = Key::<Self>::default();
rng.fill_bytes(&mut key);
key
}

/// Generate random key using the provided [`TryCryptoRng`].
#[cfg(feature = "rand_core")]
#[inline]
fn try_generate_key_with_rng<R: TryCryptoRng + ?Sized>(
rng: &mut R,
) -> Result<Key<Self>, R::Error> {
let mut key = Key::<Self>::default();
rng.try_fill_bytes(&mut key)?;
Ok(key)
}
}

/// Types which can be initialized from key and initialization vector (nonce).
Expand Down Expand Up @@ -234,93 +205,6 @@ pub trait KeyIvInit: KeySizeUser + IvSizeUser + Sized {
let iv = <&Iv<Self>>::try_from(iv).map_err(|_| InvalidLength)?;
Ok(Self::new(key, iv))
}

/// Generate random key using the operating system's secure RNG.
#[cfg(feature = "getrandom")]
#[inline]
fn generate_key() -> Result<Key<Self>, getrandom::Error> {
let mut key = Key::<Self>::default();
getrandom::fill(&mut key)?;
Ok(key)
}

/// Generate random key using the provided [`CryptoRng`].
#[cfg(feature = "rand_core")]
#[inline]
fn generate_key_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Key<Self> {
let mut key = Key::<Self>::default();
rng.fill_bytes(&mut key);
key
}

/// Generate random key using the provided [`TryCryptoRng`].
#[cfg(feature = "rand_core")]
#[inline]
fn try_generate_key_with_rng<R: TryCryptoRng + ?Sized>(
rng: &mut R,
) -> Result<Key<Self>, R::Error> {
let mut key = Key::<Self>::default();
rng.try_fill_bytes(&mut key)?;
Ok(key)
}

/// Generate random IV using the operating system's secure RNG.
#[cfg(feature = "getrandom")]
#[inline]
fn generate_iv() -> Result<Iv<Self>, getrandom::Error> {
let mut iv = Iv::<Self>::default();
getrandom::fill(&mut iv)?;
Ok(iv)
}

/// Generate random IV using the provided [`CryptoRng`].
#[cfg(feature = "rand_core")]
#[inline]
fn generate_iv_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Iv<Self> {
let mut iv = Iv::<Self>::default();
rng.fill_bytes(&mut iv);
iv
}

/// Generate random IV using the provided [`TryCryptoRng`].
#[cfg(feature = "rand_core")]
#[inline]
fn try_generate_iv_with_rng<R: TryCryptoRng + ?Sized>(
rng: &mut R,
) -> Result<Iv<Self>, R::Error> {
let mut iv = Iv::<Self>::default();
rng.try_fill_bytes(&mut iv)?;
Ok(iv)
}

/// Generate random key and IV using the operating system's secure RNG.
#[cfg(feature = "getrandom")]
#[inline]
fn generate_key_iv() -> Result<(Key<Self>, Iv<Self>), getrandom::Error> {
let key = Self::generate_key()?;
let iv = Self::generate_iv()?;
Ok((key, iv))
}

/// Generate random key and IV using the provided [`CryptoRng`].
#[cfg(feature = "rand_core")]
#[inline]
fn generate_key_iv_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> (Key<Self>, Iv<Self>) {
let key = Self::generate_key_with_rng(rng);
let iv = Self::generate_iv_with_rng(rng);
(key, iv)
}

/// Generate random key and IV using the provided [`TryCryptoRng`].
#[cfg(feature = "rand_core")]
#[inline]
fn try_generate_key_iv_with_rng<R: TryCryptoRng + ?Sized>(
rng: &mut R,
) -> Result<(Key<Self>, Iv<Self>), R::Error> {
let key = Self::try_generate_key_with_rng(rng)?;
let iv = Self::try_generate_iv_with_rng(rng)?;
Ok((key, iv))
}
}

/// Types which can be initialized from another type (usually block ciphers).
Expand All @@ -345,35 +229,6 @@ pub trait InnerIvInit: InnerUser + IvSizeUser + Sized {
let iv = <&Iv<Self>>::try_from(iv).map_err(|_| InvalidLength)?;
Ok(Self::inner_iv_init(inner, iv))
}

/// Generate random IV using the operating system's secure RNG.
#[cfg(feature = "getrandom")]
#[inline]
fn generate_iv() -> Result<Iv<Self>, getrandom::Error> {
let mut iv = Iv::<Self>::default();
getrandom::fill(&mut iv)?;
Ok(iv)
}

/// Generate random IV using the provided [`CryptoRng`].
#[cfg(feature = "rand_core")]
#[inline]
fn generate_iv_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Iv<Self> {
let mut iv = Iv::<Self>::default();
rng.fill_bytes(&mut iv);
iv
}

/// Generate random IV using the provided [`TryCryptoRng`].
#[cfg(feature = "rand_core")]
#[inline]
fn try_generate_iv_with_rng<R: TryCryptoRng + ?Sized>(
rng: &mut R,
) -> Result<Iv<Self>, R::Error> {
let mut iv = Iv::<Self>::default();
rng.try_fill_bytes(&mut iv)?;
Ok(iv)
}
}

/// Trait for loading current IV state.
Expand Down