Skip to content

Commit 8dabf55

Browse files
committed
crypto-common: Generate trait
Replaces all of the previous RNG functionality with a `Generate` trait which has the same basic shape as the existing methods, but allows types to impl only `try_from_rng` and receive provided versions of all of the other methods: - `generate`: infallible generation using system RNG with panic on error - `try_generate`: fallible version of above with RNG error `Result`s - `from_rng`: infallible generation with RNG parameter that panics on error The `generate` and `try_generate` methods are available when the `getrandom` feature is enabled. Impls are provided for `hybrid_array::Array<u8, U>`. With this approach we can generate things like symmetric keys and IVs like: type Aes256CbcEnc = cbc::Encryptor<aes::Aes256>; let key = Key::<Aes256CbcEnc>::generate(); let iv = Iv::<Aes256CbcEnc>::generate(); The trait is also intended to be impl'd by consuming crates for other key generation use cases, e.g. `RsaPrivateKey`, `dsa::SigningKey`, `ecdsa::SigningKey`, or KEM decapsulation keys.
1 parent b8679f5 commit 8dabf55

File tree

6 files changed

+105
-156
lines changed

6 files changed

+105
-156
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ members = [
1616
[patch.crates-io]
1717
digest = { path = "digest" }
1818
signature = { path = "signature" }
19+
20+
getrandom = { git = "https://github.com/rust-random/getrandom" }

crypto-common/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## 0.2.0 (UNRELEASED)
99
### Added
1010
- Sealed `BlockSizes` trait implemented for types from `U1` to `U255`
11+
- `Generate` trait ([#2096])
1112

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

17+
### Removed
18+
- `generate_*` and `try_generate_*` methods from KeyInit and KeyIvInit traits.
19+
See the newly added Generate trait for replacement ([#2096])
20+
1621
[#1759]: https://github.com/RustCrypto/traits/pull/1759
22+
[#2096]: https://github.com/RustCrypto/traits/pull/2096
1723

1824
## 0.1.7 (2025-11-12)
1925
### Changed

crypto-common/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ description = "Common cryptographic traits"
1616
hybrid-array = "0.4"
1717

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

2222
[features]
23-
getrandom = ["dep:getrandom"]
23+
getrandom = ["rand_core", "dep:getrandom"]
2424
rand_core = ["dep:rand_core"]
2525
zeroize = ["hybrid-array/zeroize"]
2626

crypto-common/src/generate.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
use hybrid_array::{Array, ArraySize};
2+
use rand_core::{CryptoRng, TryCryptoRng};
3+
4+
#[cfg(feature = "getrandom")]
5+
use crate::RngError;
6+
7+
/// Secure random generation.
8+
pub trait Generate: Sized {
9+
/// Generate random key using the provided [`TryCryptoRng`].
10+
fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error>;
11+
12+
/// Generate random key using the provided [`CryptoRng`].
13+
fn from_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
14+
let Ok(ret) = Self::try_from_rng(rng);
15+
ret
16+
}
17+
18+
/// Randomly generate a value of this type using the system's ambient cryptographically secure
19+
/// random number generator.
20+
///
21+
/// # Errors
22+
/// Returns [`RngError`] in the event the system's ambient RNG experiences an internal failure.
23+
#[cfg(feature = "getrandom")]
24+
fn try_generate() -> Result<Self, RngError> {
25+
Self::try_from_rng(&mut getrandom::SysRng)
26+
}
27+
28+
/// Randomly generate a value of this type using the system's ambient cryptographically secure
29+
/// random number generator.
30+
///
31+
/// # Panics
32+
/// This method will panic in the event the system's ambient RNG experiences an internal
33+
/// failure.
34+
///
35+
/// This shouldn't happen on most modern operating systems.
36+
#[cfg(feature = "getrandom")]
37+
fn generate() -> Self {
38+
Self::try_generate().expect("RNG failure")
39+
}
40+
}
41+
42+
impl Generate for u32 {
43+
#[inline]
44+
fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
45+
rng.try_next_u32()
46+
}
47+
}
48+
49+
impl Generate for u64 {
50+
#[inline]
51+
fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
52+
rng.try_next_u64()
53+
}
54+
}
55+
56+
impl<const N: usize> Generate for [u8; N] {
57+
#[inline]
58+
fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
59+
let mut ret = [0u8; N];
60+
rng.try_fill_bytes(&mut ret)?;
61+
Ok(ret)
62+
}
63+
}
64+
65+
impl<U: ArraySize> Generate for Array<u8, U> {
66+
#[inline]
67+
fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
68+
let mut ret = Self::default();
69+
rng.try_fill_bytes(&mut ret)?;
70+
Ok(ret)
71+
}
72+
}
73+
74+
impl<U: ArraySize> Generate for Array<u32, U> {
75+
#[inline]
76+
fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
77+
Self::try_from_fn(|_| rng.try_next_u32())
78+
}
79+
}
80+
81+
impl<U: ArraySize> Generate for Array<u64, U> {
82+
#[inline]
83+
fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
84+
Self::try_from_fn(|_| rng.try_next_u64())
85+
}
86+
}

