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//! // get your key material from a secure place; here we'll use the default RNG, seeded from the OS
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//! You can equivalently invoke this by 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//! // get your key material from a secure place; here we'll use the default RNG, seeded from the OS
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//! Or if you don't particularly care which algorithm is used, you can use the built-in default:
36//!
37//! ```
38//! use bouncycastle_core::key_material::{KeyMaterial256, KeyType};
39//! use bouncycastle_core::traits::KDF;
40//! use bouncycastle_factory::AlgorithmFactory;
41//!
42//! // get your key material from a secure place; here we'll use the default RNG, seeded from the OS
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/*** Defaults ***/
62pub const DEFAULT_KDF_NAME: &str = HKDF_SHA512_NAME;
63pub const DEFAULT_128BIT_KDF_NAME: &str = HKDF_SHA256_NAME;
64pub const DEFAULT_256BIT_KDF_NAME: &str = HKDF_SHA512_NAME;
65
66// All members must impl KDF.
67pub enum KDFFactory {
68    #[allow(non_camel_case_types)]
69    HKDF_SHA256(hkdf::HKDF_SHA256),
70    #[allow(non_camel_case_types)]
71    HKDF_SHA512(hkdf::HKDF_SHA512),
72    SHA3_224(sha3::SHA3_224),
73    SHA3_256(sha3::SHA3_256),
74    SHA3_384(sha3::SHA3_384),
75    SHA3_512(sha3::SHA3_512),
76    SHAKE128(sha3::SHAKE128),
77    SHAKE256(sha3::SHAKE256),
78}
79
80impl Default for KDFFactory {
81    fn default() -> Self {
82        KDFFactory::new(DEFAULT_KDF_NAME).unwrap()
83    }
84}
85
86impl AlgorithmFactory for KDFFactory {
87    fn default_128_bit() -> Self {
88        KDFFactory::new(DEFAULT_128BIT_KDF_NAME).unwrap()
89    }
90
91    fn default_256_bit() -> Self {
92        KDFFactory::new(DEFAULT_256BIT_KDF_NAME).unwrap()
93    }
94
95    fn new(alg_name: &str) -> Result<Self, FactoryError> {
96        match alg_name {
97            DEFAULT => Ok(KDFFactory::default()),
98            DEFAULT_128_BIT => Ok(KDFFactory::default_128_bit()),
99            DEFAULT_256_BIT => Ok(KDFFactory::default_256_bit()),
100            HKDF_SHA256_NAME => Ok(Self::HKDF_SHA256(hkdf::HKDF_SHA256::new())),
101            HKDF_SHA512_NAME => Ok(Self::HKDF_SHA512(hkdf::HKDF_SHA512::new())),
102            SHA3_224_NAME => Ok(Self::SHA3_224(sha3::SHA3_224::new())),
103            SHA3_256_NAME => Ok(Self::SHA3_256(sha3::SHA3_256::new())),
104            SHA3_384_NAME => Ok(Self::SHA3_384(sha3::SHA3_384::new())),
105            SHA3_512_NAME => Ok(Self::SHA3_512(sha3::SHA3_512::new())),
106            SHAKE128_NAME => Ok(Self::SHAKE128(sha3::SHAKE128::new())),
107            SHAKE256_NAME => Ok(Self::SHAKE256(sha3::SHAKE256::new())),
108            _ => Err(FactoryError::UnsupportedAlgorithm(format!(
109                "The algorithm: \"{}\" is not a known KDF",
110                alg_name
111            ))),
112        }
113    }
114}
115
116impl KDF for KDFFactory {
117    fn derive_key(
118        self,
119        key: &impl KeyMaterialTrait,
120        additional_input: &[u8],
121    ) -> Result<Box<dyn KeyMaterialTrait>, KDFError> {
122        match self {
123            Self::HKDF_SHA256(h) => h.derive_key(key, additional_input),
124            Self::HKDF_SHA512(h) => h.derive_key(key, additional_input),
125            Self::SHA3_224(h) => h.derive_key(key, additional_input),
126            Self::SHA3_256(h) => h.derive_key(key, additional_input),
127            Self::SHA3_384(h) => h.derive_key(key, additional_input),
128            Self::SHA3_512(h) => h.derive_key(key, additional_input),
129            Self::SHAKE128(h) => h.derive_key(key, additional_input),
130            Self::SHAKE256(h) => h.derive_key(key, additional_input),
131        }
132    }
133
134    fn derive_key_out(
135        self,
136        key: &impl KeyMaterialTrait,
137        additional_input: &[u8],
138        output_key: &mut impl KeyMaterialTrait,
139    ) -> Result<usize, KDFError> {
140        match self {
141            Self::HKDF_SHA256(h) => h.derive_key_out(key, additional_input, output_key),
142            Self::HKDF_SHA512(h) => h.derive_key_out(key, additional_input, output_key),
143            Self::SHA3_224(h) => h.derive_key_out(key, additional_input, output_key),
144            Self::SHA3_256(h) => h.derive_key_out(key, additional_input, output_key),
145            Self::SHA3_384(h) => h.derive_key_out(key, additional_input, output_key),
146            Self::SHA3_512(h) => h.derive_key_out(key, additional_input, output_key),
147            Self::SHAKE128(h) => h.derive_key_out(key, additional_input, output_key),
148            Self::SHAKE256(h) => h.derive_key_out(key, additional_input, output_key),
149        }
150    }
151
152    fn derive_key_from_multiple(
153        self,
154        keys: &[&impl KeyMaterialTrait],
155        additional_input: &[u8],
156    ) -> Result<Box<dyn KeyMaterialTrait>, KDFError> {
157        match self {
158            Self::HKDF_SHA256(h) => h.derive_key_from_multiple(keys, additional_input),
159            Self::HKDF_SHA512(h) => h.derive_key_from_multiple(keys, additional_input),
160            Self::SHA3_224(h) => h.derive_key_from_multiple(keys, additional_input),
161            Self::SHA3_256(h) => h.derive_key_from_multiple(keys, additional_input),
162            Self::SHA3_384(h) => h.derive_key_from_multiple(keys, additional_input),
163            Self::SHA3_512(h) => h.derive_key_from_multiple(keys, additional_input),
164            Self::SHAKE128(h) => h.derive_key_from_multiple(keys, additional_input),
165            Self::SHAKE256(h) => h.derive_key_from_multiple(keys, additional_input),
166        }
167    }
168
169    fn derive_key_from_multiple_out(
170        self,
171        keys: &[&impl KeyMaterialTrait],
172        additional_input: &[u8],
173        output_key: &mut impl KeyMaterialTrait,
174    ) -> Result<usize, KDFError> {
175        match self {
176            Self::HKDF_SHA256(h) => {
177                h.derive_key_from_multiple_out(keys, additional_input, output_key)
178            }
179            Self::HKDF_SHA512(h) => {
180                h.derive_key_from_multiple_out(keys, additional_input, output_key)
181            }
182            Self::SHA3_224(h) => h.derive_key_from_multiple_out(keys, additional_input, output_key),
183            Self::SHA3_256(h) => h.derive_key_from_multiple_out(keys, additional_input, output_key),
184            Self::SHA3_384(h) => h.derive_key_from_multiple_out(keys, additional_input, output_key),
185            Self::SHA3_512(h) => h.derive_key_from_multiple_out(keys, additional_input, output_key),
186            Self::SHAKE128(h) => h.derive_key_from_multiple_out(keys, additional_input, output_key),
187            Self::SHAKE256(h) => h.derive_key_from_multiple_out(keys, additional_input, output_key),
188        }
189    }
190
191    fn max_security_strength(&self) -> SecurityStrength {
192        match self {
193            Self::HKDF_SHA256(h) => h.max_security_strength(),
194            Self::HKDF_SHA512(h) => h.max_security_strength(),
195            Self::SHA3_224(h) => h.max_security_strength(),
196            Self::SHA3_256(h) => h.max_security_strength(),
197            Self::SHA3_384(h) => h.max_security_strength(),
198            Self::SHA3_512(h) => h.max_security_strength(),
199            Self::SHAKE128(h) => h.max_security_strength(),
200            Self::SHAKE256(h) => h.max_security_strength(),
201        }
202    }
203}