Skip to main content

bouncycastle_factory/
kdf_factory.rs

1//! KDF factory for creating instances of algorithms that implement the [`KDF`] trait.
2//!
3//! As with all Factory objects, this implements constructions from strings and defaults, and
4//! returns a [`KDFFactory`] object which itself implements the [`KDF`] trait as a pass-through to the underlying algorithm.
5//!
6//! Example usage:
7//! ```
8//! use bouncycastle_core::key_material::{KeyMaterial256, KeyType};
9//! use bouncycastle_core::traits::KDF;
10//! use bouncycastle_factory::AlgorithmFactory;
11//!
12//! // Obtain key material from a secure place; here the default RNG is used, seeded from the OS is used
13//! let seed_key = KeyMaterial256::from_rng(&mut bouncycastle_rng::DefaultRNG::default()).unwrap();
14//! let additional_input: &[u8] = b"some additional input";
15//!
16//! let mut h = bouncycastle_factory::kdf_factory::KDFFactory::new(bouncycastle_hkdf::HKDF_SHA256_NAME).unwrap();
17//! let new_key = h.derive_key(&seed_key, additional_input).unwrap();
18//! ```
19//!
20//! Equivalently, it may be invoked by passing a string instead of using the constant:
21//!
22//! ```
23//! use bouncycastle_core::key_material::{KeyMaterial256, KeyType};
24//! use bouncycastle_core::traits::KDF;
25//! use bouncycastle_factory::AlgorithmFactory;
26//!
27//! // Obtain key material from a secure place; here the default RNG is used, seeded from the OS is used
28//! let seed_key = KeyMaterial256::from_rng(&mut bouncycastle_rng::DefaultRNG::default()).unwrap();
29//! let additional_input: &[u8] = b"some additional input";
30//!
31//! let h = bouncycastle_factory::kdf_factory::KDFFactory::new("HKDF-SHA256").unwrap();
32//! let new_key = h.derive_key(&seed_key, additional_input).unwrap();
33//! ```
34//!
35//! If the algorithm used is not particularly important, the built-in default may be used:
36//!
37//! ```
38//! use bouncycastle_core::key_material::{KeyMaterial256, KeyType};
39//! use bouncycastle_core::traits::KDF;
40//! use bouncycastle_factory::AlgorithmFactory;
41//!
42//! // Obtain key material from a secure place; here the default RNG is used, seeded from the OS is used
43//! let seed_key = KeyMaterial256::from_rng(&mut bouncycastle_rng::DefaultRNG::default()).unwrap();
44//! let additional_input: &[u8] = b"some additional input";
45//!
46//! let h = bouncycastle_factory::kdf_factory::KDFFactory::default();
47//! let new_key = h.derive_key(&seed_key, additional_input).unwrap();
48//! ```
49
50use crate::{AlgorithmFactory, DEFAULT, DEFAULT_128_BIT, DEFAULT_256_BIT, FactoryError};
51use bouncycastle_core::errors::KDFError;
52use bouncycastle_core::key_material::KeyMaterialTrait;
53use bouncycastle_core::traits::{KDF, SecurityStrength};
54use bouncycastle_hkdf as hkdf;
55use bouncycastle_hkdf::{HKDF_SHA256_NAME, HKDF_SHA512_NAME};
56use bouncycastle_sha3 as sha3;
57use bouncycastle_sha3::{
58    SHA3_224_NAME, SHA3_256_NAME, SHA3_384_NAME, SHA3_512_NAME, SHAKE128_NAME, SHAKE256_NAME,
59};
60
61/// Wrapper object for all algorithms that impl [`KDF`].
62pub enum KDFFactory {
63    ///
64    #[allow(non_camel_case_types)]
65    HKDF_SHA256(hkdf::HKDF_SHA256),
66    ///
67    #[allow(non_camel_case_types)]
68    HKDF_SHA512(hkdf::HKDF_SHA512),
69    ///
70    SHA3_224(sha3::SHA3_224),
71    ///
72    SHA3_256(sha3::SHA3_256),
73    ///
74    SHA3_384(sha3::SHA3_384),
75    ///
76    SHA3_512(sha3::SHA3_512),
77    ///
78    SHAKE128(sha3::SHAKE128),
79    ///
80    SHAKE256(sha3::SHAKE256),
81}
82
83impl Default for KDFFactory {
84    fn default() -> Self {
85        Self::HKDF_SHA512(hkdf::HKDF_SHA512::new())
86    }
87}
88
89impl AlgorithmFactory for KDFFactory {
90    fn default_128_bit() -> Self {
91        Self::HKDF_SHA256(hkdf::HKDF_SHA256::new())
92    }
93
94    fn default_256_bit() -> Self {
95        Self::HKDF_SHA512(hkdf::HKDF_SHA512::new())
96    }
97
98    fn new(alg_name: &str) -> Result<Self, FactoryError> {
99        match alg_name {
100            DEFAULT => Ok(KDFFactory::default()),
101            DEFAULT_128_BIT => Ok(KDFFactory::default_128_bit()),
102            DEFAULT_256_BIT => Ok(KDFFactory::default_256_bit()),
103            HKDF_SHA256_NAME => Ok(Self::HKDF_SHA256(hkdf::HKDF_SHA256::new())),
104            HKDF_SHA512_NAME => Ok(Self::HKDF_SHA512(hkdf::HKDF_SHA512::new())),
105            SHA3_224_NAME => Ok(Self::SHA3_224(sha3::SHA3_224::new())),
106            SHA3_256_NAME => Ok(Self::SHA3_256(sha3::SHA3_256::new())),
107            SHA3_384_NAME => Ok(Self::SHA3_384(sha3::SHA3_384::new())),
108            SHA3_512_NAME => Ok(Self::SHA3_512(sha3::SHA3_512::new())),
109            SHAKE128_NAME => Ok(Self::SHAKE128(sha3::SHAKE128::new())),
110            SHAKE256_NAME => Ok(Self::SHAKE256(sha3::SHAKE256::new())),
111            _ => Err(FactoryError::UnsupportedAlgorithm(format!(
112                "The algorithm: \"{}\" is not a known KDF",
113                alg_name
114            ))),
115        }
116    }
117}
118
119impl KDF for KDFFactory {
120    fn derive_key(
121        self,
122        key: &impl KeyMaterialTrait,
123        additional_input: &[u8],
124    ) -> Result<Box<dyn KeyMaterialTrait>, KDFError> {
125        match self {
126            Self::HKDF_SHA256(h) => h.derive_key(key, additional_input),
127            Self::HKDF_SHA512(h) => h.derive_key(key, additional_input),
128            Self::SHA3_224(h) => h.derive_key(key, additional_input),
129            Self::SHA3_256(h) => h.derive_key(key, additional_input),
130            Self::SHA3_384(h) => h.derive_key(key, additional_input),
131            Self::SHA3_512(h) => h.derive_key(key, additional_input),
132            Self::SHAKE128(h) => h.derive_key(key, additional_input),
133            Self::SHAKE256(h) => h.derive_key(key, additional_input),
134        }
135    }
136
137    fn derive_key_out(
138        self,
139        key: &impl KeyMaterialTrait,
140        additional_input: &[u8],
141        output_key: &mut impl KeyMaterialTrait,
142    ) -> Result<usize, KDFError> {
143        match self {
144            Self::HKDF_SHA256(h) => h.derive_key_out(key, additional_input, output_key),
145            Self::HKDF_SHA512(h) => h.derive_key_out(key, additional_input, output_key),
146            Self::SHA3_224(h) => h.derive_key_out(key, additional_input, output_key),
147            Self::SHA3_256(h) => h.derive_key_out(key, additional_input, output_key),
148            Self::SHA3_384(h) => h.derive_key_out(key, additional_input, output_key),
149            Self::SHA3_512(h) => h.derive_key_out(key, additional_input, output_key),
150            Self::SHAKE128(h) => h.derive_key_out(key, additional_input, output_key),
151            Self::SHAKE256(h) => h.derive_key_out(key, additional_input, output_key),
152        }
153    }
154
155    fn derive_key_from_multiple(
156        self,
157        keys: &[&impl KeyMaterialTrait],
158        additional_input: &[u8],
159    ) -> Result<Box<dyn KeyMaterialTrait>, KDFError> {
160        match self {
161            Self::HKDF_SHA256(h) => h.derive_key_from_multiple(keys, additional_input),
162            Self::HKDF_SHA512(h) => h.derive_key_from_multiple(keys, additional_input),
163            Self::SHA3_224(h) => h.derive_key_from_multiple(keys, additional_input),
164            Self::SHA3_256(h) => h.derive_key_from_multiple(keys, additional_input),
165            Self::SHA3_384(h) => h.derive_key_from_multiple(keys, additional_input),
166            Self::SHA3_512(h) => h.derive_key_from_multiple(keys, additional_input),
167            Self::SHAKE128(h) => h.derive_key_from_multiple(keys, additional_input),
168            Self::SHAKE256(h) => h.derive_key_from_multiple(keys, additional_input),
169        }
170    }
171
172    fn derive_key_from_multiple_out(
173        self,
174        keys: &[&impl KeyMaterialTrait],
175        additional_input: &[u8],
176        output_key: &mut impl KeyMaterialTrait,
177    ) -> Result<usize, KDFError> {
178        match self {
179            Self::HKDF_SHA256(h) => {
180                h.derive_key_from_multiple_out(keys, additional_input, output_key)
181            }
182            Self::HKDF_SHA512(h) => {
183                h.derive_key_from_multiple_out(keys, additional_input, output_key)
184            }
185            Self::SHA3_224(h) => h.derive_key_from_multiple_out(keys, additional_input, output_key),
186            Self::SHA3_256(h) => h.derive_key_from_multiple_out(keys, additional_input, output_key),
187            Self::SHA3_384(h) => h.derive_key_from_multiple_out(keys, additional_input, output_key),
188            Self::SHA3_512(h) => h.derive_key_from_multiple_out(keys, additional_input, output_key),
189            Self::SHAKE128(h) => h.derive_key_from_multiple_out(keys, additional_input, output_key),
190            Self::SHAKE256(h) => h.derive_key_from_multiple_out(keys, additional_input, output_key),
191        }
192    }
193
194    fn max_security_strength(&self) -> SecurityStrength {
195        match self {
196            Self::HKDF_SHA256(h) => h.max_security_strength(),
197            Self::HKDF_SHA512(h) => h.max_security_strength(),
198            Self::SHA3_224(h) => h.max_security_strength(),
199            Self::SHA3_256(h) => h.max_security_strength(),
200            Self::SHA3_384(h) => h.max_security_strength(),
201            Self::SHA3_512(h) => h.max_security_strength(),
202            Self::SHAKE128(h) => h.max_security_strength(),
203            Self::SHAKE256(h) => h.max_security_strength(),
204        }
205    }
206}