chksum_hash_sha2_512/
state.rs

1//! Module contains items related to the [`State`] structure which allows to the direct MD5 state manipulation.
2//!
3//! # Example
4//!
5//! ```rust
6//! use chksum_hash_sha2_512 as sha2_512;
7//!
8//! // Create new state
9//! let mut state = sha2_512::state::default();
10//!
11//! // By default it returns initialization values
12//! assert_eq!(
13//!     state.digest(),
14//!     [
15//!         0x6A09E667F3BCC908,
16//!         0xBB67AE8584CAA73B,
17//!         0x3C6EF372FE94F82B,
18//!         0xA54FF53A5F1D36F1,
19//!         0x510E527FADE682D1,
20//!         0x9B05688C2B3E6C1F,
21//!         0x1F83D9ABFB41BD6B,
22//!         0x5BE0CD19137E2179,
23//!     ]
24//! );
25//!
26//! // Manually create block of data with proper padding
27//! let data = [
28//!     u64::from_be_bytes([0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
29//!     u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
30//!     # u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
31//!     # u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
32//!     # u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
33//!     # u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
34//!     # u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
35//!     # u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
36//!     # u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
37//!     # u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
38//!     # u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
39//!     # u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
40//!     # u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
41//!     # u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
42//!     # u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
43//!     // ...
44//!     u64::from_be_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
45//! ];
46//!
47//! // Update state and own new value
48//! state = state.update(data);
49//!
50//! // Proper digest of empty input
51//! assert_eq!(
52//!     state.digest(),
53//!     [
54//!         0xCF83E1357EEFB8BD,
55//!         0xF1542850D66D8007,
56//!         0xD620E4050B5715DC,
57//!         0x83F4A921D36CE9CE,
58//!         0x47D0D13C5D85F2B0,
59//!         0xFF8318D2877EEC2F,
60//!         0x63B931BD47417A81,
61//!         0xA538327AF927DA3E,
62//!     ]
63//! );
64//!
65//! // Reset state to initial values
66//! state = state.reset();
67//! assert_eq!(
68//!     state.digest(),
69//!     [
70//!         0x6A09E667F3BCC908,
71//!         0xBB67AE8584CAA73B,
72//!         0x3C6EF372FE94F82B,
73//!         0xA54FF53A5F1D36F1,
74//!         0x510E527FADE682D1,
75//!         0x9B05688C2B3E6C1F,
76//!         0x1F83D9ABFB41BD6B,
77//!         0x5BE0CD19137E2179,
78//!     ]
79//! );
80//! ```
81//!
82//! # Warning
83//!
84//! The [`State`] structure does not modify internal state, each function returns a new state that must be used.
85
86use crate::block::LENGTH_QWORDS as BLOCK_LENGTH_QWORDS;
87use crate::digest::LENGTH_QWORDS as DIGEST_LENGTH_QWORDS;
88
89#[allow(clippy::unreadable_literal)]
90const H: [u64; 8] = [
91    0x6A09E667F3BCC908,
92    0xBB67AE8584CAA73B,
93    0x3C6EF372FE94F82B,
94    0xA54FF53A5F1D36F1,
95    0x510E527FADE682D1,
96    0x9B05688C2B3E6C1F,
97    0x1F83D9ABFB41BD6B,
98    0x5BE0CD19137E2179,
99];
100
101#[allow(clippy::unreadable_literal)]
102#[rustfmt::skip]
103const K: [u64; 80] = [
104    0x428A2F98D728AE22, 0x7137449123EF65CD, 0xB5C0FBCFEC4D3B2F, 0xE9B5DBA58189DBBC,
105    0x3956C25BF348B538, 0x59F111F1B605D019, 0x923F82A4AF194F9B, 0xAB1C5ED5DA6D8118,
106    0xD807AA98A3030242, 0x12835B0145706FBE, 0x243185BE4EE4B28C, 0x550C7DC3D5FFB4E2,
107    0x72BE5D74F27B896F, 0x80DEB1FE3B1696B1, 0x9BDC06A725C71235, 0xC19BF174CF692694,
108    0xE49B69C19EF14AD2, 0xEFBE4786384F25E3, 0x0FC19DC68B8CD5B5, 0x240CA1CC77AC9C65,
109    0x2DE92C6F592B0275, 0x4A7484AA6EA6E483, 0x5CB0A9DCBD41FBD4, 0x76F988DA831153B5,
110    0x983E5152EE66DFAB, 0xA831C66D2DB43210, 0xB00327C898FB213F, 0xBF597FC7BEEF0EE4,
111    0xC6E00BF33DA88FC2, 0xD5A79147930AA725, 0x06CA6351E003826F, 0x142929670A0E6E70,
112    0x27B70A8546D22FFC, 0x2E1B21385C26C926, 0x4D2C6DFC5AC42AED, 0x53380D139D95B3DF,
113    0x650A73548BAF63DE, 0x766A0ABB3C77B2A8, 0x81C2C92E47EDAEE6, 0x92722C851482353B,
114    0xA2BFE8A14CF10364, 0xA81A664BBC423001, 0xC24B8B70D0F89791, 0xC76C51A30654BE30,
115    0xD192E819D6EF5218, 0xD69906245565A910, 0xF40E35855771202A, 0x106AA07032BBD1B8,
116    0x19A4C116B8D2D0C8, 0x1E376C085141AB53, 0x2748774CDF8EEB99, 0x34B0BCB5E19B48A8,
117    0x391C0CB3C5C95A63, 0x4ED8AA4AE3418ACB, 0x5B9CCA4F7763E373, 0x682E6FF3D6B2B8A3,
118    0x748F82EE5DEFB2FC, 0x78A5636F43172F60, 0x84C87814A1F0AB72, 0x8CC702081A6439EC,
119    0x90BEFFFA23631E28, 0xA4506CEBDE82BDE9, 0xBEF9A3F7B2C67915, 0xC67178F2E372532B,
120    0xCA273ECEEA26619C, 0xD186B8C721C0C207, 0xEADA7DD6CDE0EB1E, 0xF57D4F7FEE6ED178,
121    0x06F067AA72176FBA, 0x0A637DC5A2C898A6, 0x113F9804BEF90DAE, 0x1B710B35131C471B,
122    0x28DB77F523047D84, 0x32CAAB7B40C72493, 0x3C9EBE0A15C9BEBC, 0x431D67C49C100D4C,
123    0x4CC5D4BECB3E42B6, 0x597F299CFC657E2A, 0x5FCB6FAB3AD6FAEC, 0x6C44198C4A475817,
124];
125
126/// Create a new state.
127#[must_use]
128pub const fn new() -> State {
129    State::new()
130}
131
132/// Creates a default state.
133#[must_use]
134pub fn default() -> State {
135    State::default()
136}
137
138/// A low-level hash state.
139///
140/// Check [`state`](self) module for usage examples.
141#[derive(Clone, Copy, Debug, Eq, PartialEq)]
142#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
143pub struct State {
144    pub(crate) a: u64,
145    pub(crate) b: u64,
146    pub(crate) c: u64,
147    pub(crate) d: u64,
148    pub(crate) e: u64,
149    pub(crate) f: u64,
150    pub(crate) g: u64,
151    pub(crate) h: u64,
152}
153
154impl State {
155    /// Creates a new state.
156    #[must_use]
157    pub const fn new() -> Self {
158        let [a, b, c, d, e, f, g, h] = H;
159        Self { a, b, c, d, e, f, g, h }
160    }
161
162    /// Returns modified state with the passed data.
163    ///
164    /// **Warning!** Input block must be in the big-endian byte order.
165    #[must_use]
166    pub const fn update(&self, block: [u64; BLOCK_LENGTH_QWORDS]) -> Self {
167        const fn small_sigma0(x: u64) -> u64 {
168            x.rotate_right(1) ^ x.rotate_right(8) ^ (x >> 7)
169        }
170
171        const fn small_sigma1(x: u64) -> u64 {
172            x.rotate_right(19) ^ x.rotate_right(61) ^ (x >> 6)
173        }
174
175        #[rustfmt::skip]
176        let mut w = [
177            block[0x0], block[0x1], block[0x2], block[0x3],
178            block[0x4], block[0x5], block[0x6], block[0x7],
179            block[0x8], block[0x9], block[0xA], block[0xB],
180            block[0xC], block[0xD], block[0xE], block[0xF],
181                     0,          0,          0,          0,
182                     0,          0,          0,          0,
183                     0,          0,          0,          0,
184                     0,          0,          0,          0,
185                     0,          0,          0,          0,
186                     0,          0,          0,          0,
187                     0,          0,          0,          0,
188                     0,          0,          0,          0,
189                     0,          0,          0,          0,
190                     0,          0,          0,          0,
191                     0,          0,          0,          0,
192                     0,          0,          0,          0,
193                     0,          0,          0,          0,
194                     0,          0,          0,          0,
195                     0,          0,          0,          0,
196                     0,          0,          0,          0,
197        ];
198        w[0x10] = small_sigma1(w[0x0E])
199            .wrapping_add(w[0x09])
200            .wrapping_add(small_sigma0(w[0x01]))
201            .wrapping_add(w[0x00]);
202        w[0x11] = small_sigma1(w[0x0F])
203            .wrapping_add(w[0x0A])
204            .wrapping_add(small_sigma0(w[0x02]))
205            .wrapping_add(w[0x01]);
206        w[0x12] = small_sigma1(w[0x10])
207            .wrapping_add(w[0x0B])
208            .wrapping_add(small_sigma0(w[0x03]))
209            .wrapping_add(w[0x02]);
210        w[0x13] = small_sigma1(w[0x11])
211            .wrapping_add(w[0x0C])
212            .wrapping_add(small_sigma0(w[0x04]))
213            .wrapping_add(w[0x03]);
214        w[0x14] = small_sigma1(w[0x12])
215            .wrapping_add(w[0x0D])
216            .wrapping_add(small_sigma0(w[0x05]))
217            .wrapping_add(w[0x04]);
218        w[0x15] = small_sigma1(w[0x13])
219            .wrapping_add(w[0x0E])
220            .wrapping_add(small_sigma0(w[0x06]))
221            .wrapping_add(w[0x05]);
222        w[0x16] = small_sigma1(w[0x14])
223            .wrapping_add(w[0x0F])
224            .wrapping_add(small_sigma0(w[0x07]))
225            .wrapping_add(w[0x06]);
226        w[0x17] = small_sigma1(w[0x15])
227            .wrapping_add(w[0x10])
228            .wrapping_add(small_sigma0(w[0x08]))
229            .wrapping_add(w[0x07]);
230        w[0x18] = small_sigma1(w[0x16])
231            .wrapping_add(w[0x11])
232            .wrapping_add(small_sigma0(w[0x09]))
233            .wrapping_add(w[0x08]);
234        w[0x19] = small_sigma1(w[0x17])
235            .wrapping_add(w[0x12])
236            .wrapping_add(small_sigma0(w[0x0A]))
237            .wrapping_add(w[0x09]);
238        w[0x1A] = small_sigma1(w[0x18])
239            .wrapping_add(w[0x13])
240            .wrapping_add(small_sigma0(w[0x0B]))
241            .wrapping_add(w[0x0A]);
242        w[0x1B] = small_sigma1(w[0x19])
243            .wrapping_add(w[0x14])
244            .wrapping_add(small_sigma0(w[0x0C]))
245            .wrapping_add(w[0x0B]);
246        w[0x1C] = small_sigma1(w[0x1A])
247            .wrapping_add(w[0x15])
248            .wrapping_add(small_sigma0(w[0x0D]))
249            .wrapping_add(w[0x0C]);
250        w[0x1D] = small_sigma1(w[0x1B])
251            .wrapping_add(w[0x16])
252            .wrapping_add(small_sigma0(w[0x0E]))
253            .wrapping_add(w[0x0D]);
254        w[0x1E] = small_sigma1(w[0x1C])
255            .wrapping_add(w[0x17])
256            .wrapping_add(small_sigma0(w[0x0F]))
257            .wrapping_add(w[0x0E]);
258        w[0x1F] = small_sigma1(w[0x1D])
259            .wrapping_add(w[0x18])
260            .wrapping_add(small_sigma0(w[0x10]))
261            .wrapping_add(w[0x0F]);
262        w[0x20] = small_sigma1(w[0x1E])
263            .wrapping_add(w[0x19])
264            .wrapping_add(small_sigma0(w[0x11]))
265            .wrapping_add(w[0x10]);
266        w[0x21] = small_sigma1(w[0x1F])
267            .wrapping_add(w[0x1A])
268            .wrapping_add(small_sigma0(w[0x12]))
269            .wrapping_add(w[0x11]);
270        w[0x22] = small_sigma1(w[0x20])
271            .wrapping_add(w[0x1B])
272            .wrapping_add(small_sigma0(w[0x13]))
273            .wrapping_add(w[0x12]);
274        w[0x23] = small_sigma1(w[0x21])
275            .wrapping_add(w[0x1C])
276            .wrapping_add(small_sigma0(w[0x14]))
277            .wrapping_add(w[0x13]);
278        w[0x24] = small_sigma1(w[0x22])
279            .wrapping_add(w[0x1D])
280            .wrapping_add(small_sigma0(w[0x15]))
281            .wrapping_add(w[0x14]);
282        w[0x25] = small_sigma1(w[0x23])
283            .wrapping_add(w[0x1E])
284            .wrapping_add(small_sigma0(w[0x16]))
285            .wrapping_add(w[0x15]);
286        w[0x26] = small_sigma1(w[0x24])
287            .wrapping_add(w[0x1F])
288            .wrapping_add(small_sigma0(w[0x17]))
289            .wrapping_add(w[0x16]);
290        w[0x27] = small_sigma1(w[0x25])
291            .wrapping_add(w[0x20])
292            .wrapping_add(small_sigma0(w[0x18]))
293            .wrapping_add(w[0x17]);
294        w[0x28] = small_sigma1(w[0x26])
295            .wrapping_add(w[0x21])
296            .wrapping_add(small_sigma0(w[0x19]))
297            .wrapping_add(w[0x18]);
298        w[0x29] = small_sigma1(w[0x27])
299            .wrapping_add(w[0x22])
300            .wrapping_add(small_sigma0(w[0x1A]))
301            .wrapping_add(w[0x19]);
302        w[0x2A] = small_sigma1(w[0x28])
303            .wrapping_add(w[0x23])
304            .wrapping_add(small_sigma0(w[0x1B]))
305            .wrapping_add(w[0x1A]);
306        w[0x2B] = small_sigma1(w[0x29])
307            .wrapping_add(w[0x24])
308            .wrapping_add(small_sigma0(w[0x1C]))
309            .wrapping_add(w[0x1B]);
310        w[0x2C] = small_sigma1(w[0x2A])
311            .wrapping_add(w[0x25])
312            .wrapping_add(small_sigma0(w[0x1D]))
313            .wrapping_add(w[0x1C]);
314        w[0x2D] = small_sigma1(w[0x2B])
315            .wrapping_add(w[0x26])
316            .wrapping_add(small_sigma0(w[0x1E]))
317            .wrapping_add(w[0x1D]);
318        w[0x2E] = small_sigma1(w[0x2C])
319            .wrapping_add(w[0x27])
320            .wrapping_add(small_sigma0(w[0x1F]))
321            .wrapping_add(w[0x1E]);
322        w[0x2F] = small_sigma1(w[0x2D])
323            .wrapping_add(w[0x28])
324            .wrapping_add(small_sigma0(w[0x20]))
325            .wrapping_add(w[0x1F]);
326        w[0x30] = small_sigma1(w[0x2E])
327            .wrapping_add(w[0x29])
328            .wrapping_add(small_sigma0(w[0x21]))
329            .wrapping_add(w[0x20]);
330        w[0x31] = small_sigma1(w[0x2F])
331            .wrapping_add(w[0x2A])
332            .wrapping_add(small_sigma0(w[0x22]))
333            .wrapping_add(w[0x21]);
334        w[0x32] = small_sigma1(w[0x30])
335            .wrapping_add(w[0x2B])
336            .wrapping_add(small_sigma0(w[0x23]))
337            .wrapping_add(w[0x22]);
338        w[0x33] = small_sigma1(w[0x31])
339            .wrapping_add(w[0x2C])
340            .wrapping_add(small_sigma0(w[0x24]))
341            .wrapping_add(w[0x23]);
342        w[0x34] = small_sigma1(w[0x32])
343            .wrapping_add(w[0x2D])
344            .wrapping_add(small_sigma0(w[0x25]))
345            .wrapping_add(w[0x24]);
346        w[0x35] = small_sigma1(w[0x33])
347            .wrapping_add(w[0x2E])
348            .wrapping_add(small_sigma0(w[0x26]))
349            .wrapping_add(w[0x25]);
350        w[0x36] = small_sigma1(w[0x34])
351            .wrapping_add(w[0x2F])
352            .wrapping_add(small_sigma0(w[0x27]))
353            .wrapping_add(w[0x26]);
354        w[0x37] = small_sigma1(w[0x35])
355            .wrapping_add(w[0x30])
356            .wrapping_add(small_sigma0(w[0x28]))
357            .wrapping_add(w[0x27]);
358        w[0x38] = small_sigma1(w[0x36])
359            .wrapping_add(w[0x31])
360            .wrapping_add(small_sigma0(w[0x29]))
361            .wrapping_add(w[0x28]);
362        w[0x39] = small_sigma1(w[0x37])
363            .wrapping_add(w[0x32])
364            .wrapping_add(small_sigma0(w[0x2A]))
365            .wrapping_add(w[0x29]);
366        w[0x3A] = small_sigma1(w[0x38])
367            .wrapping_add(w[0x33])
368            .wrapping_add(small_sigma0(w[0x2B]))
369            .wrapping_add(w[0x2A]);
370        w[0x3B] = small_sigma1(w[0x39])
371            .wrapping_add(w[0x34])
372            .wrapping_add(small_sigma0(w[0x2C]))
373            .wrapping_add(w[0x2B]);
374        w[0x3C] = small_sigma1(w[0x3A])
375            .wrapping_add(w[0x35])
376            .wrapping_add(small_sigma0(w[0x2D]))
377            .wrapping_add(w[0x2C]);
378        w[0x3D] = small_sigma1(w[0x3B])
379            .wrapping_add(w[0x36])
380            .wrapping_add(small_sigma0(w[0x2E]))
381            .wrapping_add(w[0x2D]);
382        w[0x3E] = small_sigma1(w[0x3C])
383            .wrapping_add(w[0x37])
384            .wrapping_add(small_sigma0(w[0x2F]))
385            .wrapping_add(w[0x2E]);
386        w[0x3F] = small_sigma1(w[0x3D])
387            .wrapping_add(w[0x38])
388            .wrapping_add(small_sigma0(w[0x30]))
389            .wrapping_add(w[0x2F]);
390        w[0x40] = small_sigma1(w[0x3E])
391            .wrapping_add(w[0x39])
392            .wrapping_add(small_sigma0(w[0x31]))
393            .wrapping_add(w[0x30]);
394        w[0x41] = small_sigma1(w[0x3F])
395            .wrapping_add(w[0x3A])
396            .wrapping_add(small_sigma0(w[0x32]))
397            .wrapping_add(w[0x31]);
398        w[0x42] = small_sigma1(w[0x40])
399            .wrapping_add(w[0x3B])
400            .wrapping_add(small_sigma0(w[0x33]))
401            .wrapping_add(w[0x32]);
402        w[0x43] = small_sigma1(w[0x41])
403            .wrapping_add(w[0x3C])
404            .wrapping_add(small_sigma0(w[0x34]))
405            .wrapping_add(w[0x33]);
406        w[0x44] = small_sigma1(w[0x42])
407            .wrapping_add(w[0x3D])
408            .wrapping_add(small_sigma0(w[0x35]))
409            .wrapping_add(w[0x34]);
410        w[0x45] = small_sigma1(w[0x43])
411            .wrapping_add(w[0x3E])
412            .wrapping_add(small_sigma0(w[0x36]))
413            .wrapping_add(w[0x35]);
414        w[0x46] = small_sigma1(w[0x44])
415            .wrapping_add(w[0x3F])
416            .wrapping_add(small_sigma0(w[0x37]))
417            .wrapping_add(w[0x36]);
418        w[0x47] = small_sigma1(w[0x45])
419            .wrapping_add(w[0x40])
420            .wrapping_add(small_sigma0(w[0x38]))
421            .wrapping_add(w[0x37]);
422        w[0x48] = small_sigma1(w[0x46])
423            .wrapping_add(w[0x41])
424            .wrapping_add(small_sigma0(w[0x39]))
425            .wrapping_add(w[0x38]);
426        w[0x49] = small_sigma1(w[0x47])
427            .wrapping_add(w[0x42])
428            .wrapping_add(small_sigma0(w[0x3A]))
429            .wrapping_add(w[0x39]);
430        w[0x4A] = small_sigma1(w[0x48])
431            .wrapping_add(w[0x43])
432            .wrapping_add(small_sigma0(w[0x3B]))
433            .wrapping_add(w[0x3A]);
434        w[0x4B] = small_sigma1(w[0x49])
435            .wrapping_add(w[0x44])
436            .wrapping_add(small_sigma0(w[0x3C]))
437            .wrapping_add(w[0x3B]);
438        w[0x4C] = small_sigma1(w[0x4A])
439            .wrapping_add(w[0x45])
440            .wrapping_add(small_sigma0(w[0x3D]))
441            .wrapping_add(w[0x3C]);
442        w[0x4D] = small_sigma1(w[0x4B])
443            .wrapping_add(w[0x46])
444            .wrapping_add(small_sigma0(w[0x3E]))
445            .wrapping_add(w[0x3D]);
446        w[0x4E] = small_sigma1(w[0x4C])
447            .wrapping_add(w[0x47])
448            .wrapping_add(small_sigma0(w[0x3F]))
449            .wrapping_add(w[0x3E]);
450        w[0x4F] = small_sigma1(w[0x4D])
451            .wrapping_add(w[0x48])
452            .wrapping_add(small_sigma0(w[0x40]))
453            .wrapping_add(w[0x3F]);
454
455        let state = *self;
456
457        const fn ch(x: u64, y: u64, z: u64) -> u64 {
458            (x & y) ^ (!x & z)
459        }
460
461        const fn maj(x: u64, y: u64, z: u64) -> u64 {
462            (x & y) ^ (x & z) ^ (y & z)
463        }
464
465        const fn capital_sigma0(x: u64) -> u64 {
466            x.rotate_right(28) ^ x.rotate_right(34) ^ x.rotate_right(39)
467        }
468
469        const fn capital_sigma1(x: u64) -> u64 {
470            x.rotate_right(14) ^ x.rotate_right(18) ^ x.rotate_right(41)
471        }
472
473        #[allow(clippy::too_many_arguments)]
474        #[rustfmt::skip]
475        const fn round(State { a, b, c, d, e, f, g, h }: State, w: u64, k: u64) -> State {
476            let t1 = h.wrapping_add(capital_sigma1(e)).wrapping_add(ch(e, f, g)).wrapping_add(k).wrapping_add(w);
477            let t2 = capital_sigma0(a).wrapping_add(maj(a, b, c));
478            let h = g;
479            let g = f;
480            let f = e;
481            let e = d.wrapping_add(t1);
482            let d = c;
483            let c = b;
484            let b = a;
485            let a = t1.wrapping_add(t2);
486            State { a, b, c, d, e, f, g, h }
487        }
488
489        let state = round(state, w[0x00], K[0x00]);
490        let state = round(state, w[0x01], K[0x01]);
491        let state = round(state, w[0x02], K[0x02]);
492        let state = round(state, w[0x03], K[0x03]);
493        let state = round(state, w[0x04], K[0x04]);
494        let state = round(state, w[0x05], K[0x05]);
495        let state = round(state, w[0x06], K[0x06]);
496        let state = round(state, w[0x07], K[0x07]);
497        let state = round(state, w[0x08], K[0x08]);
498        let state = round(state, w[0x09], K[0x09]);
499        let state = round(state, w[0x0A], K[0x0A]);
500        let state = round(state, w[0x0B], K[0x0B]);
501        let state = round(state, w[0x0C], K[0x0C]);
502        let state = round(state, w[0x0D], K[0x0D]);
503        let state = round(state, w[0x0E], K[0x0E]);
504        let state = round(state, w[0x0F], K[0x0F]);
505        let state = round(state, w[0x10], K[0x10]);
506        let state = round(state, w[0x11], K[0x11]);
507        let state = round(state, w[0x12], K[0x12]);
508        let state = round(state, w[0x13], K[0x13]);
509        let state = round(state, w[0x14], K[0x14]);
510        let state = round(state, w[0x15], K[0x15]);
511        let state = round(state, w[0x16], K[0x16]);
512        let state = round(state, w[0x17], K[0x17]);
513        let state = round(state, w[0x18], K[0x18]);
514        let state = round(state, w[0x19], K[0x19]);
515        let state = round(state, w[0x1A], K[0x1A]);
516        let state = round(state, w[0x1B], K[0x1B]);
517        let state = round(state, w[0x1C], K[0x1C]);
518        let state = round(state, w[0x1D], K[0x1D]);
519        let state = round(state, w[0x1E], K[0x1E]);
520        let state = round(state, w[0x1F], K[0x1F]);
521        let state = round(state, w[0x20], K[0x20]);
522        let state = round(state, w[0x21], K[0x21]);
523        let state = round(state, w[0x22], K[0x22]);
524        let state = round(state, w[0x23], K[0x23]);
525        let state = round(state, w[0x24], K[0x24]);
526        let state = round(state, w[0x25], K[0x25]);
527        let state = round(state, w[0x26], K[0x26]);
528        let state = round(state, w[0x27], K[0x27]);
529        let state = round(state, w[0x28], K[0x28]);
530        let state = round(state, w[0x29], K[0x29]);
531        let state = round(state, w[0x2A], K[0x2A]);
532        let state = round(state, w[0x2B], K[0x2B]);
533        let state = round(state, w[0x2C], K[0x2C]);
534        let state = round(state, w[0x2D], K[0x2D]);
535        let state = round(state, w[0x2E], K[0x2E]);
536        let state = round(state, w[0x2F], K[0x2F]);
537        let state = round(state, w[0x30], K[0x30]);
538        let state = round(state, w[0x31], K[0x31]);
539        let state = round(state, w[0x32], K[0x32]);
540        let state = round(state, w[0x33], K[0x33]);
541        let state = round(state, w[0x34], K[0x34]);
542        let state = round(state, w[0x35], K[0x35]);
543        let state = round(state, w[0x36], K[0x36]);
544        let state = round(state, w[0x37], K[0x37]);
545        let state = round(state, w[0x38], K[0x38]);
546        let state = round(state, w[0x39], K[0x39]);
547        let state = round(state, w[0x3A], K[0x3A]);
548        let state = round(state, w[0x3B], K[0x3B]);
549        let state = round(state, w[0x3C], K[0x3C]);
550        let state = round(state, w[0x3D], K[0x3D]);
551        let state = round(state, w[0x3E], K[0x3E]);
552        let state = round(state, w[0x3F], K[0x3F]);
553        let state = round(state, w[0x40], K[0x40]);
554        let state = round(state, w[0x41], K[0x41]);
555        let state = round(state, w[0x42], K[0x42]);
556        let state = round(state, w[0x43], K[0x43]);
557        let state = round(state, w[0x44], K[0x44]);
558        let state = round(state, w[0x45], K[0x45]);
559        let state = round(state, w[0x46], K[0x46]);
560        let state = round(state, w[0x47], K[0x47]);
561        let state = round(state, w[0x48], K[0x48]);
562        let state = round(state, w[0x49], K[0x49]);
563        let state = round(state, w[0x4A], K[0x4A]);
564        let state = round(state, w[0x4B], K[0x4B]);
565        let state = round(state, w[0x4C], K[0x4C]);
566        let state = round(state, w[0x4D], K[0x4D]);
567        let state = round(state, w[0x4E], K[0x4E]);
568        let state = round(state, w[0x4F], K[0x4F]);
569
570        // Update
571
572        let Self { a, b, c, d, e, f, g, h } = state;
573
574        let a = a.wrapping_add(self.a);
575        let b = b.wrapping_add(self.b);
576        let c = c.wrapping_add(self.c);
577        let d = d.wrapping_add(self.d);
578        let e = e.wrapping_add(self.e);
579        let f = f.wrapping_add(self.f);
580        let g = g.wrapping_add(self.g);
581        let h = h.wrapping_add(self.h);
582
583        // Return
584
585        Self { a, b, c, d, e, f, g, h }
586    }
587
588    /// Returns a new state with initial values.
589    #[must_use]
590    pub const fn reset(self) -> Self {
591        let [a, b, c, d, e, f, g, h] = H;
592        Self { a, b, c, d, e, f, g, h }
593    }
594
595    /// Returns a digest.
596    #[must_use]
597    pub const fn digest(&self) -> [u64; DIGEST_LENGTH_QWORDS] {
598        let Self { a, b, c, d, e, f, g, h } = *self;
599        [a, b, c, d, e, f, g, h]
600    }
601}
602
603impl Default for State {
604    fn default() -> Self {
605        Self::new()
606    }
607}
608
609#[cfg(test)]
610mod tests {
611    use super::*;
612
613    #[test]
614    fn new_empty() {
615        let digest = new().digest();
616        assert_eq!(
617            digest,
618            [
619                0x6A09E667F3BCC908,
620                0xBB67AE8584CAA73B,
621                0x3C6EF372FE94F82B,
622                0xA54FF53A5F1D36F1,
623                0x510E527FADE682D1,
624                0x9B05688C2B3E6C1F,
625                0x1F83D9ABFB41BD6B,
626                0x5BE0CD19137E2179,
627            ]
628        );
629    }
630
631    #[test]
632    fn default_empty() {
633        let digest = default().digest();
634        assert_eq!(
635            digest,
636            [
637                0x6A09E667F3BCC908,
638                0xBB67AE8584CAA73B,
639                0x3C6EF372FE94F82B,
640                0xA54FF53A5F1D36F1,
641                0x510E527FADE682D1,
642                0x9B05688C2B3E6C1F,
643                0x1F83D9ABFB41BD6B,
644                0x5BE0CD19137E2179,
645            ]
646        );
647    }
648
649    #[test]
650    fn new_zeros() {
651        #[rustfmt::skip]
652        let block = [
653            0x8000000000000000,
654            0x0000000000000000,
655            0x0000000000000000,
656            0x0000000000000000,
657            0x0000000000000000,
658            0x0000000000000000,
659            0x0000000000000000,
660            0x0000000000000000,
661            0x0000000000000000,
662            0x0000000000000000,
663            0x0000000000000000,
664            0x0000000000000000,
665            0x0000000000000000,
666            0x0000000000000000,
667            0x0000000000000000,
668            0x0000000000000000,
669        ];
670        let digest = new().update(block).digest();
671        assert_eq!(
672            digest,
673            [
674                0xCF83E1357EEFB8BD,
675                0xF1542850D66D8007,
676                0xD620E4050B5715DC,
677                0x83F4A921D36CE9CE,
678                0x47D0D13C5D85F2B0,
679                0xFF8318D2877EEC2F,
680                0x63B931BD47417A81,
681                0xA538327AF927DA3E,
682            ]
683        );
684    }
685}