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//! Equivalently, it may be invoked by passing a 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//! If the algorithm used is not particularly important, the configured default may be used:
28//!
29//! ```
30//! use bouncycastle_factory::AlgorithmFactory;
31//! use bouncycastle_factory::xof_factory::XOFFactory;
32//!
33//! let mut h = XOFFactory::default();
34//! ```
35
36use crate::{AlgorithmFactory, FactoryError};
37use bouncycastle_core::errors::HashError;
38use bouncycastle_core::traits::{KDF, SecurityStrength, XOF};
39use bouncycastle_sha3 as sha3;
40use bouncycastle_sha3::{SHAKE128_NAME, SHAKE256_NAME};
41
42/*** Defaults ***/
43///
44pub const DEFAULT_XOF_NAME: &str = SHAKE128_NAME;
45///
46pub const DEFAULT_128BIT_XOF_NAME: &str = SHAKE128_NAME;
47///
48pub const DEFAULT_256BIT_XOF_NAME: &str = SHAKE256_NAME;
49
50/// Wrapper object for all algorithms that impl [`XOF`].
51pub enum XOFFactory {
52    ///
53    SHAKE128(sha3::SHAKE128),
54    ///
55    SHAKE256(sha3::SHAKE256),
56}
57
58impl Default for XOFFactory {
59    fn default() -> Self {
60        Self::new(DEFAULT_XOF_NAME).unwrap()
61    }
62}
63
64impl AlgorithmFactory for XOFFactory {
65    fn default_128_bit() -> Self {
66        Self::new(DEFAULT_128BIT_XOF_NAME).unwrap()
67    }
68
69    fn default_256_bit() -> Self {
70        Self::new(DEFAULT_256BIT_XOF_NAME).unwrap()
71    }
72
73    fn new(alg_name: &str) -> Result<Self, FactoryError> {
74        match alg_name {
75            SHAKE128_NAME => Ok(Self::SHAKE128(sha3::SHAKE128::new())),
76            SHAKE256_NAME => Ok(Self::SHAKE256(sha3::SHAKE256::new())),
77            _ => Err(FactoryError::UnsupportedAlgorithm(format!(
78                "The algorithm: \"{}\" is not a known XOF",
79                alg_name
80            ))),
81        }
82    }
83}
84impl XOF for XOFFactory {
85    fn hash_xof(self, data: &[u8], result_len: usize) -> Vec<u8> {
86        match self {
87            Self::SHAKE128(h) => h.hash_xof(data, result_len),
88            Self::SHAKE256(h) => h.hash_xof(data, result_len),
89        }
90    }
91
92    fn hash_xof_out(self, data: &[u8], output: &mut [u8]) -> usize {
93        output.fill(0);
94
95        match self {
96            Self::SHAKE128(h) => h.hash_xof_out(data, output),
97            Self::SHAKE256(h) => h.hash_xof_out(data, output),
98        }
99    }
100
101    fn absorb(&mut self, data: &[u8]) -> Result<(), HashError> {
102        match self {
103            Self::SHAKE128(h) => h.absorb(data),
104            Self::SHAKE256(h) => h.absorb(data),
105        }
106    }
107
108    fn absorb_last_partial_byte(
109        &mut self,
110        partial_byte: u8,
111        num_partial_bits: usize,
112    ) -> Result<(), HashError> {
113        match self {
114            Self::SHAKE128(h) => h.absorb_last_partial_byte(partial_byte, num_partial_bits),
115            Self::SHAKE256(h) => h.absorb_last_partial_byte(partial_byte, num_partial_bits),
116        }
117    }
118
119    fn squeeze(&mut self, num_bytes: usize) -> Vec<u8> {
120        match self {
121            Self::SHAKE128(h) => h.squeeze(num_bytes),
122            Self::SHAKE256(h) => h.squeeze(num_bytes),
123        }
124    }
125
126    fn squeeze_out(&mut self, output: &mut [u8]) -> usize {
127        output.fill(0);
128
129        match self {
130            Self::SHAKE128(h) => h.squeeze_out(output),
131            Self::SHAKE256(h) => h.squeeze_out(output),
132        }
133    }
134
135    fn squeeze_partial_byte_final(self, num_bits: usize) -> Result<u8, HashError> {
136        match self {
137            Self::SHAKE128(h) => h.squeeze_partial_byte_final(num_bits),
138            Self::SHAKE256(h) => h.squeeze_partial_byte_final(num_bits),
139        }
140    }
141
142    fn squeeze_partial_byte_final_out(
143        self,
144        num_bits: usize,
145        output: &mut u8,
146    ) -> Result<(), HashError> {
147        *output = 0;
148
149        match self {
150            Self::SHAKE128(h) => h.squeeze_partial_byte_final_out(num_bits, output),
151            Self::SHAKE256(h) => h.squeeze_partial_byte_final_out(num_bits, output),
152        }
153    }
154
155    fn max_security_strength(&self) -> SecurityStrength {
156        match self {
157            Self::SHAKE128(h) => KDF::max_security_strength(h),
158            Self::SHAKE256(h) => XOF::max_security_strength(h),
159        }
160    }
161}