Skip to main content

bouncycastle_factory/
rng_factory.rs

1//! RNG factory for creating instances of algorithms that implement the [RNG] trait.
2//!
3//! As with all Factory objects, this implements constructions from strings and defaults, and
4//! returns a [RNGFactory] object which itself implements the [RNG] trait as a pass-through to the underlying algorithm.
5//!
6//! A quick note about cryptographic random number generators (RNGs), which are also sometimes
7//! cryptographically secure random number generators (CSRNGs) or pseudorandom number generators (PRNGS)).
8//! As the last name suggests, they are based on deterministic permutation functions called
9//! deterministic random bit generators (DRBGs), which, always produce the same output for the same seed value.
10//! Meaning that they are only as cryptographically strong and unique as their seed.
11//!
12//! All RNGs exposed through the [RNGFactory] are seeded from the underlying operating system's entropy pool,
13//! and therefore should be sufficient for most cryptographic use. Additional entropy can be added via the
14//! [RNG::add_seed_keymaterial] function.
15//!
16//! Applications that require direct control over the seed material, for example in order to deterministically
17//! re-generate a key stream from a private seed, or in order to use a specific approved entropy source should
18//! instead use the objects in the [rng] crate, which expose more instantiation functionality.
19//!
20//!
21//! Example usage:
22//! ```
23//! use bouncycastle_factory::AlgorithmFactory;
24//! use bouncycastle_core::traits::Hash;
25//! use bouncycastle_sha3 as sha3;
26//!
27//! let data: &[u8] = b"Hello, world!";
28//!
29//! let h = bouncycastle_factory::hash_factory::HashFactory::new(sha3::SHA3_256_NAME).unwrap();
30//! let output: Vec<u8> = h.hash(data);
31//! ```
32//! You can equivalently invoke this by string instead of using the constant:
33//!
34//! ```
35//! use bouncycastle_factory::AlgorithmFactory;
36//! use bouncycastle_core::traits::Hash;
37//!
38//! let data: &[u8] = b"Hello, world!";
39//!
40//! let h = bouncycastle_factory::hash_factory::HashFactory::new("SHA3-256").unwrap();
41//! let output: Vec<u8> = h.hash(data);
42//! ```
43
44use bouncycastle_core::errors::RNGError;
45use bouncycastle_core::traits::{SecurityStrength, RNG};
46use bouncycastle_core::key_material::KeyMaterialTrait;
47use crate::{AlgorithmFactory, FactoryError};
48use crate::{DEFAULT, DEFAULT_128_BIT, DEFAULT_256_BIT};
49
50use bouncycastle_rng as rng;
51use bouncycastle_rng::{HASH_DRBG_SHA256_NAME, HASH_DRBG_SHA512_NAME};
52
53/*** Defaults ***/
54pub const DEFAULT_DRBG_NAME: &str = HASH_DRBG_SHA512_NAME;
55pub const DEFAULT_128BIT_DRBG_NAME: &str = HASH_DRBG_SHA256_NAME;
56pub const DEFAULT_256BIT_DRBG_NAME: &str = HASH_DRBG_SHA512_NAME;
57
58
59
60/// All members must impl RNG.
61pub enum RNGFactory {
62    #[allow(non_camel_case_types)]
63    HashDRBG_SHA256(rng::HashDRBG_SHA256),
64    #[allow(non_camel_case_types)]
65    HashDRBG_SHA512(rng::HashDRBG_SHA512),
66}
67
68impl Default for RNGFactory {
69    fn default() -> Self { Self::new(DEFAULT_DRBG_NAME).unwrap() }
70}
71
72impl AlgorithmFactory for RNGFactory {
73    fn default_128_bit() -> Self { Self::new(DEFAULT_128BIT_DRBG_NAME).unwrap() }
74    fn default_256_bit() -> Self { Self::new(DEFAULT_256BIT_DRBG_NAME).unwrap() }
75
76    fn new(alg_name: &str) -> Result<Self, FactoryError> {
77        match alg_name {
78            DEFAULT => Ok(Self::default()),
79            DEFAULT_128_BIT => Ok(Self::default_128_bit()),
80            DEFAULT_256_BIT => Ok(Self::default_256_bit()),
81            HASH_DRBG_SHA256_NAME => Ok(Self::HashDRBG_SHA256(rng::HashDRBG_SHA256::new_from_os())),
82            HASH_DRBG_SHA512_NAME => Ok(Self::HashDRBG_SHA512(rng::HashDRBG_SHA512::new_from_os())),
83            _ => Err(FactoryError::UnsupportedAlgorithm(format!("The algorithm: \"{}\" is not a known RNG", alg_name))),
84        }
85    }
86}
87
88impl RNG for RNGFactory {
89    fn add_seed_keymaterial(&mut self, additional_seed: impl KeyMaterialTrait) -> Result<(), RNGError> {
90        match self {
91            Self::HashDRBG_SHA256(rng) => {rng.add_seed_keymaterial(additional_seed) },
92            Self::HashDRBG_SHA512(rng) => { rng.add_seed_keymaterial(additional_seed) },
93        }
94    }
95
96    fn next_int(&mut self) -> Result<u32, RNGError> {
97        match self {
98            Self::HashDRBG_SHA256(rng) => {rng.next_int() },
99            Self::HashDRBG_SHA512(rng) => { rng.next_int() },
100        }
101    }
102
103    fn next_bytes(&mut self, len: usize) -> Result<Vec<u8>, RNGError> {
104        match self {
105            Self::HashDRBG_SHA256(rng) => {rng.next_bytes(len) },
106            Self::HashDRBG_SHA512(rng) => { rng.next_bytes(len) },
107        }
108    }
109
110    fn next_bytes_out(&mut self, out: &mut [u8]) -> Result<usize, RNGError> {
111        match self {
112            Self::HashDRBG_SHA256(rng) => {rng.next_bytes_out(out) },
113            Self::HashDRBG_SHA512(rng) => { rng.next_bytes_out(out) },
114        }
115    }
116
117    fn fill_keymaterial_out(&mut self, out: &mut impl KeyMaterialTrait) -> Result<usize, RNGError> {
118        match self {
119            Self::HashDRBG_SHA256(rng) => {rng.fill_keymaterial_out(out) },
120            Self::HashDRBG_SHA512(rng) => { rng.fill_keymaterial_out(out) },
121        }
122    }
123
124    fn security_strength(&self) -> SecurityStrength {
125        match self {
126            Self::HashDRBG_SHA256(rng) => {rng.security_strength() },
127            Self::HashDRBG_SHA512(rng) => { rng.security_strength() },
128        }
129    }
130}