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);