sha3_const/
lib.rs

1//! `const fn` implementation of the SHA-3 family of hash and extendable-output
2//! functions.
3//!
4//! This crate allows you to use the SHA-3 hash and extendable-output functions
5//! as constant expressions in Rust. For all other usages, the [sha3](https://crates.io/crates/sha3)
6//! crate includes more optimized implementations of these hash functions.
7//!
8//! # Examples
9//!
10//! ```rust
11//! # use sha3_const::Shake256;
12//! const PSEUDO_RANDOM_BYTES: [u8; 1000] = Shake256::new()
13//!         .update(b"The quick brown fox ")
14//!         .update(b"jumps over the lazy dog")
15//!         .finalize();
16//! ```
17//!
18//! ```rust
19//! #![feature(const_mut_refs)]
20//! # use sha3_const::Shake128;
21//! const ROUND_CONSTANTS: [u128; 8] = {
22//!     let shake = Shake128::new()
23//!         .update(b"The quick brown fox ")
24//!         .update(b"jumps over the lazy dog");
25//!
26//!     let mut reader = shake.finalize_xof();
27//!     let mut output = [0; 8];
28//!
29//!     let mut i = 0;
30//!     while i < 8 {
31//!         let mut buf = [0; 16];
32//!         reader.read(&mut buf);
33//!         output[i] = u128::from_be_bytes(buf);
34//!         i += 1;
35//!     }
36//!
37//!     output
38//! };
39//!
40//! assert_eq!(
41//!     [
42//!         324498722242859095401832112442782838951,
43//!         100470442341479765851591908475476895342,
44//!         241049111671168257801898223573666863059,
45//!         139197826094415251816510671569090212218,
46//!         73371475849610774600276735485442220492,
47//!         321031806373587100556524628628207173306,
48//!         70553598458795679727810425741185559539,
49//!         297273966300911440566694043047331846682,
50//!     ],
51//!     ROUND_CONSTANTS,
52//! );
53//! ```
54
55#![feature(const_mut_refs)]
56#![no_std]
57
58mod keccak;
59
60use keccak::KeccakState;
61use keccak::XofReader;
62
63const PADDING_SHA3: u8 = 0x06;
64const PADDING_KECCAK: u8 = 0x01;
65
66macro_rules! sha3 {
67    (
68        $(#[$doc:meta])* $name:ident,
69        $security:literal,
70        $padding:expr,
71    ) => {
72        $(#[$doc])*
73        #[derive(Clone)]
74        pub struct $name {
75            state: KeccakState,
76        }
77
78        impl $name {
79            /// Constructs a new hasher
80            pub const fn new() -> $name {
81                $name {
82                    state: KeccakState::new($security, $padding),
83                }
84            }
85
86            /// Absorbs additional input
87            ///
88            /// Can be called multiple times
89            pub const fn update(mut self, input: &[u8]) -> Self {
90                // usee `mut self` instead of `&mut self` because
91                // mutable references are unstable in constants.
92                self.state.update(input);
93                self
94            }
95
96            /// Pads and squeezes the state to the output
97            pub const fn finalize(&self) -> [u8; {$security / 8}] {
98                let mut reader = self.state.finalize();
99                let mut output = [0; {$security / 8}];
100                reader.read(&mut output);
101                output
102            }
103        }
104    };
105}
106
107sha3!(
108    /// The `SHA3-224` hash function
109    ///
110    /// # Examples
111    ///
112    /// ```rust
113    /// # use sha3_const::Sha3_224;
114    /// const DIGEST: [u8; 28] = Sha3_224::new()
115    ///     .update(b"The quick brown fox ")
116    ///     .update(b"jumps over the lazy dog")
117    ///     .finalize();
118    ///
119    /// assert_eq!(
120    ///     [
121    ///         0xd1, 0x5d, 0xad, 0xce, 0xaa, 0x4d, 0x5d, 0x7b, 0xb3, 0xb4, 0x8f, 0x44, 0x64, 0x21,
122    ///         0xd5, 0x42, 0xe0, 0x8a, 0xd8, 0x88, 0x73, 0x05, 0xe2, 0x8d, 0x58, 0x33, 0x57, 0x95
123    ///     ],
124    ///     DIGEST,
125    /// );
126    /// ```
127    Sha3_224,
128    224,
129    PADDING_SHA3,
130);
131
132sha3!(
133    /// The `SHA3-256` hash function
134    ///
135    /// # Examples
136    ///
137    /// ```rust
138    /// # use sha3_const::Sha3_256;
139    /// const DIGEST: [u8; 32] = Sha3_256::new()
140    ///     .update(b"The quick brown fox ")
141    ///     .update(b"jumps over the lazy dog")
142    ///     .finalize();
143    ///
144    /// assert_eq!(
145    ///     [
146    ///         0x69, 0x07, 0x0d, 0xda, 0x01, 0x97, 0x5c, 0x8c, 0x12, 0x0c, 0x3a, 0xad, 0xa1, 0xb2,
147    ///         0x82, 0x39, 0x4e, 0x7f, 0x03, 0x2f, 0xa9, 0xcf, 0x32, 0xf4, 0xcb, 0x22, 0x59, 0xa0,
148    ///         0x89, 0x7d, 0xfc, 0x04
149    ///     ],
150    ///     DIGEST,
151    /// );
152    /// ```
153    Sha3_256,
154    256,
155    PADDING_SHA3,
156);
157
158sha3!(
159    /// The `SHA3-384` hash function
160    ///
161    /// # Examples
162    ///
163    /// ```rust
164    /// # use sha3_const::Sha3_384;
165    /// const DIGEST: [u8; 48] = Sha3_384::new()
166    ///     .update(b"The quick brown fox ")
167    ///     .update(b"jumps over the lazy dog")
168    ///     .finalize();
169    ///
170    /// assert_eq!(
171    ///     [
172    ///         0x70, 0x63, 0x46, 0x5e, 0x08, 0xa9, 0x3b, 0xce, 0x31, 0xcd, 0x89, 0xd2, 0xe3, 0xca,
173    ///         0x8f, 0x60, 0x24, 0x98, 0x69, 0x6e, 0x25, 0x35, 0x92, 0xed, 0x26, 0xf0, 0x7b, 0xf7,
174    ///         0xe7, 0x03, 0xcf, 0x32, 0x85, 0x81, 0xe1, 0x47, 0x1a, 0x7b, 0xa7, 0xab, 0x11, 0x9b,
175    ///         0x1a, 0x9e, 0xbd, 0xf8, 0xbe, 0x41
176    ///     ],
177    ///     DIGEST,
178    /// );
179    /// ```
180    Sha3_384,
181    384,
182    PADDING_SHA3,
183);
184
185sha3!(
186    /// The `SHA3-512` hash function
187    ///
188    /// # Examples
189    ///
190    /// ```rust
191    /// # use sha3_const::Sha3_512;
192    /// const DIGEST: [u8; 64] = Sha3_512::new()
193    ///     .update(b"The quick brown fox ")
194    ///     .update(b"jumps over the lazy dog")
195    ///     .finalize();
196    ///
197    /// assert_eq!(
198    ///     [
199    ///         0x01, 0xde, 0xdd, 0x5d, 0xe4, 0xef, 0x14, 0x64, 0x24, 0x45, 0xba, 0x5f, 0x5b, 0x97,
200    ///         0xc1, 0x5e, 0x47, 0xb9, 0xad, 0x93, 0x13, 0x26, 0xe4, 0xb0, 0x72, 0x7c, 0xd9, 0x4c,
201    ///         0xef, 0xc4, 0x4f, 0xff, 0x23, 0xf0, 0x7b, 0xf5, 0x43, 0x13, 0x99, 0x39, 0xb4, 0x91,
202    ///         0x28, 0xca, 0xf4, 0x36, 0xdc, 0x1b, 0xde, 0xe5, 0x4f, 0xcb, 0x24, 0x02, 0x3a, 0x08,
203    ///         0xd9, 0x40, 0x3f, 0x9b, 0x4b, 0xf0, 0xd4, 0x50
204    ///     ],
205    ///     DIGEST,
206    /// );
207    /// ```
208    Sha3_512,
209    512,
210    PADDING_SHA3,
211);
212
213sha3!(
214    /// The `KECCAK-224` hash function
215    ///
216    /// # Examples
217    ///
218    /// ```rust
219    /// # use sha3_const::Keccak224;
220    /// const DIGEST: [u8; 28] = Keccak224::new()
221    ///     .update(b"The quick brown fox ")
222    ///     .update(b"jumps over the lazy dog")
223    ///     .finalize();
224    ///
225    /// assert_eq!(
226    ///     [
227    ///         0x31, 0x0a, 0xee, 0x6b, 0x30, 0xc4, 0x73, 0x50, 0x57, 0x6a, 0xc2, 0x87, 0x3f, 0xa8,
228    ///         0x9f, 0xd1, 0x90, 0xcd, 0xc4, 0x88, 0x44, 0x2f, 0x3e, 0xf6, 0x54, 0xcf, 0x23, 0xfe
229    ///     ],
230    ///     DIGEST,
231    /// );
232    /// ```
233    Keccak224,
234    224,
235    PADDING_KECCAK,
236);
237
238sha3!(
239    /// The `KECCAK-256` hash function
240    ///
241    /// # Examples
242    ///
243    /// ```rust
244    /// # use sha3_const::Keccak256;
245    /// const DIGEST: [u8; 32] = Keccak256::new()
246    ///     .update(b"The quick brown fox ")
247    ///     .update(b"jumps over the lazy dog")
248    ///     .finalize();
249    ///
250    /// assert_eq!(
251    ///     [
252    ///         0x4d, 0x74, 0x1b, 0x6f, 0x1e, 0xb2, 0x9c, 0xb2, 0xa9, 0xb9, 0x91, 0x1c, 0x82, 0xf5,
253    ///         0x6f, 0xa8, 0xd7, 0x3b, 0x04, 0x95, 0x9d, 0x3d, 0x9d, 0x22, 0x28, 0x95, 0xdf, 0x6c,
254    ///         0x0b, 0x28, 0xaa, 0x15
255    ///     ],
256    ///     DIGEST,
257    /// );
258    /// ```
259    Keccak256,
260    256,
261    PADDING_KECCAK,
262);
263
264sha3!(
265    /// The `KECCAK-384` hash function
266    ///
267    /// # Examples
268    ///
269    /// ```rust
270    /// # use sha3_const::Keccak384;
271    /// const DIGEST: [u8; 48] = Keccak384::new()
272    ///     .update(b"The quick brown fox ")
273    ///     .update(b"jumps over the lazy dog")
274    ///     .finalize();
275    ///
276    /// assert_eq!(
277    ///     [
278    ///         0x28, 0x39, 0x90, 0xfa, 0x9d, 0x5f, 0xb7, 0x31, 0xd7, 0x86, 0xc5, 0xbb, 0xee, 0x94,
279    ///         0xea, 0x4d, 0xb4, 0x91, 0x0f, 0x18, 0xc6, 0x2c, 0x03, 0xd1, 0x73, 0xfc, 0x0a, 0x5e,
280    ///         0x49, 0x44, 0x22, 0xe8, 0xa0, 0xb3, 0xda, 0x75, 0x74, 0xda, 0xe7, 0xfa, 0x0b, 0xaf,
281    ///         0x00, 0x5e, 0x50, 0x40, 0x63, 0xb3
282    ///     ],
283    ///     DIGEST,
284    /// );
285    /// ```
286    Keccak384,
287    384,
288    PADDING_KECCAK,
289);
290
291sha3!(
292    /// The `KECCAK-512` hash function
293    ///
294    /// # Examples
295    ///
296    /// ```rust
297    /// # use sha3_const::Keccak512;
298    /// const DIGEST: [u8; 64] = Keccak512::new()
299    ///     .update(b"The quick brown fox ")
300    ///     .update(b"jumps over the lazy dog")
301    ///     .finalize();
302    ///
303    /// assert_eq!(
304    ///     [
305    ///         0xd1, 0x35, 0xbb, 0x84, 0xd0, 0x43, 0x9d, 0xba, 0xc4, 0x32, 0x24, 0x7e, 0xe5, 0x73,
306    ///         0xa2, 0x3e, 0xa7, 0xd3, 0xc9, 0xde, 0xb2, 0xa9, 0x68, 0xeb, 0x31, 0xd4, 0x7c, 0x4f,
307    ///         0xb4, 0x5f, 0x1e, 0xf4, 0x42, 0x2d, 0x6c, 0x53, 0x1b, 0x5b, 0x9b, 0xd6, 0xf4, 0x49,
308    ///         0xeb, 0xcc, 0x44, 0x9e, 0xa9, 0x4d, 0x0a, 0x8f, 0x05, 0xf6, 0x21, 0x30, 0xfd, 0xa6,
309    ///         0x12, 0xda, 0x53, 0xc7, 0x96, 0x59, 0xf6, 0x09
310    ///     ],
311    ///     DIGEST,
312    /// );
313    /// ```
314    Keccak512,
315    512,
316    PADDING_KECCAK,
317);
318
319macro_rules! shake {
320    (
321        $(#[$doc:meta])* $name:ident,
322        $security:literal,
323    ) => {
324        $(#[$doc])*
325        pub struct $name {
326            state: KeccakState,
327        }
328
329        impl $name {
330            /// Constructs a new hasher
331            pub const fn new() -> $name {
332                $name {
333                    state: KeccakState::new($security, 0x1f),
334                }
335            }
336
337            /// Absorbs additional input
338            ///
339            /// Can be called multiple times.
340            pub const fn update(mut self, input: &[u8]) -> Self {
341                // usee `mut self` instead of `&mut self` because
342                // mutable references are unstable in constants.
343                self.state.update(input);
344                self
345            }
346
347            /// Retrieves an extendable-output function (XOF) reader for current hasher instance
348            pub const fn finalize_xof(&self) -> XofReader {
349                self.state.finalize()
350            }
351
352            /// Finalizes the context and compute the output
353            pub const fn finalize<const N: usize>(&self) -> [u8; N] {
354                let mut reader = self.finalize_xof();
355                let mut output = [0; N];
356                reader.read(&mut output);
357                output
358            }
359        }
360
361        impl Default for $name {
362            fn default() -> Self {
363                $name::new()
364            }
365        }
366    };
367}
368
369shake!(
370    /// The `SHAKE128` extendable-output function
371    ///
372    /// # Examples
373    ///
374    /// ```rust
375    /// # use sha3_const::Shake128;
376    /// const PSEUDO_RANDOM_BYTES: [u8; 32] = Shake128::new()
377    ///     .update(b"The quick brown fox ")
378    ///     .update(b"jumps over the lazy dog")
379    ///     .finalize();
380    ///
381    /// assert_eq!(
382    ///     [
383    ///         0xf4, 0x20, 0x2e, 0x3c, 0x58, 0x52, 0xf9, 0x18, 0x2a, 0x04, 0x30, 0xfd, 0x81, 0x44,
384    ///         0xf0, 0xa7, 0x4b, 0x95, 0xe7, 0x41, 0x7e, 0xca, 0xe1, 0x7d, 0xb0, 0xf8, 0xcf, 0xee,
385    ///         0xd0, 0xe3, 0xe6, 0x6e,
386    ///     ],
387    ///     PSEUDO_RANDOM_BYTES,
388    /// );
389    /// ```
390    ///
391    /// ```rust
392    /// #![feature(const_mut_refs)]
393    /// # use sha3_const::Shake128;
394    /// const ROUND_CONSTANTS_LEN: usize = 16;
395    /// const ROUND_CONSTANTS: [u128; ROUND_CONSTANTS_LEN] = {
396    ///     let shake = Shake128::new()
397    ///         .update(b"The quick brown fox ")
398    ///         .update(b"jumps over the lazy dog");
399    ///     let mut reader = shake.finalize_xof();
400    ///     let mut output = [0; ROUND_CONSTANTS_LEN];
401    ///     let mut i = 0;
402    ///     while i < ROUND_CONSTANTS_LEN {
403    ///         let mut buf = [0; 16];
404    ///         reader.read(&mut buf);
405    ///         output[i] = u128::from_be_bytes(buf);
406    ///         i += 1;
407    ///     }
408    ///     output
409    /// };
410    ///
411    /// assert_eq!(
412    ///     [
413    ///         324498722242859095401832112442782838951,
414    ///         100470442341479765851591908475476895342,
415    ///         241049111671168257801898223573666863059,
416    ///         139197826094415251816510671569090212218,
417    ///         73371475849610774600276735485442220492,
418    ///         321031806373587100556524628628207173306,
419    ///         70553598458795679727810425741185559539,
420    ///         297273966300911440566694043047331846682,
421    ///         112409550095757610585880508546188812219,
422    ///         9460513120811775587939596453044060211,
423    ///         211668019939948365501534576791633315998,
424    ///         50002500201489421996668063727168431450,
425    ///         333627932176661322387974747609682513723,
426    ///         182198809023207418976073231225478277370,
427    ///         318669594573585197479605797034214181928,
428    ///         298412008578376288352503392148066037786,
429    ///     ],
430    ///     ROUND_CONSTANTS,
431    /// );
432    /// ```
433    Shake128,
434    128,
435);
436
437shake!(
438    /// The `SHAKE256` extendable-output function
439    ///
440    /// # Examples
441    ///
442    /// ```rust
443    /// # use sha3_const::Shake256;
444    /// const PSEUDO_RANDOM_BYTES: [u8; 64] = Shake256::new()
445    ///     .update(b"The quick brown fox ")
446    ///     .update(b"jumps over the lazy dog")
447    ///     .finalize();
448    ///
449    /// assert_eq!(
450    ///     [
451    ///         0x2f, 0x67, 0x13, 0x43, 0xd9, 0xb2, 0xe1, 0x60, 0x4d, 0xc9, 0xdc, 0xf0, 0x75, 0x3e,
452    ///         0x5f, 0xe1, 0x5c, 0x7c, 0x64, 0xa0, 0xd2, 0x83, 0xcb, 0xbf, 0x72, 0x2d, 0x41, 0x1a,
453    ///         0x0e, 0x36, 0xf6, 0xca, 0x1d, 0x01, 0xd1, 0x36, 0x9a, 0x23, 0x53, 0x9c, 0xd8, 0x0f,
454    ///         0x7c, 0x05, 0x4b, 0x6e, 0x5d, 0xaf, 0x9c, 0x96, 0x2c, 0xad, 0x5b, 0x8e, 0xd5, 0xbd,
455    ///         0x11, 0x99, 0x8b, 0x40, 0xd5, 0x73, 0x44, 0x42
456    ///     ],
457    ///     PSEUDO_RANDOM_BYTES,
458    /// );
459    /// ```
460    ///
461    /// ```rust
462    /// #![feature(const_mut_refs)]
463    /// # use sha3_const::Shake256;
464    /// const ROUND_CONSTANTS_LEN: usize = 16;
465    /// const ROUND_CONSTANTS: [u128; ROUND_CONSTANTS_LEN] = {
466    ///     let shake = Shake256::new()
467    ///         .update(b"The quick brown fox ")
468    ///         .update(b"jumps over the lazy dog");
469    ///     let mut reader = shake.finalize_xof();
470    ///     let mut output = [0; ROUND_CONSTANTS_LEN];
471    ///     let mut i = 0;
472    ///     while i < ROUND_CONSTANTS_LEN {
473    ///         let mut buf = [0; 16];
474    ///         reader.read(&mut buf);
475    ///         output[i] = u128::from_be_bytes(buf);
476    ///         i += 1;
477    ///     }
478    ///     output
479    /// };
480    ///
481    /// assert_eq!(
482    ///     [
483    ///         63008913119763991345740861509526773729,
484    ///         122934861405288129899227865927808120522,
485    ///         38557047524252432877084375354350394799,
486    ///         208139318032057588670393890858232661058,
487    ///         253672765511221901359815901266029094236,
488    ///         24673942916364082950221119418287074493,
489    ///         314501551299016784988697613270261126631,
490    ///         55846473543301730160082510643706458461,
491    ///         74217159387677683656408416866508597390,
492    ///         103097936643341605695740861737581768184,
493    ///         43427127028232698635034841870476065529,
494    ///         30671809218547569588332151812578484838,
495    ///         234968987069139406291454845949508600001,
496    ///         174416227018858056231916805199588046174,
497    ///         206220167108618043277683992075133751175,
498    ///         50389517484914419772600260972881863524,
499    ///     ],
500    ///     ROUND_CONSTANTS,
501    /// );
502    /// ```
503    Shake256,
504    256,
505);