dcrypt_algorithms/xof/
mod.rs1#![cfg_attr(not(feature = "std"), no_std)]
7
8#[cfg(feature = "alloc")]
9extern crate alloc;
10
11#[cfg(not(feature = "std"))]
12#[cfg(feature = "alloc")]
13use alloc::vec::Vec;
14
15#[cfg(feature = "std")]
16use std::vec::Vec;
17
18use crate::error::{validate, Error, Result};
19
20#[cfg(feature = "alloc")]
21pub mod shake;
22
23#[cfg(feature = "alloc")]
24pub mod blake3;
25
26#[cfg(feature = "alloc")]
28pub use shake::{ShakeXof128, ShakeXof256};
29
30#[cfg(feature = "alloc")]
31pub use blake3::Blake3Xof;
32
33#[cfg(feature = "alloc")]
35pub type Xof = Vec<u8>;
36
37pub trait ExtendableOutputFunction {
39 fn new() -> Self;
41
42 fn update(&mut self, data: &[u8]) -> Result<()>;
44
45 fn finalize(&mut self) -> Result<()>;
47
48 fn squeeze(&mut self, output: &mut [u8]) -> Result<()>;
50
51 #[cfg(feature = "alloc")]
53 fn squeeze_into_vec(&mut self, len: usize) -> Result<Vec<u8>>;
54
55 fn reset(&mut self) -> Result<()>;
57
58 fn security_level() -> usize;
60
61 #[cfg(feature = "alloc")]
63 fn generate(data: &[u8], len: usize) -> Result<Vec<u8>>
64 where
65 Self: Sized,
66 {
67 validate::parameter(
68 len > 0,
69 "output_length",
70 "XOF output length must be greater than 0",
71 )?;
72
73 let mut xof = Self::new();
74 xof.update(data)?;
75 xof.squeeze_into_vec(len)
76 }
77}
78
79pub trait XofAlgorithm {
81 const SECURITY_LEVEL: usize;
83
84 const MIN_OUTPUT_SIZE: usize;
86
87 const MAX_OUTPUT_SIZE: Option<usize>;
89
90 const ALGORITHM_ID: &'static str;
92
93 fn name() -> &'static str {
95 Self::ALGORITHM_ID
96 }
97
98 fn validate_output_length(len: usize) -> Result<()> {
100 validate::parameter(
101 len >= Self::MIN_OUTPUT_SIZE,
102 "output_length",
103 "Output length below minimum recommended size",
104 )?;
105
106 if let Some(max) = Self::MAX_OUTPUT_SIZE {
107 validate::max_length("XOF output", len, max)?;
108 }
109
110 Ok(())
111 }
112}
113
114pub enum Shake128Algorithm {}
116
117impl XofAlgorithm for Shake128Algorithm {
118 const SECURITY_LEVEL: usize = 128;
119 const MIN_OUTPUT_SIZE: usize = 16; const MAX_OUTPUT_SIZE: Option<usize> = None; const ALGORITHM_ID: &'static str = "SHAKE-128";
122}
123
124pub enum Shake256Algorithm {}
126
127impl XofAlgorithm for Shake256Algorithm {
128 const SECURITY_LEVEL: usize = 256;
129 const MIN_OUTPUT_SIZE: usize = 32; const MAX_OUTPUT_SIZE: Option<usize> = None; const ALGORITHM_ID: &'static str = "SHAKE-256";
132}
133
134pub enum Blake3Algorithm {}
136
137impl XofAlgorithm for Blake3Algorithm {
138 const SECURITY_LEVEL: usize = 256;
139 const MIN_OUTPUT_SIZE: usize = 32; const MAX_OUTPUT_SIZE: Option<usize> = None; const ALGORITHM_ID: &'static str = "BLAKE3-XOF";
142}
143
144pub trait KeyedXof: ExtendableOutputFunction {
146 fn with_key(key: &[u8]) -> Result<Self>
148 where
149 Self: Sized;
150
151 #[cfg(feature = "alloc")]
153 fn keyed_generate(key: &[u8], data: &[u8], len: usize) -> Result<Vec<u8>>
154 where
155 Self: Sized,
156 {
157 validate::parameter(
158 len > 0,
159 "output_length",
160 "XOF output length must be greater than 0",
161 )?;
162
163 let mut xof = Self::with_key(key)?;
164 xof.update(data)?;
165 xof.squeeze_into_vec(len)
166 }
167}
168
169pub trait DeriveKeyXof: ExtendableOutputFunction {
171 fn for_derive_key(context: &[u8]) -> Result<Self>
173 where
174 Self: Sized;
175
176 #[cfg(feature = "alloc")]
178 fn derive_key(context: &[u8], data: &[u8], len: usize) -> Result<Vec<u8>>
179 where
180 Self: Sized,
181 {
182 validate::parameter(
183 len > 0,
184 "output_length",
185 "Key derivation output length must be greater than 0",
186 )?;
187
188 let mut xof = Self::for_derive_key(context)?;
189 xof.update(data)?;
190 xof.squeeze_into_vec(len)
191 }
192}
193
194impl Error {
196 pub(crate) fn xof_finalized() -> Self {
198 Error::Processing {
199 operation: "XOF",
200 details: "Cannot update after finalization",
201 }
202 }
203
204 pub(crate) fn xof_squeezing() -> Self {
206 Error::Processing {
207 operation: "XOF",
208 details: "Cannot update after squeezing has begun",
209 }
210 }
211}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216
217 #[test]
218 fn test_xof_algorithm_validation() {
219 assert!(Shake128Algorithm::validate_output_length(16).is_ok());
221 assert!(Shake128Algorithm::validate_output_length(15).is_err());
222
223 assert!(Shake256Algorithm::validate_output_length(32).is_ok());
225 assert!(Shake256Algorithm::validate_output_length(31).is_err());
226
227 assert!(Blake3Algorithm::validate_output_length(32).is_ok());
229 assert!(Blake3Algorithm::validate_output_length(31).is_err());
230 }
231}