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 bouncycastle_core::traits::XOF;
9//! use bouncycastle_factory::AlgorithmFactory;
10//! use bouncycastle_factory::xof_factory::XOFFactory;
11//! use bouncycastle_sha3 as sha3;
12//!
13//! let data: &[u8] = b"Hello, world!";
14//!
15//! let mut h = XOFFactory::new(sha3::SHAKE128_NAME).unwrap();
16//! h.absorb(data);
17//! let output: Vec<u8> = h.squeeze(16);
18//! ```
19//! You can equivalently invoke this by string instead of using the constant:
20//!
21//! ```
22//! use bouncycastle_factory::AlgorithmFactory;
23//! use bouncycastle_factory::xof_factory::XOFFactory;
24//!
25//! let mut h = XOFFactory::new("SHAKE128");
26//! ```
27//!
28//! Or, if you don't particularly care which algorithm you get, you can use the configured default:
29//!
30//! ```
31//! use bouncycastle_factory::AlgorithmFactory;
32//! use bouncycastle_factory::xof_factory::XOFFactory;
33//!
34//! let mut h = XOFFactory::default();
35//! ```
36
37use crate::{AlgorithmFactory, FactoryError};
38use bouncycastle_core::errors::HashError;
39use bouncycastle_core::traits::{KDF, SecurityStrength, XOF};
40use bouncycastle_sha3 as sha3;
41use bouncycastle_sha3::{SHAKE128_NAME, SHAKE256_NAME};
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// All members must impl XOF.
49pub enum XOFFactory {
50    SHAKE128(sha3::SHAKE128),
51    SHAKE256(sha3::SHAKE256),
52}
53
54impl Default for XOFFactory {
55    fn default() -> Self {
56        Self::new(DEFAULT_XOF_NAME).unwrap()
57    }
58}
59
60impl AlgorithmFactory for XOFFactory {
61    fn default_128_bit() -> Self {
62        Self::new(DEFAULT_128BIT_XOF_NAME).unwrap()
63    }
64
65    fn default_256_bit() -> Self {
66        Self::new(DEFAULT_256BIT_XOF_NAME).unwrap()
67    }
68
69    fn new(alg_name: &str) -> Result<Self, FactoryError> {
70        match alg_name {
71            SHAKE128_NAME => Ok(Self::SHAKE128(sha3::SHAKE128::new())),
72            SHAKE256_NAME => Ok(Self::SHAKE256(sha3::SHAKE256::new())),
73            _ => Err(FactoryError::UnsupportedAlgorithm(format!(
74                "The algorithm: \"{}\" is not a known XOF",
75                alg_name
76            ))),
77        }
78    }
79}
80impl XOF for XOFFactory {
81    fn hash_xof(self, data: &[u8], result_len: usize) -> Vec<u8> {
82        match self {
83            Self::SHAKE128(h) => h.hash_xof(data, result_len),
84            Self::SHAKE256(h) => h.hash_xof(data, result_len),
85        }
86    }
87
88    fn hash_xof_out(self, data: &[u8], output: &mut [u8]) -> usize {
89        match self {
90            Self::SHAKE128(h) => h.hash_xof_out(data, output),
91            Self::SHAKE256(h) => h.hash_xof_out(data, output),
92        }
93    }
94
95    fn absorb(&mut self, data: &[u8]) {
96        match self {
97            Self::SHAKE128(h) => h.absorb(data),
98            Self::SHAKE256(h) => h.absorb(data),
99        }
100    }
101
102    fn absorb_last_partial_byte(
103        &mut self,
104        partial_byte: u8,
105        num_partial_bits: usize,
106    ) -> Result<(), HashError> {
107        match self {
108            Self::SHAKE128(h) => h.absorb_last_partial_byte(partial_byte, num_partial_bits),
109            Self::SHAKE256(h) => h.absorb_last_partial_byte(partial_byte, num_partial_bits),
110        }
111    }
112
113    fn squeeze(&mut self, num_bytes: usize) -> Vec<u8> {
114        match self {
115            Self::SHAKE128(h) => h.squeeze(num_bytes),
116            Self::SHAKE256(h) => h.squeeze(num_bytes),
117        }
118    }
119
120    fn squeeze_out(&mut self, output: &mut [u8]) -> usize {
121        match self {
122            Self::SHAKE128(h) => h.squeeze_out(output),
123            Self::SHAKE256(h) => h.squeeze_out(output),
124        }
125    }
126
127    fn squeeze_partial_byte_final(self, num_bits: usize) -> Result<u8, HashError> {
128        match self {
129            Self::SHAKE128(h) => h.squeeze_partial_byte_final(num_bits),
130            Self::SHAKE256(h) => h.squeeze_partial_byte_final(num_bits),
131        }
132    }
133
134    fn squeeze_partial_byte_final_out(
135        self,
136        num_bits: usize,
137        output: &mut u8,
138    ) -> Result<(), HashError> {
139        match self {
140            Self::SHAKE128(h) => h.squeeze_partial_byte_final_out(num_bits, output),
141            Self::SHAKE256(h) => h.squeeze_partial_byte_final_out(num_bits, output),
142        }
143    }
144
145    fn max_security_strength(&self) -> SecurityStrength {
146        match self {
147            Self::SHAKE128(h) => KDF::max_security_strength(h),
148            Self::SHAKE256(h) => XOF::max_security_strength(h),
149        }
150    }
151}