1#![no_std]
6#![forbid(unsafe_code)]
7#![warn(missing_docs, missing_debug_implementations)]
8
9#[cfg(all(feature = "parallelhash", target_arch = "wasm32"))]
10compile_error!(
11 "parallelhash feature is not supported on wasm32; do not enable 'parallelhash' for WASM builds"
12);
13
14extern crate alloc;
15
16use alloc::boxed::Box;
17use alloc::vec::Vec;
18
19pub use digest::{
21 self,
22 CollisionResistance,
23 CustomizedInit,
24 Digest,
25 ExtendableOutput,
26 ExtendableOutputReset,
27 Update,
28};
29pub use lib_q_core::{
31 Algorithm,
32 Hash,
33 HashContext,
34 Result,
35};
36pub use lib_q_k12::{
38 Kt128,
39 Kt128Reader,
40 Kt256,
41 Kt256Reader,
42};
43pub use lib_q_keccak_digest::{
44 Keccak224,
45 Keccak256,
46 Keccak256Full,
47 Keccak384,
48 Keccak512,
49};
50pub use lib_q_sha3::{
51 Sha3_224,
52 Sha3_256,
53 Sha3_384,
54 Sha3_512,
55 Shake128,
56 Shake128Reader,
57 Shake256,
58 Shake256Reader,
59};
60
61mod cshake;
63mod hash_types;
64mod internal_block_api;
65mod kmac;
66mod parallelhash;
67#[cfg(feature = "alloc")]
68mod provider;
69mod sha2_hashes;
70mod shake;
71mod tuplehash;
72mod turbo_shake;
73mod utils;
74
75pub use cshake::{
77 CShake128,
78 CShake128Reader,
79 CShake256,
80 CShake256Reader,
81};
82pub use kmac::{
84 Kmac128,
85 Kmac128Reader,
86 Kmac256,
87 Kmac256Reader,
88};
89pub use parallelhash::{
90 ParallelHash128,
91 ParallelHash128Reader,
92 ParallelHash256,
93 ParallelHash256Reader,
94};
95#[cfg(feature = "alloc")]
97pub use provider::LibQHashProvider;
98pub use sha2_hashes::{
99 Sha224Hash,
100 Sha256Hash,
101 Sha384Hash,
102 Sha512_224Hash,
103 Sha512_256Hash,
104 Sha512Hash,
105};
106pub use shake::{
107 Shake128 as InternalShake128,
108 Shake128Reader as InternalShake128Reader,
109 Shake256 as InternalShake256,
110 Shake256Reader as InternalShake256Reader,
111};
112pub use tuplehash::{
113 TupleHash128,
114 TupleHash128Reader,
115 TupleHash256,
116 TupleHash256Reader,
117};
118pub use turbo_shake::{
119 TurboShake128,
120 TurboShake128Reader,
121 TurboShake256,
122 TurboShake256Reader,
123};
124pub use utils::MAX_SP800185_FIXED_OUTPUT_BYTES;
125
126pub use crate::hash_types::{
128 CShake128Hash,
129 CShake256Hash,
130 Keccak224Hash,
131 Keccak256Hash,
132 Keccak384Hash,
133 Keccak512Hash,
134 Kmac128Hash,
135 Kmac256Hash,
136 Kt128Hash,
137 Kt256Hash,
138 ParallelHash128Hash,
139 ParallelHash256Hash,
140 Sha3_224Hash,
141 Sha3_256Hash,
142 Sha3_384Hash,
143 Sha3_512Hash,
144 Shake128Hash,
145 Shake256Hash,
146 TupleHash128Hash,
147 TupleHash256Hash,
148 TurboShake128Hash,
149 TurboShake256Hash,
150};
151
152pub const PLEN: usize = 25;
155pub const DEFAULT_ROUND_COUNT: usize = 24;
157
158pub const KECCAK_PAD: u8 = 0x01;
161pub const SHA3_PAD: u8 = 0x06;
163pub const SHAKE_PAD: u8 = 0x1F;
165pub const CSHAKE_PAD: u8 = 0x04;
167
168#[derive(Debug, Clone, PartialEq, Eq)]
170pub enum HashAlgorithm {
171 Sha3_224,
173 Sha3_256,
175 Sha3_384,
177 Sha3_512,
179 Shake128,
181 Shake256,
183 Cshake128,
185 Cshake256,
187 Kt128,
189 Kt256,
191 Keccak224,
193 Keccak256,
195 Keccak384,
197 Keccak512,
199 TurboShake128,
201 TurboShake256,
203 Kmac128,
205 Kmac256,
207 TupleHash128,
209 TupleHash256,
211 ParallelHash128,
213 ParallelHash256,
215 Sha224,
217 Sha256,
219 Sha384,
221 Sha512,
223 Sha512_224,
225 Sha512_256,
227}
228
229impl HashAlgorithm {
230 pub fn output_size(&self) -> usize {
232 match self {
233 HashAlgorithm::Sha3_224 => 28,
234 HashAlgorithm::Sha3_256 => 32,
235 HashAlgorithm::Sha3_384 => 48,
236 HashAlgorithm::Sha3_512 => 64,
237 HashAlgorithm::Shake128 => 16,
238 HashAlgorithm::Shake256 => 32,
239 HashAlgorithm::Cshake128 => 16,
240 HashAlgorithm::Cshake256 => 32,
241 HashAlgorithm::Kt128 => 32,
242 HashAlgorithm::Kt256 => 64,
243 HashAlgorithm::Keccak224 => 28,
244 HashAlgorithm::Keccak256 => 32,
245 HashAlgorithm::Keccak384 => 48,
246 HashAlgorithm::Keccak512 => 64,
247 HashAlgorithm::TurboShake128 => 16,
248 HashAlgorithm::TurboShake256 => 32,
249 HashAlgorithm::Kmac128 => 16,
250 HashAlgorithm::Kmac256 => 32,
251 HashAlgorithm::TupleHash128 => 16,
252 HashAlgorithm::TupleHash256 => 32,
253 HashAlgorithm::ParallelHash128 => 16,
254 HashAlgorithm::ParallelHash256 => 32,
255 HashAlgorithm::Sha224 => 28,
256 HashAlgorithm::Sha256 => 32,
257 HashAlgorithm::Sha384 => 48,
258 HashAlgorithm::Sha512 => 64,
259 HashAlgorithm::Sha512_224 => 28,
260 HashAlgorithm::Sha512_256 => 32,
261 }
262 }
263}
264
265pub fn available_algorithms() -> Vec<&'static str> {
267 alloc::vec![
268 "sha3-224",
269 "sha3-256",
270 "sha3-384",
271 "sha3-512",
272 "shake128",
273 "shake256",
274 "cshake128",
275 "cshake256",
276 "kt128",
277 "kt256",
278 "kangarootwelve",
279 "keccak224",
280 "keccak256",
281 "keccak384",
282 "keccak512",
283 "turboshake128",
284 "turboshake256",
285 "kmac128",
286 "kmac256",
287 "tuplehash128",
288 "tuplehash256",
289 "parallelhash128",
290 "parallelhash256",
291 "sha-224",
292 "sha-256",
293 "sha-384",
294 "sha-512",
295 "sha-512/224",
296 "sha-512/256",
297 ]
298}
299
300pub fn algorithm_to_hash_algorithm(algorithm: Algorithm) -> Result<HashAlgorithm> {
302 match algorithm {
303 Algorithm::Sha3_224 => Ok(HashAlgorithm::Sha3_224),
304 Algorithm::Sha3_256 => Ok(HashAlgorithm::Sha3_256),
305 Algorithm::Sha3_384 => Ok(HashAlgorithm::Sha3_384),
306 Algorithm::Sha3_512 => Ok(HashAlgorithm::Sha3_512),
307 Algorithm::Shake128 => Ok(HashAlgorithm::Shake128),
308 Algorithm::Shake256 => Ok(HashAlgorithm::Shake256),
309 Algorithm::CShake128 => Ok(HashAlgorithm::Cshake128),
310 Algorithm::CShake256 => Ok(HashAlgorithm::Cshake256),
311 Algorithm::Kt128 => Ok(HashAlgorithm::Kt128),
312 Algorithm::Kt256 => Ok(HashAlgorithm::Kt256),
313 Algorithm::Keccak224 => Ok(HashAlgorithm::Keccak224),
314 Algorithm::Keccak256 => Ok(HashAlgorithm::Keccak256),
315 Algorithm::Keccak384 => Ok(HashAlgorithm::Keccak384),
316 Algorithm::Keccak512 => Ok(HashAlgorithm::Keccak512),
317 Algorithm::TurboShake128 => Ok(HashAlgorithm::TurboShake128),
318 Algorithm::TurboShake256 => Ok(HashAlgorithm::TurboShake256),
319 Algorithm::Kmac128 => Ok(HashAlgorithm::Kmac128),
320 Algorithm::Kmac256 => Ok(HashAlgorithm::Kmac256),
321 Algorithm::TupleHash128 => Ok(HashAlgorithm::TupleHash128),
322 Algorithm::TupleHash256 => Ok(HashAlgorithm::TupleHash256),
323 Algorithm::ParallelHash128 => Ok(HashAlgorithm::ParallelHash128),
324 Algorithm::ParallelHash256 => Ok(HashAlgorithm::ParallelHash256),
325 Algorithm::Sha224 => Ok(HashAlgorithm::Sha224),
326 Algorithm::Sha256 => Ok(HashAlgorithm::Sha256),
327 Algorithm::Sha384 => Ok(HashAlgorithm::Sha384),
328 Algorithm::Sha512 => Ok(HashAlgorithm::Sha512),
329 Algorithm::Sha512_224 => Ok(HashAlgorithm::Sha512_224),
330 Algorithm::Sha512_256 => Ok(HashAlgorithm::Sha512_256),
331 _ => Err(lib_q_core::Error::InvalidAlgorithm {
332 algorithm: "Algorithm is not a hash algorithm",
333 }),
334 }
335}
336
337pub fn create_hash(algorithm: HashAlgorithm) -> Result<Box<dyn lib_q_core::Hash>> {
339 match algorithm {
340 HashAlgorithm::Sha3_224 => Ok(Box::new(Sha3_224Hash::new())),
341 HashAlgorithm::Sha3_256 => Ok(Box::new(Sha3_256Hash::new())),
342 HashAlgorithm::Sha3_384 => Ok(Box::new(Sha3_384Hash::new())),
343 HashAlgorithm::Sha3_512 => Ok(Box::new(Sha3_512Hash::new())),
344 HashAlgorithm::Shake128 => Ok(Box::new(Shake128Hash::new())),
345 HashAlgorithm::Shake256 => Ok(Box::new(Shake256Hash::new())),
346 HashAlgorithm::Cshake128 => Ok(Box::new(CShake128Hash::new())),
347 HashAlgorithm::Cshake256 => Ok(Box::new(CShake256Hash::new())),
348 HashAlgorithm::Kmac128 => Ok(Box::new(Kmac128Hash::new())),
349 HashAlgorithm::Kmac256 => Ok(Box::new(Kmac256Hash::new())),
350 HashAlgorithm::TupleHash128 => Ok(Box::new(TupleHash128Hash::new())),
351 HashAlgorithm::TupleHash256 => Ok(Box::new(TupleHash256Hash::new())),
352 HashAlgorithm::ParallelHash128 => Ok(Box::new(ParallelHash128Hash::new())),
353 HashAlgorithm::ParallelHash256 => Ok(Box::new(ParallelHash256Hash::new())),
354 HashAlgorithm::Kt128 => Ok(Box::new(Kt128Hash::new())),
355 HashAlgorithm::Kt256 => Ok(Box::new(Kt256Hash::new())),
356 HashAlgorithm::Keccak224 => Ok(Box::new(Keccak224Hash::new())),
357 HashAlgorithm::Keccak256 => Ok(Box::new(Keccak256Hash::new())),
358 HashAlgorithm::Keccak384 => Ok(Box::new(Keccak384Hash::new())),
359 HashAlgorithm::Keccak512 => Ok(Box::new(Keccak512Hash::new())),
360 HashAlgorithm::TurboShake128 => Ok(Box::new(TurboShake128Hash::new())),
361 HashAlgorithm::TurboShake256 => Ok(Box::new(TurboShake256Hash::new())),
362 HashAlgorithm::Sha224 => Ok(Box::new(Sha224Hash::new())),
363 HashAlgorithm::Sha256 => Ok(Box::new(Sha256Hash::new())),
364 HashAlgorithm::Sha384 => Ok(Box::new(Sha384Hash::new())),
365 HashAlgorithm::Sha512 => Ok(Box::new(Sha512Hash::new())),
366 HashAlgorithm::Sha512_224 => Ok(Box::new(Sha512_224Hash::new())),
367 HashAlgorithm::Sha512_256 => Ok(Box::new(Sha512_256Hash::new())),
368 }
369}
370
371#[cfg(feature = "alloc")]
386pub fn create_hash_context() -> Result<HashContext> {
387 let provider = LibQHashProvider::new()?;
388 Ok(HashContext::with_provider(alloc::boxed::Box::new(provider)))
389}
390
391#[cfg(test)]
392mod tests {
393 use alloc::format;
394 use alloc::string::String;
395 use core::fmt::{
396 self,
397 Display,
398 };
399
400 use digest::block_api::AlgorithmName;
401
402 use super::*;
403
404 struct AlgName<T: AlgorithmName>(core::marker::PhantomData<T>);
405
406 impl<T: AlgorithmName> Display for AlgName<T> {
407 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
408 T::write_alg_name(f)
409 }
410 }
411
412 fn alg_name_string<T: AlgorithmName>() -> String {
413 format!("{}", AlgName::<T>(core::marker::PhantomData))
414 }
415
416 #[test]
417 fn test_available_algorithms() {
418 let algorithms = available_algorithms();
419 assert!(!algorithms.is_empty());
420 assert!(algorithms.contains(&"sha3-224"));
421 assert!(algorithms.contains(&"sha3-256"));
422 assert!(algorithms.contains(&"sha3-384"));
423 assert!(algorithms.contains(&"sha3-512"));
424 assert!(algorithms.contains(&"shake128"));
425 assert!(algorithms.contains(&"shake256"));
426 assert!(algorithms.contains(&"cshake256"));
427 assert!(algorithms.contains(&"kt128"));
428 assert!(algorithms.contains(&"kt256"));
429 assert!(algorithms.contains(&"kangarootwelve"));
430 assert!(algorithms.contains(&"keccak224"));
431 assert!(algorithms.contains(&"keccak256"));
432 assert!(algorithms.contains(&"keccak384"));
433 assert!(algorithms.contains(&"keccak512"));
434 assert!(algorithms.contains(&"sha-256"));
435 }
436
437 #[test]
438 fn test_sha256_known_answer() {
439 let h = Sha256Hash::new();
440 let out = h.hash(b"").expect("sha256");
441 assert_eq!(out.len(), 32);
442 assert_eq!(
443 out.as_slice(),
444 hex_literal::hex!("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
445 );
446 }
447
448 #[test]
449 fn test_cshake_implementations() {
450 let cshake = CShake256Hash::new();
452 let result = cshake.hash(b"Hello, World!").unwrap();
453 assert_eq!(result.len(), 32);
454 }
455
456 #[test]
457 fn test_cshake_customization() {
458 let cshake1 = CShake256Hash::new_customized(b"App1");
460 let cshake2 = CShake256Hash::new_customized(b"App2");
461
462 let hash1 = cshake1.hash(b"test").unwrap();
463 let hash2 = cshake2.hash(b"test").unwrap();
464
465 assert_ne!(hash1, hash2);
466 }
467
468 #[test]
469 fn test_invalid_algorithm_name() {
470 let result = algorithm_to_hash_algorithm(Algorithm::MlDsa65); assert!(result.is_err());
474 }
475
476 #[test]
477 fn hash_algorithm_output_size_exhaustive() {
478 use HashAlgorithm::*;
479 let all = [
480 Sha3_224,
481 Sha3_256,
482 Sha3_384,
483 Sha3_512,
484 Shake128,
485 Shake256,
486 Cshake128,
487 Cshake256,
488 Kt128,
489 Kt256,
490 Keccak224,
491 Keccak256,
492 Keccak384,
493 Keccak512,
494 TurboShake128,
495 TurboShake256,
496 Kmac128,
497 Kmac256,
498 TupleHash128,
499 TupleHash256,
500 ParallelHash128,
501 ParallelHash256,
502 Sha224,
503 Sha256,
504 Sha384,
505 Sha512,
506 Sha512_224,
507 Sha512_256,
508 ];
509 for a in all {
510 assert!(a.output_size() > 0);
511 }
512 }
513
514 #[test]
515 fn create_hash_smoke_all_variants() {
516 use HashAlgorithm::*;
517 let variants = [
518 Sha3_224,
519 Sha3_256,
520 Sha3_384,
521 Sha3_512,
522 Shake128,
523 Shake256,
524 Cshake128,
525 Cshake256,
526 Kmac128,
527 Kmac256,
528 TupleHash128,
529 TupleHash256,
530 ParallelHash128,
531 ParallelHash256,
532 Kt128,
533 Kt256,
534 Keccak224,
535 Keccak256,
536 Keccak384,
537 Keccak512,
538 TurboShake128,
539 TurboShake256,
540 Sha224,
541 Sha256,
542 Sha384,
543 Sha512,
544 Sha512_224,
545 Sha512_256,
546 ];
547 for alg in variants {
548 let h = create_hash(alg.clone()).expect("create_hash");
549 let out = h.hash(b"coverage").expect("hash");
550 assert_eq!(out.len(), alg.output_size());
551 }
552 }
553
554 #[test]
555 fn algorithm_to_hash_algorithm_roundtrip_core() {
556 let pairs = [
557 (Algorithm::Sha3_224, HashAlgorithm::Sha3_224),
558 (Algorithm::Sha3_256, HashAlgorithm::Sha3_256),
559 (Algorithm::Shake128, HashAlgorithm::Shake128),
560 (Algorithm::CShake256, HashAlgorithm::Cshake256),
561 (Algorithm::Kmac128, HashAlgorithm::Kmac128),
562 (Algorithm::TupleHash256, HashAlgorithm::TupleHash256),
563 (Algorithm::ParallelHash128, HashAlgorithm::ParallelHash128),
564 (Algorithm::Kt128, HashAlgorithm::Kt128),
565 (Algorithm::Kt256, HashAlgorithm::Kt256),
566 (Algorithm::Keccak256, HashAlgorithm::Keccak256),
567 (Algorithm::TurboShake128, HashAlgorithm::TurboShake128),
568 (Algorithm::Sha256, HashAlgorithm::Sha256),
569 (Algorithm::Sha512_256, HashAlgorithm::Sha512_256),
570 ];
571 for (core, expected) in pairs {
572 assert_eq!(algorithm_to_hash_algorithm(core).unwrap(), expected);
573 }
574 }
575
576 #[cfg(feature = "alloc")]
577 #[test]
578 fn create_hash_context_returns_functional_context() {
579 let mut ctx = create_hash_context().expect("context");
580 let digest = ctx
581 .hash(Algorithm::Sha3_256, b"lib-q-hash context test")
582 .unwrap();
583 assert_eq!(digest.len(), 32);
584 }
585
586 #[test]
587 fn turboshake_hasher_alg_name_and_debug() {
588 let hasher = TurboShake128::<6>::default();
589 assert_eq!(alg_name_string::<TurboShake128<6>>(), "TurboSHAKE128");
590 assert_eq!(format!("{hasher:?}"), "TurboShake128 { ... }");
591 }
592}