Skip to main content

bouncycastle_factory/
hash_factory.rs

1//! Hash factory for creating instances of algorithms that implement the [`Hash`] trait.
2//!
3//! As with all Factory objects, this implements constructions from strings and defaults, and
4//! returns a [`HashFactory`] object which itself implements the [`Hash`] trait as a pass-through to the underlying algorithm.
5//!
6//! Example usage:
7//! ```
8//! use bouncycastle_factory::AlgorithmFactory;
9//! use bouncycastle_core::traits::Hash;
10//! use bouncycastle_sha3 as sha3;
11//!
12//! let data: &[u8] = b"Hello, world!";
13//!
14//! let h = bouncycastle_factory::hash_factory::HashFactory::new(sha3::SHA3_256_NAME).unwrap();
15//! let output: Vec<u8> = h.hash(data);
16//! ```
17//! Equivalently, it may be invoked by passing a string instead of using the constant:
18//!
19//! ```
20//! use bouncycastle_factory::AlgorithmFactory;
21//! use bouncycastle_core::traits::Hash;
22//!
23//! let data: &[u8] = b"Hello, world!";
24//!
25//! let h = bouncycastle_factory::hash_factory::HashFactory::new("SHA3-256").unwrap();
26//! let output: Vec<u8> = h.hash(data);
27//! ```
28
29use crate::{AlgorithmFactory, FactoryError};
30use crate::{DEFAULT, DEFAULT_128_BIT, DEFAULT_256_BIT};
31use bouncycastle_core::errors::HashError;
32use bouncycastle_core::traits::{Algorithm, Hash, SecurityStrength};
33use bouncycastle_sha2 as sha2;
34use bouncycastle_sha2::{SHA224_NAME, SHA256_NAME, SHA384_NAME, SHA512_NAME};
35use bouncycastle_sha3 as sha3;
36use bouncycastle_sha3::{SHA3_224_NAME, SHA3_256_NAME, SHA3_384_NAME, SHA3_512_NAME};
37
38/// Wrapper object for all algorithms that impl [`Hash`].
39/// Note: no SHAKE because SHAKE is not NIST approved as a hash function. See FIPS 202 section A.2.
40pub enum HashFactory {
41    ///
42    SHA224(sha2::SHA224),
43    ///
44    SHA256(sha2::SHA256),
45    ///
46    SHA384(sha2::SHA384),
47    ///
48    SHA512(sha2::SHA512),
49    ///
50    SHA3_224(sha3::SHA3_224),
51    ///
52    SHA3_256(sha3::SHA3_256),
53    ///
54    SHA3_384(sha3::SHA3_384),
55    ///
56    SHA3_512(sha3::SHA3_512),
57}
58
59impl Default for HashFactory {
60    fn default() -> HashFactory {
61        Self::SHA3_256(sha3::SHA3_256::new())
62    }
63}
64
65impl AlgorithmFactory for HashFactory {
66    fn default_128_bit() -> HashFactory {
67        Self::SHA3_256(sha3::SHA3_256::new())
68    }
69    fn default_256_bit() -> HashFactory {
70        Self::SHA3_512(sha3::SHA3_512::new())
71    }
72
73    fn new(alg_name: &str) -> Result<Self, FactoryError> {
74        match alg_name {
75            DEFAULT => Ok(Self::default()),
76            DEFAULT_128_BIT => Ok(Self::default_128_bit()),
77            DEFAULT_256_BIT => Ok(Self::default_256_bit()),
78            SHA224_NAME => Ok(Self::SHA224(sha2::SHA224::new())),
79            SHA256_NAME => Ok(Self::SHA256(sha2::SHA256::new())),
80            SHA384_NAME => Ok(Self::SHA384(sha2::SHA384::new())),
81            SHA512_NAME => Ok(Self::SHA512(sha2::SHA512::new())),
82            SHA3_224_NAME => Ok(Self::SHA3_224(sha3::SHA3_224::new())),
83            SHA3_256_NAME => Ok(Self::SHA3_256(sha3::SHA3_256::new())),
84            SHA3_384_NAME => Ok(Self::SHA3_384(sha3::SHA3_384::new())),
85            SHA3_512_NAME => Ok(Self::SHA3_512(sha3::SHA3_512::new())),
86            _ => Err(FactoryError::UnsupportedAlgorithm(format!(
87                "The algorithm: \"{}\" is not a known Hash",
88                alg_name
89            ))),
90        }
91    }
92}
93
94// TODO -- this is broken.
95//      The designed behaviour here is that the Factory object pass these through to the underlying algorithm
96//      that it's wrapping, but that can't be done with consts, so I think the Algorithm trait needs
97//      a rework to be functions instead of consts.
98impl Algorithm for HashFactory {
99    const ALG_NAME: &'static str = "TODO";
100    const MAX_SECURITY_STRENGTH: SecurityStrength = SecurityStrength::None;
101}
102
103impl Hash for HashFactory {
104    fn block_bitlen(&self) -> usize {
105        match self {
106            Self::SHA224(h) => h.block_bitlen(),
107            Self::SHA256(h) => h.block_bitlen(),
108            Self::SHA384(h) => h.block_bitlen(),
109            Self::SHA512(h) => h.block_bitlen(),
110            Self::SHA3_224(h) => h.block_bitlen(),
111            Self::SHA3_256(h) => h.block_bitlen(),
112            Self::SHA3_384(h) => h.block_bitlen(),
113            Self::SHA3_512(h) => h.block_bitlen(),
114        }
115    }
116
117    fn output_len(&self) -> usize {
118        match self {
119            Self::SHA224(h) => h.output_len(),
120            Self::SHA256(h) => h.output_len(),
121            Self::SHA384(h) => h.output_len(),
122            Self::SHA512(h) => h.output_len(),
123            Self::SHA3_224(h) => h.output_len(),
124            Self::SHA3_256(h) => h.output_len(),
125            Self::SHA3_384(h) => h.output_len(),
126            Self::SHA3_512(h) => h.output_len(),
127        }
128    }
129
130    fn hash(self, data: &[u8]) -> Vec<u8> {
131        match self {
132            Self::SHA224(h) => h.hash(data),
133            Self::SHA256(h) => h.hash(data),
134            Self::SHA384(h) => h.hash(data),
135            Self::SHA512(h) => h.hash(data),
136            Self::SHA3_224(h) => h.hash(data),
137            Self::SHA3_256(h) => h.hash(data),
138            Self::SHA3_384(h) => h.hash(data),
139            Self::SHA3_512(h) => h.hash(data),
140        }
141    }
142
143    fn hash_out(self, data: &[u8], output: &mut [u8]) -> usize {
144        output.fill(0);
145
146        match self {
147            Self::SHA224(h) => h.hash_out(data, output),
148            Self::SHA256(h) => h.hash_out(data, output),
149            Self::SHA384(h) => h.hash_out(data, output),
150            Self::SHA512(h) => h.hash_out(data, output),
151            Self::SHA3_224(h) => h.hash_out(data, output),
152            Self::SHA3_256(h) => h.hash_out(data, output),
153            Self::SHA3_384(h) => h.hash_out(data, output),
154            Self::SHA3_512(h) => h.hash_out(data, output),
155        }
156    }
157
158    fn do_update(&mut self, data: &[u8]) {
159        match self {
160            Self::SHA224(h) => h.do_update(data),
161            Self::SHA256(h) => h.do_update(data),
162            Self::SHA384(h) => h.do_update(data),
163            Self::SHA512(h) => h.do_update(data),
164            Self::SHA3_224(h) => h.do_update(data),
165            Self::SHA3_256(h) => h.do_update(data),
166            Self::SHA3_384(h) => h.do_update(data),
167            Self::SHA3_512(h) => h.do_update(data),
168        }
169    }
170
171    fn do_final(self) -> Vec<u8> {
172        match self {
173            Self::SHA224(h) => h.do_final(),
174            Self::SHA256(h) => h.do_final(),
175            Self::SHA384(h) => h.do_final(),
176            Self::SHA512(h) => h.do_final(),
177            Self::SHA3_224(h) => h.do_final(),
178            Self::SHA3_256(h) => h.do_final(),
179            Self::SHA3_384(h) => h.do_final(),
180            Self::SHA3_512(h) => h.do_final(),
181        }
182    }
183
184    fn do_final_out(self, output: &mut [u8]) -> usize {
185        output.fill(0);
186
187        match self {
188            Self::SHA224(h) => h.do_final_out(output),
189            Self::SHA256(h) => h.do_final_out(output),
190            Self::SHA384(h) => h.do_final_out(output),
191            Self::SHA512(h) => h.do_final_out(output),
192            Self::SHA3_224(h) => h.do_final_out(output),
193            Self::SHA3_256(h) => h.do_final_out(output),
194            Self::SHA3_384(h) => h.do_final_out(output),
195            Self::SHA3_512(h) => h.do_final_out(output),
196        }
197    }
198
199    fn do_final_partial_bits(
200        self,
201        partial_byte: u8,
202        num_partial_bits: usize,
203    ) -> Result<Vec<u8>, HashError> {
204        match self {
205            Self::SHA224(h) => h.do_final_partial_bits(partial_byte, num_partial_bits),
206            Self::SHA256(h) => h.do_final_partial_bits(partial_byte, num_partial_bits),
207            Self::SHA384(h) => h.do_final_partial_bits(partial_byte, num_partial_bits),
208            Self::SHA512(h) => h.do_final_partial_bits(partial_byte, num_partial_bits),
209            Self::SHA3_224(h) => h.do_final_partial_bits(partial_byte, num_partial_bits),
210            Self::SHA3_256(h) => h.do_final_partial_bits(partial_byte, num_partial_bits),
211            Self::SHA3_384(h) => h.do_final_partial_bits(partial_byte, num_partial_bits),
212            Self::SHA3_512(h) => h.do_final_partial_bits(partial_byte, num_partial_bits),
213        }
214    }
215
216    fn do_final_partial_bits_out(
217        self,
218        partial_byte: u8,
219        num_partial_bits: usize,
220        output: &mut [u8],
221    ) -> Result<usize, HashError> {
222        match self {
223            Self::SHA224(h) => h.do_final_partial_bits_out(partial_byte, num_partial_bits, output),
224            Self::SHA256(h) => h.do_final_partial_bits_out(partial_byte, num_partial_bits, output),
225            Self::SHA384(h) => h.do_final_partial_bits_out(partial_byte, num_partial_bits, output),
226            Self::SHA512(h) => h.do_final_partial_bits_out(partial_byte, num_partial_bits, output),
227            Self::SHA3_224(h) => {
228                h.do_final_partial_bits_out(partial_byte, num_partial_bits, output)
229            }
230            Self::SHA3_256(h) => {
231                h.do_final_partial_bits_out(partial_byte, num_partial_bits, output)
232            }
233            Self::SHA3_384(h) => {
234                h.do_final_partial_bits_out(partial_byte, num_partial_bits, output)
235            }
236            Self::SHA3_512(h) => {
237                h.do_final_partial_bits_out(partial_byte, num_partial_bits, output)
238            }
239        }
240    }
241
242    fn max_security_strength(&self) -> SecurityStrength {
243        match self {
244            Self::SHA224(h) => h.max_security_strength(),
245            Self::SHA256(h) => h.max_security_strength(),
246            Self::SHA384(h) => h.max_security_strength(),
247            Self::SHA512(h) => h.max_security_strength(),
248            Self::SHA3_224(h) => h.max_security_strength(),
249            Self::SHA3_256(h) => h.max_security_strength(),
250            Self::SHA3_384(h) => h.max_security_strength(),
251            Self::SHA3_512(h) => h.max_security_strength(),
252        }
253    }
254}