crypto-common/src/lib.rs

Lines changed: 7 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,24 @@
1212
/// Hazardous materials.
1313
pub mod hazmat;
1414

15-
#[cfg(feature = "getrandom")]
16-
pub use getrandom;
17-
15+
/// Secure random generation.
1816
#[cfg(feature = "rand_core")]
19-
pub use rand_core;
17+
mod generate;
2018

2119
pub use hybrid_array as array;
2220
pub use hybrid_array::typenum;
2321

22+
#[cfg(feature = "rand_core")]
23+
pub use {generate::Generate, rand_core};
24+
#[cfg(feature = "getrandom")]
25+
pub use {getrandom, getrandom::Error as RngError};
26+
2427
use core::fmt;
2528
use hybrid_array::{
2629
Array, ArraySize,
2730
typenum::{Diff, Sum, Unsigned},
2831
};
2932

30-
#[cfg(feature = "rand_core")]
31-
use rand_core::{CryptoRng, TryCryptoRng};
32-
3333
/// Block on which [`BlockSizeUser`] implementors operate.
3434
pub type Block<B> = Array<u8, <B as BlockSizeUser>::BlockSize>;
3535

@@ -178,35 +178,6 @@ pub trait KeyInit: KeySizeUser + Sized {
178178
.map(Self::new)
179179
.map_err(|_| InvalidLength)
180180
}
181-
182-
/// Generate random key using the operating system's secure RNG.
183-
#[cfg(feature = "getrandom")]
184-
#[inline]
185-
fn generate_key() -> Result<Key<Self>, getrandom::Error> {
186-
let mut key = Key::<Self>::default();
187-
getrandom::fill(&mut key)?;
188-
Ok(key)
189-
}
190-
191-
/// Generate random key using the provided [`CryptoRng`].
192-
#[cfg(feature = "rand_core")]
193-
#[inline]
194-
fn generate_key_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Key<Self> {
195-
let mut key = Key::<Self>::default();
196-
rng.fill_bytes(&mut key);
197-
key
198-
}
199-
200-
/// Generate random key using the provided [`TryCryptoRng`].
201-
#[cfg(feature = "rand_core")]
202-
#[inline]
203-
fn try_generate_key_with_rng<R: TryCryptoRng + ?Sized>(
204-
rng: &mut R,
205-
) -> Result<Key<Self>, R::Error> {
206-
let mut key = Key::<Self>::default();
207-
rng.try_fill_bytes(&mut key)?;
208-
Ok(key)
209-
}
210181
}
211182

