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//! Equivalently, it may be invoked by passing a 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 crate::{AlgorithmFactory, FactoryError};
45use crate::{DEFAULT, DEFAULT_128_BIT, DEFAULT_256_BIT};
46use bouncycastle_core::errors::RNGError;
47use bouncycastle_core::key_material::KeyMaterialTrait;
48use bouncycastle_core::traits::{RNG, SecurityStrength};
49
50use bouncycastle_rng as rng;
51use bouncycastle_rng::{HASH_DRBG_SHA256_NAME, HASH_DRBG_SHA512_NAME};
52
53/// Wrapper object for all algorithms that impl [`RNG`].
54pub enum RNGFactory {
55    ///
56    #[allow(non_camel_case_types)]
57    HashDRBG_SHA256(rng::HashDRBG_SHA256),
58    ///
59    #[allow(non_camel_case_types)]
60    HashDRBG_SHA512(rng::HashDRBG_SHA512),
61}
62
63impl Default for RNGFactory {
64    fn default() -> Self {
65        Self::HashDRBG_SHA512(rng::HashDRBG_SHA512::new_from_os())
66    }
67}
68
69impl AlgorithmFactory for RNGFactory {
70    fn default_128_bit() -> Self {
71        Self::HashDRBG_SHA256(rng::HashDRBG_SHA256::new_from_os())
72    }
73    fn default_256_bit() -> Self {
74        Self::HashDRBG_SHA512(rng::HashDRBG_SHA512::new_from_os())
75    }
76
77    fn new(alg_name: &str) -> Result<Self, FactoryError> {
78        match alg_name {
79            DEFAULT => Ok(Self::default()),
80            DEFAULT_128_BIT => Ok(Self::default_128_bit()),
81            DEFAULT_256_BIT => Ok(Self::default_256_bit()),
82            HASH_DRBG_SHA256_NAME => Ok(Self::HashDRBG_SHA256(rng::HashDRBG_SHA256::new_from_os())),
83            HASH_DRBG_SHA512_NAME => Ok(Self::HashDRBG_SHA512(rng::HashDRBG_SHA512::new_from_os())),
84            _ => Err(FactoryError::UnsupportedAlgorithm(format!(
85                "The algorithm: \"{}\" is not a known RNG",
86                alg_name
87            ))),
88        }
89    }
90}
91
92impl RNG for RNGFactory {
93    fn add_seed_keymaterial(
94        &mut self,
95        additional_seed: &dyn KeyMaterialTrait,
96    ) -> Result<(), RNGError> {
97        match self {
98            Self::HashDRBG_SHA256(rng) => rng.add_seed_keymaterial(additional_seed),
99            Self::HashDRBG_SHA512(rng) => rng.add_seed_keymaterial(additional_seed),
100        }
101    }
102
103    fn next_int(&mut self) -> Result<u32, RNGError> {
104        match self {
105            Self::HashDRBG_SHA256(rng) => rng.next_int(),
106            Self::HashDRBG_SHA512(rng) => rng.next_int(),
107        }
108    }
109
110    fn next_bytes(&mut self, len: usize) -> Result<Vec<u8>, RNGError> {
111        match self {
112            Self::HashDRBG_SHA256(rng) => rng.next_bytes(len),
113            Self::HashDRBG_SHA512(rng) => rng.next_bytes(len),
114        }
115    }
116
117    fn next_bytes_out(&mut self, out: &mut [u8]) -> Result<usize, RNGError> {
118        out.fill(0);
119
120        match self {
121            Self::HashDRBG_SHA256(rng) => rng.next_bytes_out(out),
122            Self::HashDRBG_SHA512(rng) => rng.next_bytes_out(out),
123        }
124    }
125
126    fn fill_keymaterial_out(&mut self, out: &mut dyn KeyMaterialTrait) -> Result<usize, RNGError> {
127        match self {
128            Self::HashDRBG_SHA256(rng) => rng.fill_keymaterial_out(out),
129            Self::HashDRBG_SHA512(rng) => rng.fill_keymaterial_out(out),
130        }
131    }
132
133    fn security_strength(&self) -> SecurityStrength {
134        match self {
135            Self::HashDRBG_SHA256(rng) => rng.security_strength(),
136            Self::HashDRBG_SHA512(rng) => rng.security_strength(),
137        }
138    }
139}