Skip to main content

bouncycastle_factory/
xof_factory.rs

1//! XOF factory for creating instances of algorithms that implement the [XOF] trait.
2//!
3//! As with all Factory objects, this implements constructions from strings and defaults, and
4//! returns a [XOFFactory] object which itself implements the [XOF] trait as a pass-through to the underlying algorithm.
5//!
6//! Example usage:
7//! ```
8//! use core_interface::traits::XOF;
9//! use factory::AlgorithmFactory;
10//! use factory::xof_factory::XOFFactory;
11//!
12//! let data: &[u8] = b"Hello, world!";
13//!
14//! let mut h = XOFFactory::new(sha3::SHAKE128_NAME).unwrap();
15//! h.absorb(data).unwrap();
16//! let output: Vec<u8> = h.squeeze(16).unwrap();
17//! ```
18//! You can equivalently invoke this by string instead of using the constant:
19//!
20//! ```
21//! use factory::AlgorithmFactory;
22//! use factory::xof_factory::XOFFactory;
23//!
24//! let mut h = XOFFactory::new("SHAKE128").unwrap();
25//! ```
26//!
27//! Or, if you don't particularly care which algorithm you get, you can use the configured default:
28//!
29//! ```
30//! use factory::AlgorithmFactory;
31//! use factory::xof_factory::XOFFactory;
32//!
33//! let mut h = XOFFactory::default();
34//! ```
35
36use bouncycastle_sha3 as sha3;
37use bouncycastle_core_interface::errors::HashError;
38use bouncycastle_core_interface::traits::{SecurityStrength, KDF, XOF};
39use bouncycastle_sha3::{SHAKE128_NAME, SHAKE256_NAME};
40use crate::{AlgorithmFactory, FactoryError};
41
42
43/*** Defaults ***/
44pub const DEFAULT_XOF_NAME: &str = SHAKE128_NAME;
45pub const DEFAULT_128BIT_XOF_NAME: &str = SHAKE128_NAME;
46pub const DEFAULT_256BIT_XOF_NAME: &str = SHAKE256_NAME;
47
48
49// All members must impl XOF.
50pub enum XOFFactory {
51    SHAKE128(sha3::SHAKE128),
52    SHAKE256(sha3::SHAKE256),
53}
54
55impl Default for XOFFactory {
56    fn default() -> Self {
57        Self::new(DEFAULT_XOF_NAME).unwrap()
58    }
59}
60
61impl AlgorithmFactory for XOFFactory {
62    fn default_128_bit() -> Self {
63        Self::new(DEFAULT_128BIT_XOF_NAME).unwrap()
64    }
65
66    fn default_256_bit() -> Self { Self::new(DEFAULT_256BIT_XOF_NAME).unwrap() }
67
68    fn new(alg_name: &str) -> Result<Self, FactoryError> {
69        match alg_name {
70            SHAKE128_NAME => Ok(Self::SHAKE128(sha3::SHAKE128::new())),
71            SHAKE256_NAME => Ok(Self::SHAKE256(sha3::SHAKE256::new())),
72            _ => Err(FactoryError::UnsupportedAlgorithm(format!("The algorithm: \"{}\" is not a known XOF", alg_name))),
73        }
74    }
75}
76impl XOF for XOFFactory {
77    fn hash_xof(self, data: &[u8], result_len: usize) -> Vec<u8> {
78        match self {
79            Self::SHAKE128(h) => h.hash_xof(data, result_len),
80            Self::SHAKE256(h) => h.hash_xof(data, result_len),
81        }
82    }
83
84    fn hash_xof_out(self, data: &[u8], output: &mut [u8]) -> usize {
85        match self {
86            Self::SHAKE128(h) => h.hash_xof_out(data, output),
87            Self::SHAKE256(h) => h.hash_xof_out(data, output),
88        }
89    }
90
91    fn absorb(&mut self, data: &[u8]) -> Result<(), HashError> {
92        match self {
93            Self::SHAKE128(h) => h.absorb(data),
94            Self::SHAKE256(h) => h.absorb(data),
95        }
96    }
97
98    fn absorb_last_partial_byte(&mut self, partial_byte: u8, num_partial_bits: usize) -> Result<(), HashError> {
99        match self {
100            Self::SHAKE128(h) => h.absorb_last_partial_byte(partial_byte, num_partial_bits),
101            Self::SHAKE256(h) => h.absorb_last_partial_byte(partial_byte, num_partial_bits),
102        }
103    }
104
105    fn squeeze(&mut self, num_bytes: usize) -> Result<Vec<u8>, HashError> {
106        match self {
107            Self::SHAKE128(h) => h.squeeze(num_bytes),
108            Self::SHAKE256(h) => h.squeeze(num_bytes),
109        }
110    }
111
112    fn squeeze_out(&mut self, output: &mut [u8]) -> Result<usize, HashError> {
113        match self {
114            Self::SHAKE128(h) => h.squeeze_out(output),
115            Self::SHAKE256(h) => h.squeeze_out(output),
116        }
117    }
118
119    fn squeeze_partial_byte_final(self, num_bits: usize) -> Result<u8, HashError> {
120        match self {
121            Self::SHAKE128(h) => h.squeeze_partial_byte_final(num_bits),
122            Self::SHAKE256(h) => h.squeeze_partial_byte_final(num_bits),
123        }
124    }
125
126    fn squeeze_partial_byte_final_out(self, num_bits: usize, output: &mut u8) -> Result<(), HashError> {
127        match self {
128            Self::SHAKE128(h) => h.squeeze_partial_byte_final_out(num_bits, output),
129            Self::SHAKE256(h) => h.squeeze_partial_byte_final_out(num_bits, output),
130        }
131    }
132
133    fn max_security_strength(&self) -> SecurityStrength {
134        match self {
135            Self::SHAKE128(h) => KDF::max_security_strength(h),
136            Self::SHAKE256(h) => XOF::max_security_strength(h),
137        }
138    }
139}