212183
/// Types which can be initialized from key and initialization vector (nonce).
@@ -234,93 +205,6 @@ pub trait KeyIvInit: KeySizeUser + IvSizeUser + Sized {
234205
let iv = <&Iv<Self>>::try_from(iv).map_err(|_| InvalidLength)?;
235206
Ok(Self::new(key, iv))
236207
}
237-
238-
/// Generate random key using the operating system's secure RNG.
239-
#[cfg(feature = "getrandom")]
240-
#[inline]
241-
fn generate_key() -> Result<Key<Self>, getrandom::Error> {
242-
let mut key = Key::<Self>::default();
243-
getrandom::fill(&mut key)?;
244-
Ok(key)
245-
}
246-
247-
/// Generate random key using the provided [`CryptoRng`].
248-
#[cfg(feature = "rand_core")]
249-
#[inline]
250-
fn generate_key_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Key<Self> {
251-
let mut key = Key::<Self>::default();
252-
rng.fill_bytes(&mut key);
253-
key
254-
}
255-
256-
/// Generate random key using the provided [`TryCryptoRng`].
257-
#[cfg(feature = "rand_core")]
258-
#[inline]
259-
fn try_generate_key_with_rng<R: TryCryptoRng + ?Sized>(
260-
rng: &mut R,
261-
) -> Result<Key<Self>, R::Error> {
262-
let mut key = Key::<Self>::default();
263-
rng.try_fill_bytes(&mut key)?;
264-
Ok(key)
265-
}
266-
267-
/// Generate random IV using the operating system's secure RNG.
268-
#[cfg(feature = "getrandom")]
269-
#[inline]
270-
fn generate_iv() -> Result<Iv<Self>, getrandom::Error> {
271-
let mut iv = Iv::<Self>::default();
272-
getrandom::fill(&mut iv)?;
273-
Ok(iv)
274-
}
275-
276-
/// Generate random IV using the provided [`CryptoRng`].
277-
#[cfg(feature = "rand_core")]
278-
#[inline]
279-
fn generate_iv_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Iv<Self> {
280-
let mut iv = Iv::<Self>::default();
281-
rng.fill_bytes(&mut iv);
282-
iv
283-
}
284-
285-
/// Generate random IV using the provided [`TryCryptoRng`].
286-
#[cfg(feature = "rand_core")]
287-
#[inline]
288-
fn try_generate_iv_with_rng<R: TryCryptoRng + ?Sized>(
289-
rng: &mut R,
290-
) -> Result<Iv<Self>, R::Error> {
291-
let mut iv = Iv::<Self>::default();
292-
rng.try_fill_bytes(&mut iv)?;
293-
Ok(iv)
294-
}
295-
296-
/// Generate random key and IV using the operating system's secure RNG.
297-
#[cfg(feature = "getrandom")]
298-
#[inline]
299-
fn generate_key_iv() -> Result<(Key<Self>, Iv<Self>), getrandom::Error> {
300-
let key = Self::generate_key()?;
301-
let iv = Self::generate_iv()?;
302-
Ok((key, iv))
303-
}
304-
305-
/// Generate random key and IV using the provided [`CryptoRng`].
306-
#[cfg(feature = "rand_core")]
307-
#[inline]
308-
fn generate_key_iv_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> (Key<Self>, Iv<Self>) {
309-
let key = Self::generate_key_with_rng(rng);
310-
let iv = Self::generate_iv_with_rng(rng);
311-
(key, iv)
312-
}
313-
314-
/// Generate random key and IV using the provided [`TryCryptoRng`].
315-
#[cfg(feature = "rand_core")]
316-
#[inline]
317-
fn try_generate_key_iv_with_rng<R: TryCryptoRng + ?Sized>(
318-
rng: &mut R,
319-
) -> Result<(Key<Self>, Iv<Self>), R::Error> {
320-
let key = Self::try_generate_key_with_rng(rng)?;
321-
let iv = Self::try_generate_iv_with_rng(rng)?;
322-
Ok((key, iv))
323-
}
324208
}
325209

326210
/// Types which can be initialized from another type (usually block ciphers).
@@ -345,35 +229,6 @@ pub trait InnerIvInit: InnerUser + IvSizeUser + Sized {
345229
let iv = <&Iv<Self>>::try_from(iv).map_err(|_| InvalidLength)?;
346230
Ok(Self::inner_iv_init(inner, iv))
347231
}
348-
349-
/// Generate random IV using the operating system's secure RNG.
350-
#[cfg(feature = "getrandom")]
351-
#[inline]
352-
fn generate_iv() -> Result<Iv<Self>, getrandom::Error> {
353-
let mut iv = Iv::<Self>::default();
354-
getrandom::fill(&mut iv)?;
355-
Ok(iv)
356-
}
357-
358-
/// Generate random IV using the provided [`CryptoRng`].
359-
#[cfg(feature = "rand_core")]
360-
#[inline]
361-
fn generate_iv_with_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Iv<Self> {
362-
let mut iv = Iv::<Self>::default();
363-
rng.fill_bytes(&mut iv);
364-
iv
365-
}
366-
367-
/// Generate random IV using the provided [`TryCryptoRng`].
368-
#[cfg(feature = "rand_core")]
369-
#[inline]
370-
fn try_generate_iv_with_rng<R: TryCryptoRng + ?Sized>(
371-
rng: &mut R,
372-
) -> Result<Iv<Self>, R::Error> {
373-
let mut iv = Iv::<Self>::default();
374-
rng.try_fill_bytes(&mut iv)?;
375-
Ok(iv)
376-
}
377232
}
378233

379234
/// Trait for loading current IV state.

0 commit comments

Comments
 (0)