Skip to main content

lib_q_k12/
lib.rs

1#![no_std]
2#![doc = include_str!("../README.md")]
3#![doc(
4    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
5    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
6)]
7#![forbid(unsafe_code)]
8#![warn(missing_docs, unreachable_pub)]
9
10#[cfg(feature = "alloc")]
11extern crate alloc;
12
13pub use digest;
14
15/// Block-level types
16pub mod block_api;
17
18use core::fmt;
19
20use digest::block_api::{
21    AlgorithmName,
22    BlockSizeUser,
23    ExtendableOutputCore,
24    UpdateCore,
25    XofReaderCore,
26};
27use digest::block_buffer::{
28    BlockBuffer,
29    Eager,
30    ReadBuffer,
31};
32use digest::consts::{
33    U16,
34    U32,
35    U128,
36    U136,
37    U168,
38};
39use digest::{
40    CollisionResistance,
41    ExtendableOutput,
42    HashMarker,
43    Reset,
44    Update,
45    XofReader,
46};
47
48macro_rules! impl_k12 {
49    (
50        $name:ident, $reader_name:ident, $core_name:ident, $reader_core_name:ident, $rate:ty,
51        $alg_name:literal,
52    ) => {
53        #[doc = $alg_name]
54        #[doc = " hasher."]
55        #[derive(Default, Clone)]
56        pub struct $name<'cs> {
57            core: block_api::$core_name<'cs>,
58            buffer: BlockBuffer<U128, Eager>,
59        }
60
61        impl<'cs> $name<'cs> {
62            #[doc = "Creates a new"]
63            #[doc = $alg_name]
64            #[doc = " instance with the given customization string."]
65            pub fn new(customization: &'cs [u8]) -> Self {
66                Self {
67                    core: block_api::$core_name::new(customization),
68                    buffer: Default::default(),
69                }
70            }
71        }
72
73        impl fmt::Debug for $name<'_> {
74            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
75                f.write_str(concat!(stringify!($name), " { .. }"))
76            }
77        }
78
79        impl AlgorithmName for $name<'_> {
80            fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
81                f.write_str($alg_name)
82            }
83        }
84
85        impl HashMarker for $name<'_> {}
86
87        impl BlockSizeUser for $name<'_> {
88            type BlockSize = U128;
89        }
90
91        impl Update for $name<'_> {
92            fn update(&mut self, data: &[u8]) {
93                let Self { core, buffer } = self;
94                buffer.digest_blocks(data, |blocks| core.update_blocks(blocks));
95            }
96        }
97
98        impl Reset for $name<'_> {
99            fn reset(&mut self) {
100                self.core.reset();
101                self.buffer.reset();
102            }
103        }
104
105        impl ExtendableOutput for $name<'_> {
106            type Reader = $reader_name;
107
108            #[inline]
109            fn finalize_xof(mut self) -> Self::Reader {
110                Self::Reader {
111                    core: self.core.finalize_xof_core(&mut self.buffer),
112                    buffer: Default::default(),
113                }
114            }
115        }
116
117        #[cfg(feature = "zeroize")]
118        impl digest::zeroize::ZeroizeOnDrop for $name<'_> {}
119
120        #[doc = $alg_name]
121        #[doc = " XOF reader."]
122        pub struct $reader_name {
123            core: block_api::$reader_core_name,
124            buffer: ReadBuffer<$rate>,
125        }
126
127        impl fmt::Debug for $reader_name {
128            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
129                f.write_str(concat!(stringify!($reader_name), " { .. }"))
130            }
131        }
132
133        impl XofReader for $reader_name {
134            #[inline]
135            fn read(&mut self, buffer: &mut [u8]) {
136                let Self { core, buffer: buf } = self;
137                buf.read(buffer, |block| *block = core.read_block());
138            }
139        }
140
141        #[cfg(feature = "zeroize")]
142        impl digest::zeroize::ZeroizeOnDrop for $reader_name {}
143    };
144}
145
146impl_k12!(
147    Kt128,
148    Kt128Reader,
149    Kt128Core,
150    Kt128ReaderCore,
151    U168,
152    "KT128",
153);
154impl_k12!(
155    Kt256,
156    Kt256Reader,
157    Kt256Core,
158    Kt256ReaderCore,
159    U136,
160    "KT256",
161);
162
163/// 128-bit collision resistance per [RFC 9861 §7.7][rfc], conditional on output length: this
164/// figure applies at an output of at least `2 * CollisionResistance` = 32 bytes, per the
165/// [`digest::CollisionResistance`] trait contract. `Kt128` is a XOF with no fixed output size,
166/// so that length is the caller's choice: at a shorter output, the same contract gives
167/// `min(CollisionResistance, OutputSize / 2)` bytes.
168///
169/// [rfc]: https://www.rfc-editor.org/rfc/rfc9861.html#section-7-7
170impl CollisionResistance for Kt128<'_> {
171    type CollisionResistance = U16;
172}
173
174/// 256-bit collision resistance per [RFC 9861 §7.8][rfc], conditional on output length: this
175/// figure applies at an output of at least `2 * CollisionResistance` = **64 bytes**, per the
176/// [`digest::CollisionResistance`] trait contract. `Kt256` is a XOF with no fixed output size,
177/// so that length is the caller's choice: at a shorter output, the same contract gives
178/// `min(CollisionResistance, OutputSize / 2)` bytes — e.g. **128-bit**, not 256-bit, at the
179/// 32-byte output used in this crate's examples.
180///
181/// [rfc]: https://www.rfc-editor.org/rfc/rfc9861.html#section-7-8
182impl CollisionResistance for Kt256<'_> {
183    type CollisionResistance = U32;
184}