1#[cfg(all(feature = "std", target_arch = "x86"))]
6use core::arch::x86::*;
7#[cfg(all(feature = "std", target_arch = "x86_64"))]
8use core::arch::x86_64::*;
9use core::ops::Index;
10use core::slice::SliceIndex;
11use core::str;
12
13use crate::{FromSliceError, HashEngine};
14
15crate::internal_macros::hash_type! {
16 256,
17 "Output of the SHA-256 hash function."
18}
19
20pub const BLOCK_SIZE: usize = 64;
22
23#[derive(Clone)]
25pub struct Engine {
26 buffer: [u8; BLOCK_SIZE],
27 h: [u32; 8],
28 length: usize,
29}
30
31impl Default for Engine {
32 fn default() -> Self {
33 Engine {
34 h: [
35 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
36 0x5be0cd19,
37 ],
38 length: 0,
39 buffer: [0; BLOCK_SIZE],
40 }
41 }
42}
43
44impl HashEngine for Engine {
45 type Digest = [u8; 32];
46 type Midstate = Midstate;
47 const BLOCK_SIZE: usize = BLOCK_SIZE;
48
49 #[inline]
50 fn n_bytes_hashed(&self) -> usize { self.length }
51
52 crate::internal_macros::engine_input_impl!(32);
53
54 #[cfg(not(hashes_fuzz))]
55 #[inline]
56 fn finalize(mut self) -> Self::Digest {
57 let data_len = self.length as u64;
59
60 let zeroes = [0; BLOCK_SIZE - 8];
61 self.input(&[0x80]);
62 if self.length % BLOCK_SIZE > zeroes.len() {
63 self.input(&zeroes);
64 }
65 let pad_length = zeroes.len() - (self.length % BLOCK_SIZE);
66 self.input(&zeroes[..pad_length]);
67 debug_assert_eq!(self.length % BLOCK_SIZE, zeroes.len());
68
69 self.input(&(8 * data_len).to_be_bytes());
70 debug_assert_eq!(self.length % BLOCK_SIZE, 0);
71
72 self.midstate().to_byte_array()
73 }
74
75 #[cfg(hashes_fuzz)]
76 fn finalize(mut self) -> Self::Digest {
77 let mut hash = e.midstate().to_byte_array();
78 if hash == [0; 32] {
79 hash[0] = 1;
82 }
83 hash
84 }
85
86 #[cfg(not(hashes_fuzz))]
87 #[inline]
88 fn midstate(&self) -> Midstate {
89 let mut ret = [0; 32];
90 for (val, ret_bytes) in self.h.iter().zip(ret.chunks_exact_mut(4)) {
91 ret_bytes.copy_from_slice(&val.to_be_bytes());
92 }
93 Midstate(ret)
94 }
95
96 #[cfg(hashes_fuzz)]
97 fn midstate(&self) -> Midstate {
98 let mut ret = [0; 32];
99 ret.copy_from_slice(&self.buffer[..32]);
100 Midstate(ret)
101 }
102
103 #[inline]
104 fn from_midstate(midstate: Midstate, length: usize) -> Engine {
105 assert!(length % BLOCK_SIZE == 0, "length is no multiple of the block size");
106
107 let mut ret = [0; 8];
108 for (ret_val, midstate_bytes) in ret.iter_mut().zip(midstate[..].chunks_exact(4)) {
109 *ret_val = u32::from_be_bytes(midstate_bytes.try_into().expect("4 byte slice"));
110 }
111
112 Engine { buffer: [0; BLOCK_SIZE], h: ret, length }
113 }
114}
115
116impl Hash {
117 pub const fn const_hash(bytes: &[u8]) -> Self { Hash(Midstate::const_hash(bytes, true).0) }
121}
122
123#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
125pub struct Midstate(pub [u8; 32]);
126
127crate::internal_macros::arr_newtype_fmt_impl!(Midstate, 32);
128serde_impl!(Midstate, 32);
129crate::internal_macros::as_ref_impl!(Midstate);
130
131impl<I: SliceIndex<[u8]>> Index<I> for Midstate {
132 type Output = I::Output;
133
134 #[inline]
135 fn index(&self, index: I) -> &Self::Output { &self.0[index] }
136}
137
138impl str::FromStr for Midstate {
139 type Err = hex::HexToArrayError;
140 fn from_str(s: &str) -> Result<Self, Self::Err> { hex::FromHex::from_hex(s) }
141}
142
143impl Midstate {
144 const LEN: usize = 32;
146
147 pub const fn from_byte_array(inner: [u8; 32]) -> Self { Midstate(inner) }
149
150 pub fn from_slice(sl: &[u8]) -> Result<Midstate, FromSliceError> {
152 if sl.len() != Self::LEN {
153 Err(FromSliceError { expected: Self::LEN, got: sl.len() })
154 } else {
155 let mut ret = [0; 32];
156 ret.copy_from_slice(sl);
157 Ok(Midstate(ret))
158 }
159 }
160
161 pub fn to_byte_array(self) -> [u8; 32] { self.0 }
163
164 pub const fn hash_tag(tag: &[u8]) -> Self {
170 let hash = Hash::const_hash(tag);
171 let mut buf = [0u8; 64];
172 let mut i = 0usize;
173 while i < buf.len() {
174 buf[i] = hash.0[i % hash.0.len()];
175 i += 1;
176 }
177 Self::const_hash(&buf, false)
178 }
179}
180
181impl hex::FromHex for Midstate {
182 type Error = hex::HexToArrayError;
183
184 fn from_hex(s: &str) -> Result<Self, Self::Error> {
185 let bytes = <[u8; 32]>::from_hex(s)?;
186 Ok(Midstate(bytes))
187 }
188}
189
190#[allow(non_snake_case)]
191const fn Ch(x: u32, y: u32, z: u32) -> u32 { z ^ (x & (y ^ z)) }
192#[allow(non_snake_case)]
193const fn Maj(x: u32, y: u32, z: u32) -> u32 { (x & y) | (z & (x | y)) }
194#[allow(non_snake_case)]
195const fn Sigma0(x: u32) -> u32 { x.rotate_left(30) ^ x.rotate_left(19) ^ x.rotate_left(10) }
196#[allow(non_snake_case)]
197const fn Sigma1(x: u32) -> u32 { x.rotate_left(26) ^ x.rotate_left(21) ^ x.rotate_left(7) }
198const fn sigma0(x: u32) -> u32 { x.rotate_left(25) ^ x.rotate_left(14) ^ (x >> 3) }
199const fn sigma1(x: u32) -> u32 { x.rotate_left(15) ^ x.rotate_left(13) ^ (x >> 10) }
200
201#[cfg(feature = "small-hash")]
202#[macro_use]
203mod small_hash {
204 use super::*;
205
206 #[rustfmt::skip]
207 pub(super) const fn round(a: u32, b: u32, c: u32, d: u32, e: u32,
208 f: u32, g: u32, h: u32, k: u32, w: u32) -> (u32, u32) {
209 let t1 =
210 h.wrapping_add(Sigma1(e)).wrapping_add(Ch(e, f, g)).wrapping_add(k).wrapping_add(w);
211 let t2 = Sigma0(a).wrapping_add(Maj(a, b, c));
212 (d.wrapping_add(t1), t1.wrapping_add(t2))
213 }
214 #[rustfmt::skip]
215 pub(super) const fn later_round(a: u32, b: u32, c: u32, d: u32, e: u32,
216 f: u32, g: u32, h: u32, k: u32, w: u32,
217 w1: u32, w2: u32, w3: u32,
218 ) -> (u32, u32, u32) {
219 let w = w.wrapping_add(sigma1(w1)).wrapping_add(w2).wrapping_add(sigma0(w3));
220 let (d, h) = round(a, b, c, d, e, f, g, h, k, w);
221 (d, h, w)
222 }
223
224 macro_rules! round(
225 ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr) => (
227 let updates = small_hash::round($a, $b, $c, $d, $e, $f, $g, $h, $k, $w);
228 $d = updates.0;
229 $h = updates.1;
230 );
231 ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr, $w1:expr, $w2:expr, $w3:expr) => (
233 let updates = small_hash::later_round($a, $b, $c, $d, $e, $f, $g, $h, $k, $w, $w1, $w2, $w3);
234 $d = updates.0;
235 $h = updates.1;
236 $w = updates.2;
237 )
238 );
239}
240
241#[cfg(not(feature = "small-hash"))]
242#[macro_use]
243mod fast_hash {
244 macro_rules! round(
245 ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr) => (
247 let t1 = $h.wrapping_add(Sigma1($e)).wrapping_add(Ch($e, $f, $g)).wrapping_add($k).wrapping_add($w);
248 let t2 = Sigma0($a).wrapping_add(Maj($a, $b, $c));
249 $d = $d.wrapping_add(t1);
250 $h = t1.wrapping_add(t2);
251 );
252 ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr, $w1:expr, $w2:expr, $w3:expr) => (
254 $w = $w.wrapping_add(sigma1($w1)).wrapping_add($w2).wrapping_add(sigma0($w3));
255 round!($a, $b, $c, $d, $e, $f, $g, $h, $k, $w);
256 )
257 );
258}
259
260impl Midstate {
261 #[allow(clippy::identity_op)] const fn read_u32(bytes: &[u8], index: usize) -> u32 {
263 ((bytes[index + 0] as u32) << 24)
264 | ((bytes[index + 1] as u32) << 16)
265 | ((bytes[index + 2] as u32) << 8)
266 | ((bytes[index + 3] as u32) << 0)
267 }
268
269 const fn copy_w(bytes: &[u8], index: usize) -> [u32; 16] {
270 let mut w = [0u32; 16];
271 let mut i = 0;
272 while i < 16 {
273 w[i] = Self::read_u32(bytes, index + i * 4);
274 i += 1;
275 }
276 w
277 }
278
279 const fn const_hash(bytes: &[u8], finalize: bool) -> Self {
280 let mut state = [
281 0x6a09e667u32,
282 0xbb67ae85,
283 0x3c6ef372,
284 0xa54ff53a,
285 0x510e527f,
286 0x9b05688c,
287 0x1f83d9ab,
288 0x5be0cd19,
289 ];
290
291 let num_chunks = (bytes.len() + 9 + 63) / 64;
292 let mut chunk = 0;
293 #[allow(clippy::precedence)]
294 while chunk < num_chunks {
295 if !finalize && chunk + 1 == num_chunks {
296 break;
297 }
298 let mut w = if chunk * 64 + 64 <= bytes.len() {
299 Self::copy_w(bytes, chunk * 64)
300 } else {
301 let mut buf = [0; 64];
302 let mut i = 0;
303 let offset = chunk * 64;
304 while offset + i < bytes.len() {
305 buf[i] = bytes[offset + i];
306 i += 1;
307 }
308 if (bytes.len() % 64 <= 64 - 9) || (chunk + 2 == num_chunks) {
309 buf[i] = 0x80;
310 }
311 #[allow(clippy::identity_op)] #[allow(clippy::erasing_op)]
313 if chunk + 1 == num_chunks {
314 let bit_len = bytes.len() as u64 * 8;
315 buf[64 - 8] = ((bit_len >> 8 * 7) & 0xFF) as u8;
316 buf[64 - 7] = ((bit_len >> 8 * 6) & 0xFF) as u8;
317 buf[64 - 6] = ((bit_len >> 8 * 5) & 0xFF) as u8;
318 buf[64 - 5] = ((bit_len >> 8 * 4) & 0xFF) as u8;
319 buf[64 - 4] = ((bit_len >> 8 * 3) & 0xFF) as u8;
320 buf[64 - 3] = ((bit_len >> 8 * 2) & 0xFF) as u8;
321 buf[64 - 2] = ((bit_len >> 8 * 1) & 0xFF) as u8;
322 buf[64 - 1] = ((bit_len >> 8 * 0) & 0xFF) as u8;
323 }
324 Self::copy_w(&buf, 0)
325 };
326 chunk += 1;
327
328 let mut a = state[0];
329 let mut b = state[1];
330 let mut c = state[2];
331 let mut d = state[3];
332 let mut e = state[4];
333 let mut f = state[5];
334 let mut g = state[6];
335 let mut h = state[7];
336
337 round!(a, b, c, d, e, f, g, h, 0x428a2f98, w[0]);
338 round!(h, a, b, c, d, e, f, g, 0x71374491, w[1]);
339 round!(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w[2]);
340 round!(f, g, h, a, b, c, d, e, 0xe9b5dba5, w[3]);
341 round!(e, f, g, h, a, b, c, d, 0x3956c25b, w[4]);
342 round!(d, e, f, g, h, a, b, c, 0x59f111f1, w[5]);
343 round!(c, d, e, f, g, h, a, b, 0x923f82a4, w[6]);
344 round!(b, c, d, e, f, g, h, a, 0xab1c5ed5, w[7]);
345 round!(a, b, c, d, e, f, g, h, 0xd807aa98, w[8]);
346 round!(h, a, b, c, d, e, f, g, 0x12835b01, w[9]);
347 round!(g, h, a, b, c, d, e, f, 0x243185be, w[10]);
348 round!(f, g, h, a, b, c, d, e, 0x550c7dc3, w[11]);
349 round!(e, f, g, h, a, b, c, d, 0x72be5d74, w[12]);
350 round!(d, e, f, g, h, a, b, c, 0x80deb1fe, w[13]);
351 round!(c, d, e, f, g, h, a, b, 0x9bdc06a7, w[14]);
352 round!(b, c, d, e, f, g, h, a, 0xc19bf174, w[15]);
353
354 round!(a, b, c, d, e, f, g, h, 0xe49b69c1, w[0], w[14], w[9], w[1]);
355 round!(h, a, b, c, d, e, f, g, 0xefbe4786, w[1], w[15], w[10], w[2]);
356 round!(g, h, a, b, c, d, e, f, 0x0fc19dc6, w[2], w[0], w[11], w[3]);
357 round!(f, g, h, a, b, c, d, e, 0x240ca1cc, w[3], w[1], w[12], w[4]);
358 round!(e, f, g, h, a, b, c, d, 0x2de92c6f, w[4], w[2], w[13], w[5]);
359 round!(d, e, f, g, h, a, b, c, 0x4a7484aa, w[5], w[3], w[14], w[6]);
360 round!(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w[6], w[4], w[15], w[7]);
361 round!(b, c, d, e, f, g, h, a, 0x76f988da, w[7], w[5], w[0], w[8]);
362 round!(a, b, c, d, e, f, g, h, 0x983e5152, w[8], w[6], w[1], w[9]);
363 round!(h, a, b, c, d, e, f, g, 0xa831c66d, w[9], w[7], w[2], w[10]);
364 round!(g, h, a, b, c, d, e, f, 0xb00327c8, w[10], w[8], w[3], w[11]);
365 round!(f, g, h, a, b, c, d, e, 0xbf597fc7, w[11], w[9], w[4], w[12]);
366 round!(e, f, g, h, a, b, c, d, 0xc6e00bf3, w[12], w[10], w[5], w[13]);
367 round!(d, e, f, g, h, a, b, c, 0xd5a79147, w[13], w[11], w[6], w[14]);
368 round!(c, d, e, f, g, h, a, b, 0x06ca6351, w[14], w[12], w[7], w[15]);
369 round!(b, c, d, e, f, g, h, a, 0x14292967, w[15], w[13], w[8], w[0]);
370
371 round!(a, b, c, d, e, f, g, h, 0x27b70a85, w[0], w[14], w[9], w[1]);
372 round!(h, a, b, c, d, e, f, g, 0x2e1b2138, w[1], w[15], w[10], w[2]);
373 round!(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w[2], w[0], w[11], w[3]);
374 round!(f, g, h, a, b, c, d, e, 0x53380d13, w[3], w[1], w[12], w[4]);
375 round!(e, f, g, h, a, b, c, d, 0x650a7354, w[4], w[2], w[13], w[5]);
376 round!(d, e, f, g, h, a, b, c, 0x766a0abb, w[5], w[3], w[14], w[6]);
377 round!(c, d, e, f, g, h, a, b, 0x81c2c92e, w[6], w[4], w[15], w[7]);
378 round!(b, c, d, e, f, g, h, a, 0x92722c85, w[7], w[5], w[0], w[8]);
379 round!(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w[8], w[6], w[1], w[9]);
380 round!(h, a, b, c, d, e, f, g, 0xa81a664b, w[9], w[7], w[2], w[10]);
381 round!(g, h, a, b, c, d, e, f, 0xc24b8b70, w[10], w[8], w[3], w[11]);
382 round!(f, g, h, a, b, c, d, e, 0xc76c51a3, w[11], w[9], w[4], w[12]);
383 round!(e, f, g, h, a, b, c, d, 0xd192e819, w[12], w[10], w[5], w[13]);
384 round!(d, e, f, g, h, a, b, c, 0xd6990624, w[13], w[11], w[6], w[14]);
385 round!(c, d, e, f, g, h, a, b, 0xf40e3585, w[14], w[12], w[7], w[15]);
386 round!(b, c, d, e, f, g, h, a, 0x106aa070, w[15], w[13], w[8], w[0]);
387
388 round!(a, b, c, d, e, f, g, h, 0x19a4c116, w[0], w[14], w[9], w[1]);
389 round!(h, a, b, c, d, e, f, g, 0x1e376c08, w[1], w[15], w[10], w[2]);
390 round!(g, h, a, b, c, d, e, f, 0x2748774c, w[2], w[0], w[11], w[3]);
391 round!(f, g, h, a, b, c, d, e, 0x34b0bcb5, w[3], w[1], w[12], w[4]);
392 round!(e, f, g, h, a, b, c, d, 0x391c0cb3, w[4], w[2], w[13], w[5]);
393 round!(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w[5], w[3], w[14], w[6]);
394 round!(c, d, e, f, g, h, a, b, 0x5b9cca4f, w[6], w[4], w[15], w[7]);
395 round!(b, c, d, e, f, g, h, a, 0x682e6ff3, w[7], w[5], w[0], w[8]);
396 round!(a, b, c, d, e, f, g, h, 0x748f82ee, w[8], w[6], w[1], w[9]);
397 round!(h, a, b, c, d, e, f, g, 0x78a5636f, w[9], w[7], w[2], w[10]);
398 round!(g, h, a, b, c, d, e, f, 0x84c87814, w[10], w[8], w[3], w[11]);
399 round!(f, g, h, a, b, c, d, e, 0x8cc70208, w[11], w[9], w[4], w[12]);
400 round!(e, f, g, h, a, b, c, d, 0x90befffa, w[12], w[10], w[5], w[13]);
401 round!(d, e, f, g, h, a, b, c, 0xa4506ceb, w[13], w[11], w[6], w[14]);
402 round!(c, d, e, f, g, h, a, b, 0xbef9a3f7, w[14], w[12], w[7], w[15]);
403 round!(b, c, d, e, f, g, h, a, 0xc67178f2, w[15], w[13], w[8], w[0]);
404
405 state[0] = state[0].wrapping_add(a);
406 state[1] = state[1].wrapping_add(b);
407 state[2] = state[2].wrapping_add(c);
408 state[3] = state[3].wrapping_add(d);
409 state[4] = state[4].wrapping_add(e);
410 state[5] = state[5].wrapping_add(f);
411 state[6] = state[6].wrapping_add(g);
412 state[7] = state[7].wrapping_add(h);
413 }
414 let mut output = [0u8; 32];
415 let mut i = 0;
416 #[allow(clippy::identity_op)] while i < 8 {
418 output[i * 4 + 0] = (state[i + 0] >> 24) as u8;
419 output[i * 4 + 1] = (state[i + 0] >> 16) as u8;
420 output[i * 4 + 2] = (state[i + 0] >> 8) as u8;
421 output[i * 4 + 3] = (state[i + 0] >> 0) as u8;
422 i += 1;
423 }
424 Midstate(output)
425 }
426}
427
428impl Engine {
429 pub fn from_midstate(midstate: Midstate, length: usize) -> Engine {
435 assert!(length % BLOCK_SIZE == 0, "length is no multiple of the block size");
436
437 let mut ret = [0; 8];
438 for (ret_val, midstate_bytes) in ret.iter_mut().zip(midstate[..].chunks_exact(4)) {
439 *ret_val = u32::from_be_bytes(midstate_bytes.try_into().expect("4 byte slice"));
440 }
441
442 Engine { buffer: [0; BLOCK_SIZE], h: ret, length }
443 }
444
445 fn process_block(&mut self) {
446 #[cfg(all(feature = "std", any(target_arch = "x86", target_arch = "x86_64")))]
447 {
448 if is_x86_feature_detected!("sse4.1")
449 && is_x86_feature_detected!("sha")
450 && is_x86_feature_detected!("sse2")
451 && is_x86_feature_detected!("ssse3")
452 {
453 return unsafe { self.process_block_simd_x86_intrinsics() };
454 }
455 }
456
457 self.software_process_block()
459 }
460
461 #[cfg(all(feature = "std", any(target_arch = "x86", target_arch = "x86_64")))]
462 #[target_feature(enable = "sha,sse2,ssse3,sse4.1")]
463 unsafe fn process_block_simd_x86_intrinsics(&mut self) {
464 let (mut state0, mut state1);
474 let (mut msg, mut tmp);
475
476 let (mut msg0, mut msg1, mut msg2, mut msg3);
477
478 let (abef_save, cdgh_save);
479
480 #[allow(non_snake_case)]
481 let MASK: __m128i =
482 _mm_set_epi64x(0x0c0d_0e0f_0809_0a0bu64 as i64, 0x0405_0607_0001_0203u64 as i64);
483
484 let block_offset = 0;
485
486 tmp = _mm_loadu_si128(self.h.as_ptr().add(0) as *const __m128i);
490 state1 = _mm_loadu_si128(self.h.as_ptr().add(4) as *const __m128i);
491
492 tmp = _mm_shuffle_epi32(tmp, 0xB1); state1 = _mm_shuffle_epi32(state1, 0x1B); state0 = _mm_alignr_epi8(tmp, state1, 8); state1 = _mm_blend_epi16(state1, tmp, 0xF0); {
499 abef_save = state0;
501 cdgh_save = state1;
502
503 msg = _mm_loadu_si128(self.buffer.as_ptr().add(block_offset) as *const __m128i);
505 msg0 = _mm_shuffle_epi8(msg, MASK);
506 msg = _mm_add_epi32(
507 msg0,
508 _mm_set_epi64x(0xE9B5DBA5B5C0FBCFu64 as i64, 0x71374491428A2F98u64 as i64),
509 );
510 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
511 msg = _mm_shuffle_epi32(msg, 0x0E);
512 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
513
514 msg1 = _mm_loadu_si128(self.buffer.as_ptr().add(block_offset + 16) as *const __m128i);
516 msg1 = _mm_shuffle_epi8(msg1, MASK);
517 msg = _mm_add_epi32(
518 msg1,
519 _mm_set_epi64x(0xAB1C5ED5923F82A4u64 as i64, 0x59F111F13956C25Bu64 as i64),
520 );
521 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
522 msg = _mm_shuffle_epi32(msg, 0x0E);
523 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
524 msg0 = _mm_sha256msg1_epu32(msg0, msg1);
525
526 msg2 = _mm_loadu_si128(self.buffer.as_ptr().add(block_offset + 32) as *const __m128i);
528 msg2 = _mm_shuffle_epi8(msg2, MASK);
529 msg = _mm_add_epi32(
530 msg2,
531 _mm_set_epi64x(0x550C7DC3243185BEu64 as i64, 0x12835B01D807AA98u64 as i64),
532 );
533 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
534 msg = _mm_shuffle_epi32(msg, 0x0E);
535 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
536 msg1 = _mm_sha256msg1_epu32(msg1, msg2);
537
538 msg3 = _mm_loadu_si128(self.buffer.as_ptr().add(block_offset + 48) as *const __m128i);
540 msg3 = _mm_shuffle_epi8(msg3, MASK);
541 msg = _mm_add_epi32(
542 msg3,
543 _mm_set_epi64x(0xC19BF1749BDC06A7u64 as i64, 0x80DEB1FE72BE5D74u64 as i64),
544 );
545 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
546 tmp = _mm_alignr_epi8(msg3, msg2, 4);
547 msg0 = _mm_add_epi32(msg0, tmp);
548 msg0 = _mm_sha256msg2_epu32(msg0, msg3);
549 msg = _mm_shuffle_epi32(msg, 0x0E);
550 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
551 msg2 = _mm_sha256msg1_epu32(msg2, msg3);
552
553 msg = _mm_add_epi32(
555 msg0,
556 _mm_set_epi64x(0x240CA1CC0FC19DC6u64 as i64, 0xEFBE4786E49B69C1u64 as i64),
557 );
558 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
559 tmp = _mm_alignr_epi8(msg0, msg3, 4);
560 msg1 = _mm_add_epi32(msg1, tmp);
561 msg1 = _mm_sha256msg2_epu32(msg1, msg0);
562 msg = _mm_shuffle_epi32(msg, 0x0E);
563 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
564 msg3 = _mm_sha256msg1_epu32(msg3, msg0);
565
566 msg = _mm_add_epi32(
568 msg1,
569 _mm_set_epi64x(0x76F988DA5CB0A9DCu64 as i64, 0x4A7484AA2DE92C6Fu64 as i64),
570 );
571 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
572 tmp = _mm_alignr_epi8(msg1, msg0, 4);
573 msg2 = _mm_add_epi32(msg2, tmp);
574 msg2 = _mm_sha256msg2_epu32(msg2, msg1);
575 msg = _mm_shuffle_epi32(msg, 0x0E);
576 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
577 msg0 = _mm_sha256msg1_epu32(msg0, msg1);
578
579 msg = _mm_add_epi32(
581 msg2,
582 _mm_set_epi64x(0xBF597FC7B00327C8u64 as i64, 0xA831C66D983E5152u64 as i64),
583 );
584 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
585 tmp = _mm_alignr_epi8(msg2, msg1, 4);
586 msg3 = _mm_add_epi32(msg3, tmp);
587 msg3 = _mm_sha256msg2_epu32(msg3, msg2);
588 msg = _mm_shuffle_epi32(msg, 0x0E);
589 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
590 msg1 = _mm_sha256msg1_epu32(msg1, msg2);
591
592 msg = _mm_add_epi32(
594 msg3,
595 _mm_set_epi64x(0x1429296706CA6351u64 as i64, 0xD5A79147C6E00BF3u64 as i64),
596 );
597 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
598 tmp = _mm_alignr_epi8(msg3, msg2, 4);
599 msg0 = _mm_add_epi32(msg0, tmp);
600 msg0 = _mm_sha256msg2_epu32(msg0, msg3);
601 msg = _mm_shuffle_epi32(msg, 0x0E);
602 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
603 msg2 = _mm_sha256msg1_epu32(msg2, msg3);
604
605 msg = _mm_add_epi32(
607 msg0,
608 _mm_set_epi64x(0x53380D134D2C6DFCu64 as i64, 0x2E1B213827B70A85u64 as i64),
609 );
610 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
611 tmp = _mm_alignr_epi8(msg0, msg3, 4);
612 msg1 = _mm_add_epi32(msg1, tmp);
613 msg1 = _mm_sha256msg2_epu32(msg1, msg0);
614 msg = _mm_shuffle_epi32(msg, 0x0E);
615 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
616 msg3 = _mm_sha256msg1_epu32(msg3, msg0);
617
618 msg = _mm_add_epi32(
620 msg1,
621 _mm_set_epi64x(0x92722C8581C2C92Eu64 as i64, 0x766A0ABB650A7354u64 as i64),
622 );
623 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
624 tmp = _mm_alignr_epi8(msg1, msg0, 4);
625 msg2 = _mm_add_epi32(msg2, tmp);
626 msg2 = _mm_sha256msg2_epu32(msg2, msg1);
627 msg = _mm_shuffle_epi32(msg, 0x0E);
628 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
629 msg0 = _mm_sha256msg1_epu32(msg0, msg1);
630
631 msg = _mm_add_epi32(
633 msg2,
634 _mm_set_epi64x(0xC76C51A3C24B8B70u64 as i64, 0xA81A664BA2BFE8A1u64 as i64),
635 );
636 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
637 tmp = _mm_alignr_epi8(msg2, msg1, 4);
638 msg3 = _mm_add_epi32(msg3, tmp);
639 msg3 = _mm_sha256msg2_epu32(msg3, msg2);
640 msg = _mm_shuffle_epi32(msg, 0x0E);
641 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
642 msg1 = _mm_sha256msg1_epu32(msg1, msg2);
643
644 msg = _mm_add_epi32(
646 msg3,
647 _mm_set_epi64x(0x106AA070F40E3585u64 as i64, 0xD6990624D192E819u64 as i64),
648 );
649 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
650 tmp = _mm_alignr_epi8(msg3, msg2, 4);
651 msg0 = _mm_add_epi32(msg0, tmp);
652 msg0 = _mm_sha256msg2_epu32(msg0, msg3);
653 msg = _mm_shuffle_epi32(msg, 0x0E);
654 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
655 msg2 = _mm_sha256msg1_epu32(msg2, msg3);
656
657 msg = _mm_add_epi32(
659 msg0,
660 _mm_set_epi64x(0x34B0BCB52748774Cu64 as i64, 0x1E376C0819A4C116u64 as i64),
661 );
662 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
663 tmp = _mm_alignr_epi8(msg0, msg3, 4);
664 msg1 = _mm_add_epi32(msg1, tmp);
665 msg1 = _mm_sha256msg2_epu32(msg1, msg0);
666 msg = _mm_shuffle_epi32(msg, 0x0E);
667 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
668 msg3 = _mm_sha256msg1_epu32(msg3, msg0);
669
670 msg = _mm_add_epi32(
672 msg1,
673 _mm_set_epi64x(0x682E6FF35B9CCA4Fu64 as i64, 0x4ED8AA4A391C0CB3u64 as i64),
674 );
675 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
676 tmp = _mm_alignr_epi8(msg1, msg0, 4);
677 msg2 = _mm_add_epi32(msg2, tmp);
678 msg2 = _mm_sha256msg2_epu32(msg2, msg1);
679 msg = _mm_shuffle_epi32(msg, 0x0E);
680 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
681
682 msg = _mm_add_epi32(
684 msg2,
685 _mm_set_epi64x(0x8CC7020884C87814u64 as i64, 0x78A5636F748F82EEu64 as i64),
686 );
687 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
688 tmp = _mm_alignr_epi8(msg2, msg1, 4);
689 msg3 = _mm_add_epi32(msg3, tmp);
690 msg3 = _mm_sha256msg2_epu32(msg3, msg2);
691 msg = _mm_shuffle_epi32(msg, 0x0E);
692 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
693
694 msg = _mm_add_epi32(
696 msg3,
697 _mm_set_epi64x(0xC67178F2BEF9A3F7u64 as i64, 0xA4506CEB90BEFFFAu64 as i64),
698 );
699 state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
700 msg = _mm_shuffle_epi32(msg, 0x0E);
701 state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
702
703 state0 = _mm_add_epi32(state0, abef_save);
705 state1 = _mm_add_epi32(state1, cdgh_save);
706 }
707
708 tmp = _mm_shuffle_epi32(state0, 0x1B); state1 = _mm_shuffle_epi32(state1, 0xB1); state0 = _mm_blend_epi16(tmp, state1, 0xF0); state1 = _mm_alignr_epi8(state1, tmp, 8); _mm_storeu_si128(self.h.as_mut_ptr().add(0) as *mut __m128i, state0);
717 _mm_storeu_si128(self.h.as_mut_ptr().add(4) as *mut __m128i, state1);
718 }
719
720 fn software_process_block(&mut self) {
722 debug_assert_eq!(self.buffer.len(), BLOCK_SIZE);
723
724 let mut w = [0u32; 16];
725 for (w_val, buff_bytes) in w.iter_mut().zip(self.buffer.chunks_exact(4)) {
726 *w_val = u32::from_be_bytes(buff_bytes.try_into().expect("4 byte slice"));
727 }
728
729 let mut a = self.h[0];
730 let mut b = self.h[1];
731 let mut c = self.h[2];
732 let mut d = self.h[3];
733 let mut e = self.h[4];
734 let mut f = self.h[5];
735 let mut g = self.h[6];
736 let mut h = self.h[7];
737
738 round!(a, b, c, d, e, f, g, h, 0x428a2f98, w[0]);
739 round!(h, a, b, c, d, e, f, g, 0x71374491, w[1]);
740 round!(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w[2]);
741 round!(f, g, h, a, b, c, d, e, 0xe9b5dba5, w[3]);
742 round!(e, f, g, h, a, b, c, d, 0x3956c25b, w[4]);
743 round!(d, e, f, g, h, a, b, c, 0x59f111f1, w[5]);
744 round!(c, d, e, f, g, h, a, b, 0x923f82a4, w[6]);
745 round!(b, c, d, e, f, g, h, a, 0xab1c5ed5, w[7]);
746 round!(a, b, c, d, e, f, g, h, 0xd807aa98, w[8]);
747 round!(h, a, b, c, d, e, f, g, 0x12835b01, w[9]);
748 round!(g, h, a, b, c, d, e, f, 0x243185be, w[10]);
749 round!(f, g, h, a, b, c, d, e, 0x550c7dc3, w[11]);
750 round!(e, f, g, h, a, b, c, d, 0x72be5d74, w[12]);
751 round!(d, e, f, g, h, a, b, c, 0x80deb1fe, w[13]);
752 round!(c, d, e, f, g, h, a, b, 0x9bdc06a7, w[14]);
753 round!(b, c, d, e, f, g, h, a, 0xc19bf174, w[15]);
754
755 round!(a, b, c, d, e, f, g, h, 0xe49b69c1, w[0], w[14], w[9], w[1]);
756 round!(h, a, b, c, d, e, f, g, 0xefbe4786, w[1], w[15], w[10], w[2]);
757 round!(g, h, a, b, c, d, e, f, 0x0fc19dc6, w[2], w[0], w[11], w[3]);
758 round!(f, g, h, a, b, c, d, e, 0x240ca1cc, w[3], w[1], w[12], w[4]);
759 round!(e, f, g, h, a, b, c, d, 0x2de92c6f, w[4], w[2], w[13], w[5]);
760 round!(d, e, f, g, h, a, b, c, 0x4a7484aa, w[5], w[3], w[14], w[6]);
761 round!(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w[6], w[4], w[15], w[7]);
762 round!(b, c, d, e, f, g, h, a, 0x76f988da, w[7], w[5], w[0], w[8]);
763 round!(a, b, c, d, e, f, g, h, 0x983e5152, w[8], w[6], w[1], w[9]);
764 round!(h, a, b, c, d, e, f, g, 0xa831c66d, w[9], w[7], w[2], w[10]);
765 round!(g, h, a, b, c, d, e, f, 0xb00327c8, w[10], w[8], w[3], w[11]);
766 round!(f, g, h, a, b, c, d, e, 0xbf597fc7, w[11], w[9], w[4], w[12]);
767 round!(e, f, g, h, a, b, c, d, 0xc6e00bf3, w[12], w[10], w[5], w[13]);
768 round!(d, e, f, g, h, a, b, c, 0xd5a79147, w[13], w[11], w[6], w[14]);
769 round!(c, d, e, f, g, h, a, b, 0x06ca6351, w[14], w[12], w[7], w[15]);
770 round!(b, c, d, e, f, g, h, a, 0x14292967, w[15], w[13], w[8], w[0]);
771
772 round!(a, b, c, d, e, f, g, h, 0x27b70a85, w[0], w[14], w[9], w[1]);
773 round!(h, a, b, c, d, e, f, g, 0x2e1b2138, w[1], w[15], w[10], w[2]);
774 round!(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w[2], w[0], w[11], w[3]);
775 round!(f, g, h, a, b, c, d, e, 0x53380d13, w[3], w[1], w[12], w[4]);
776 round!(e, f, g, h, a, b, c, d, 0x650a7354, w[4], w[2], w[13], w[5]);
777 round!(d, e, f, g, h, a, b, c, 0x766a0abb, w[5], w[3], w[14], w[6]);
778 round!(c, d, e, f, g, h, a, b, 0x81c2c92e, w[6], w[4], w[15], w[7]);
779 round!(b, c, d, e, f, g, h, a, 0x92722c85, w[7], w[5], w[0], w[8]);
780 round!(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w[8], w[6], w[1], w[9]);
781 round!(h, a, b, c, d, e, f, g, 0xa81a664b, w[9], w[7], w[2], w[10]);
782 round!(g, h, a, b, c, d, e, f, 0xc24b8b70, w[10], w[8], w[3], w[11]);
783 round!(f, g, h, a, b, c, d, e, 0xc76c51a3, w[11], w[9], w[4], w[12]);
784 round!(e, f, g, h, a, b, c, d, 0xd192e819, w[12], w[10], w[5], w[13]);
785 round!(d, e, f, g, h, a, b, c, 0xd6990624, w[13], w[11], w[6], w[14]);
786 round!(c, d, e, f, g, h, a, b, 0xf40e3585, w[14], w[12], w[7], w[15]);
787 round!(b, c, d, e, f, g, h, a, 0x106aa070, w[15], w[13], w[8], w[0]);
788
789 round!(a, b, c, d, e, f, g, h, 0x19a4c116, w[0], w[14], w[9], w[1]);
790 round!(h, a, b, c, d, e, f, g, 0x1e376c08, w[1], w[15], w[10], w[2]);
791 round!(g, h, a, b, c, d, e, f, 0x2748774c, w[2], w[0], w[11], w[3]);
792 round!(f, g, h, a, b, c, d, e, 0x34b0bcb5, w[3], w[1], w[12], w[4]);
793 round!(e, f, g, h, a, b, c, d, 0x391c0cb3, w[4], w[2], w[13], w[5]);
794 round!(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w[5], w[3], w[14], w[6]);
795 round!(c, d, e, f, g, h, a, b, 0x5b9cca4f, w[6], w[4], w[15], w[7]);
796 round!(b, c, d, e, f, g, h, a, 0x682e6ff3, w[7], w[5], w[0], w[8]);
797 round!(a, b, c, d, e, f, g, h, 0x748f82ee, w[8], w[6], w[1], w[9]);
798 round!(h, a, b, c, d, e, f, g, 0x78a5636f, w[9], w[7], w[2], w[10]);
799 round!(g, h, a, b, c, d, e, f, 0x84c87814, w[10], w[8], w[3], w[11]);
800 round!(f, g, h, a, b, c, d, e, 0x8cc70208, w[11], w[9], w[4], w[12]);
801 round!(e, f, g, h, a, b, c, d, 0x90befffa, w[12], w[10], w[5], w[13]);
802 round!(d, e, f, g, h, a, b, c, 0xa4506ceb, w[13], w[11], w[6], w[14]);
803 round!(c, d, e, f, g, h, a, b, 0xbef9a3f7, w[14], w[12], w[7], w[15]);
804 round!(b, c, d, e, f, g, h, a, 0xc67178f2, w[15], w[13], w[8], w[0]);
805
806 self.h[0] = self.h[0].wrapping_add(a);
807 self.h[1] = self.h[1].wrapping_add(b);
808 self.h[2] = self.h[2].wrapping_add(c);
809 self.h[3] = self.h[3].wrapping_add(d);
810 self.h[4] = self.h[4].wrapping_add(e);
811 self.h[5] = self.h[5].wrapping_add(f);
812 self.h[6] = self.h[6].wrapping_add(g);
813 self.h[7] = self.h[7].wrapping_add(h);
814 }
815}
816
817#[cfg(test)]
818mod tests {
819 use super::*;
820 use crate::sha256;
821
822 #[test]
823 #[cfg(feature = "alloc")]
824 fn test() {
825 #[derive(Clone)]
826 struct Test {
827 input: &'static str,
828 output: Vec<u8>,
829 output_str: &'static str,
830 }
831
832 #[rustfmt::skip]
833 let tests = vec![
834 Test {
836 input: "",
837 output: vec![
838 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
839 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
840 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
841 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
842 ],
843 output_str: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
844 },
845 Test {
846 input: "The quick brown fox jumps over the lazy dog",
847 output: vec![
848 0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94,
849 0x69, 0xca, 0x9a, 0xbc, 0xb0, 0x08, 0x2e, 0x4f,
850 0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76,
851 0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92,
852 ],
853 output_str: "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
854 },
855 Test {
856 input: "The quick brown fox jumps over the lazy dog.",
857 output: vec![
858 0xef, 0x53, 0x7f, 0x25, 0xc8, 0x95, 0xbf, 0xa7,
859 0x82, 0x52, 0x65, 0x29, 0xa9, 0xb6, 0x3d, 0x97,
860 0xaa, 0x63, 0x15, 0x64, 0xd5, 0xd7, 0x89, 0xc2,
861 0xb7, 0x65, 0x44, 0x8c, 0x86, 0x35, 0xfb, 0x6c,
862 ],
863 output_str: "ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c",
864 },
865 ];
866
867 for test in tests {
868 let hash = sha256::Hash::hash(test.input.as_bytes());
870 assert_eq!(hash, test.output_str.parse::<sha256::Hash>().expect("parse hex"));
871 assert_eq!(&hash[..], &test.output[..]);
872 assert_eq!(&hash.to_string(), &test.output_str);
873
874 let mut engine = sha256::Engine::new();
876 for ch in test.input.as_bytes() {
877 engine.input(&[*ch]);
878 }
879 let manual_hash = sha256::Hash::from_engine(engine);
880 assert_eq!(hash, manual_hash);
881 assert_eq!(hash.to_byte_array()[..].as_ref(), test.output.as_slice());
882 }
883 }
884
885 #[test]
886 fn fmt_roundtrips() {
887 let hash = sha256::Hash::hash(b"some arbitrary bytes");
888 let hex = format!("{}", hash);
889 let rinsed = hex.parse::<sha256::Hash>().expect("failed to parse hex");
890 assert_eq!(rinsed, hash)
891 }
892
893 #[test]
894 #[rustfmt::skip]
895 fn midstate() {
896 let mut engine = sha256::Engine::new();
898 engine.input(&[
901 0x9d, 0xd0, 0x1b, 0x56, 0xb1, 0x56, 0x45, 0x14,
902 0x3e, 0xad, 0x15, 0x8d, 0xec, 0x19, 0xf8, 0xce,
903 0xa9, 0x0b, 0xd0, 0xa9, 0xb2, 0xf8, 0x1d, 0x21,
904 0xff, 0xa3, 0xa4, 0xc6, 0x44, 0x81, 0xd4, 0x1c,
905 ]);
906 engine.input(&[0; 32]);
908 assert_eq!(
909 engine.midstate(),
910 sha256::Midstate::from_byte_array([
912 0x0b, 0xcf, 0xe0, 0xe5, 0x4e, 0x6c, 0xc7, 0xd3,
913 0x4f, 0x4f, 0x7c, 0x1d, 0xf0, 0xb0, 0xf5, 0x03,
914 0xf2, 0xf7, 0x12, 0x91, 0x2a, 0x06, 0x05, 0xb4,
915 0x14, 0xed, 0x33, 0x7f, 0x7f, 0x03, 0x2e, 0x03,
916 ])
917 );
918 }
919
920 #[test]
921 fn engine_with_state() {
922 let mut engine = sha256::Hash::engine();
923 let midstate_engine = sha256::Engine::from_midstate(engine.midstate(), 0);
924 assert_eq!(engine.h, midstate_engine.h);
926
927 engine.input(&[1; 63]);
929 assert_eq!(engine.h, midstate_engine.h);
930 engine.input(&[2; 1]);
931 assert_ne!(engine.h, midstate_engine.h);
932
933 let data_vec = vec![vec![3; 1], vec![4; 63], vec![5; 65], vec![6; 66]];
936 for data in data_vec {
937 let mut engine = engine.clone();
938 let mut midstate_engine =
939 sha256::Engine::from_midstate(engine.midstate(), engine.length);
940 assert_eq!(engine.h, midstate_engine.h);
941 assert_eq!(engine.length, midstate_engine.length);
942 engine.input(&data);
943 midstate_engine.input(&data);
944 assert_eq!(engine.h, midstate_engine.h);
945 let hash1 = sha256::Hash::from_engine(engine);
946 let hash2 = sha256::Hash::from_engine(midstate_engine);
947 assert_eq!(hash1, hash2);
948 }
949
950 #[rustfmt::skip]
954 static MIDSTATE: [u8; 32] = [
955 0x0f, 0xd0, 0x69, 0x0c, 0xfe, 0xfe, 0xae, 0x97,
956 0x99, 0x6e, 0xac, 0x7f, 0x5c, 0x30, 0xd8, 0x64,
957 0x8c, 0x4a, 0x05, 0x73, 0xac, 0xa1, 0xa2, 0x2f,
958 0x6f, 0x43, 0xb8, 0x01, 0x85, 0xce, 0x27, 0xcd,
959 ];
960 #[rustfmt::skip]
961 static HASH_EXPECTED: [u8; 32] = [
962 0x18, 0x84, 0xe4, 0x72, 0x40, 0x4e, 0xf4, 0x5a,
963 0xb4, 0x9c, 0x4e, 0xa4, 0x9a, 0xe6, 0x23, 0xa8,
964 0x88, 0x52, 0x7f, 0x7d, 0x8a, 0x06, 0x94, 0x20,
965 0x8f, 0xf1, 0xf7, 0xa9, 0xd5, 0x69, 0x09, 0x59,
966 ];
967 let midstate_engine =
968 sha256::Engine::from_midstate(sha256::Midstate::from_byte_array(MIDSTATE), 64);
969 let hash = sha256::Hash::from_engine(midstate_engine);
970 assert_eq!(hash, sha256::Hash(HASH_EXPECTED));
971 }
972
973 #[test]
974 fn const_hash() {
975 assert_eq!(Hash::hash(&[]), Hash::const_hash(&[]));
976
977 let mut bytes = Vec::new();
978 for i in 0..256 {
979 bytes.push(i as u8);
980 assert_eq!(
981 Hash::hash(&bytes),
982 Hash::const_hash(&bytes),
983 "hashes don't match for length {}",
984 i + 1
985 );
986 }
987 }
988
989 #[test]
990 fn const_midstate() {
991 assert_eq!(
992 Midstate::hash_tag(b"TapLeaf"),
993 Midstate([
994 156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211,
995 243, 147, 108, 71, 99, 110, 96, 125, 179, 62, 234, 221, 198, 240, 201,
996 ])
997 )
998 }
999
1000 #[test]
1001 fn midstate_fmt_roundtrip() {
1002 let midstate = Midstate::hash_tag(b"ArbitraryTag");
1003 let hex = format!("{}", midstate);
1004 let rinsed = hex.parse::<Midstate>().expect("failed to parse hex");
1005 assert_eq!(rinsed, midstate)
1006 }
1007
1008 #[cfg(feature = "serde")]
1009 #[test]
1010 fn sha256_serde() {
1011 use serde_test::{assert_tokens, Configure, Token};
1012
1013 #[rustfmt::skip]
1014 static HASH_BYTES: [u8; 32] = [
1015 0xef, 0x53, 0x7f, 0x25, 0xc8, 0x95, 0xbf, 0xa7,
1016 0x82, 0x52, 0x65, 0x29, 0xa9, 0xb6, 0x3d, 0x97,
1017 0xaa, 0x63, 0x15, 0x64, 0xd5, 0xd7, 0x89, 0xc2,
1018 0xb7, 0x65, 0x44, 0x8c, 0x86, 0x35, 0xfb, 0x6c,
1019 ];
1020
1021 let hash = sha256::Hash::from_slice(&HASH_BYTES).expect("right number of bytes");
1022 assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]);
1023 assert_tokens(
1024 &hash.readable(),
1025 &[Token::Str("ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c")],
1026 );
1027 }
1028
1029 #[cfg(target_arch = "wasm32")]
1030 mod wasm_tests {
1031 extern crate wasm_bindgen_test;
1032 use self::wasm_bindgen_test::*;
1033 use super::*;
1034 #[wasm_bindgen_test]
1035 fn sha256_tests() {
1036 test();
1037 midstate();
1038 engine_with_state();
1039 }
1040 }
1041}
1042
1043#[cfg(bench)]
1044mod benches {
1045 use test::Bencher;
1046
1047 use super::*;
1048 use crate::sha256;
1049
1050 #[bench]
1051 pub fn sha256_10(bh: &mut Bencher) {
1052 let mut engine = sha256::Hash::engine();
1053 let bytes = [1u8; 10];
1054 bh.iter(|| {
1055 engine.input(&bytes);
1056 });
1057 bh.bytes = bytes.len() as u64;
1058 }
1059
1060 #[bench]
1061 pub fn sha256_1k(bh: &mut Bencher) {
1062 let mut engine = sha256::Hash::engine();
1063 let bytes = [1u8; 1024];
1064 bh.iter(|| {
1065 engine.input(&bytes);
1066 });
1067 bh.bytes = bytes.len() as u64;
1068 }
1069
1070 #[bench]
1071 pub fn sha256_64k(bh: &mut Bencher) {
1072 let mut engine = sha256::Hash::engine();
1073 let bytes = [1u8; 65536];
1074 bh.iter(|| {
1075 engine.input(&bytes);
1076 });
1077 bh.bytes = bytes.len() as u64;
1078 }
1079}