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