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).div_ceil(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 let _ = w[15]; 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 HashEngine {
429 pub fn from_midstate(midstate: Midstate, length: usize) -> HashEngine {
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 HashEngine { 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 let _ = w[15]; self.h[0] = self.h[0].wrapping_add(a);
808 self.h[1] = self.h[1].wrapping_add(b);
809 self.h[2] = self.h[2].wrapping_add(c);
810 self.h[3] = self.h[3].wrapping_add(d);
811 self.h[4] = self.h[4].wrapping_add(e);
812 self.h[5] = self.h[5].wrapping_add(f);
813 self.h[6] = self.h[6].wrapping_add(g);
814 self.h[7] = self.h[7].wrapping_add(h);
815 }
816}
817
818#[cfg(test)]
819mod tests {
820 use super::*;
821 use crate::{sha256, Hash as _, HashEngine};
822
823 #[test]
824 #[cfg(feature = "alloc")]
825 fn test() {
826 #[derive(Clone)]
827 struct Test {
828 input: &'static str,
829 output: Vec<u8>,
830 output_str: &'static str,
831 }
832
833 #[rustfmt::skip]
834 let tests = vec![
835 Test {
837 input: "",
838 output: vec![
839 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
840 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
841 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
842 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
843 ],
844 output_str: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
845 },
846 Test {
847 input: "The quick brown fox jumps over the lazy dog",
848 output: vec![
849 0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94,
850 0x69, 0xca, 0x9a, 0xbc, 0xb0, 0x08, 0x2e, 0x4f,
851 0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76,
852 0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92,
853 ],
854 output_str: "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
855 },
856 Test {
857 input: "The quick brown fox jumps over the lazy dog.",
858 output: vec![
859 0xef, 0x53, 0x7f, 0x25, 0xc8, 0x95, 0xbf, 0xa7,
860 0x82, 0x52, 0x65, 0x29, 0xa9, 0xb6, 0x3d, 0x97,
861 0xaa, 0x63, 0x15, 0x64, 0xd5, 0xd7, 0x89, 0xc2,
862 0xb7, 0x65, 0x44, 0x8c, 0x86, 0x35, 0xfb, 0x6c,
863 ],
864 output_str: "ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c",
865 },
866 ];
867
868 for test in tests {
869 let hash = sha256::Hash::hash(test.input.as_bytes());
871 assert_eq!(hash, test.output_str.parse::<sha256::Hash>().expect("parse hex"));
872 assert_eq!(&hash[..], &test.output[..]);
873 assert_eq!(&hash.to_string(), &test.output_str);
874
875 let mut engine = sha256::Hash::engine();
877 for ch in test.input.as_bytes() {
878 engine.input(&[*ch]);
879 }
880 let manual_hash = sha256::Hash::from_engine(engine);
881 assert_eq!(hash, manual_hash);
882 assert_eq!(hash.to_byte_array()[..].as_ref(), test.output.as_slice());
883 }
884 }
885
886 #[test]
887 fn fmt_roundtrips() {
888 let hash = sha256::Hash::hash(b"some arbitrary bytes");
889 let hex = format!("{}", hash);
890 let rinsed = hex.parse::<sha256::Hash>().expect("failed to parse hex");
891 assert_eq!(rinsed, hash)
892 }
893
894 #[test]
895 #[rustfmt::skip]
896 fn midstate() {
897 let mut engine = sha256::Hash::engine();
899 engine.input(&[
902 0x9d, 0xd0, 0x1b, 0x56, 0xb1, 0x56, 0x45, 0x14,
903 0x3e, 0xad, 0x15, 0x8d, 0xec, 0x19, 0xf8, 0xce,
904 0xa9, 0x0b, 0xd0, 0xa9, 0xb2, 0xf8, 0x1d, 0x21,
905 0xff, 0xa3, 0xa4, 0xc6, 0x44, 0x81, 0xd4, 0x1c,
906 ]);
907 engine.input(&[0; 32]);
909 assert_eq!(
910 engine.midstate(),
911 sha256::Midstate::from_byte_array([
913 0x0b, 0xcf, 0xe0, 0xe5, 0x4e, 0x6c, 0xc7, 0xd3,
914 0x4f, 0x4f, 0x7c, 0x1d, 0xf0, 0xb0, 0xf5, 0x03,
915 0xf2, 0xf7, 0x12, 0x91, 0x2a, 0x06, 0x05, 0xb4,
916 0x14, 0xed, 0x33, 0x7f, 0x7f, 0x03, 0x2e, 0x03,
917 ])
918 );
919 }
920
921 #[test]
922 fn engine_with_state() {
923 let mut engine = sha256::Hash::engine();
924 let midstate_engine = sha256::HashEngine::from_midstate(engine.midstate(), 0);
925 assert_eq!(engine.h, midstate_engine.h);
927
928 engine.input(&[1; 63]);
930 assert_eq!(engine.h, midstate_engine.h);
931 engine.input(&[2; 1]);
932 assert_ne!(engine.h, midstate_engine.h);
933
934 let data_vec = vec![vec![3; 1], vec![4; 63], vec![5; 65], vec![6; 66]];
937 for data in data_vec {
938 let mut engine = engine.clone();
939 let mut midstate_engine =
940 sha256::HashEngine::from_midstate(engine.midstate(), engine.length);
941 assert_eq!(engine.h, midstate_engine.h);
942 assert_eq!(engine.length, midstate_engine.length);
943 engine.input(&data);
944 midstate_engine.input(&data);
945 assert_eq!(engine.h, midstate_engine.h);
946 let hash1 = sha256::Hash::from_engine(engine);
947 let hash2 = sha256::Hash::from_engine(midstate_engine);
948 assert_eq!(hash1, hash2);
949 }
950
951 #[rustfmt::skip]
955 static MIDSTATE: [u8; 32] = [
956 0x0f, 0xd0, 0x69, 0x0c, 0xfe, 0xfe, 0xae, 0x97,
957 0x99, 0x6e, 0xac, 0x7f, 0x5c, 0x30, 0xd8, 0x64,
958 0x8c, 0x4a, 0x05, 0x73, 0xac, 0xa1, 0xa2, 0x2f,
959 0x6f, 0x43, 0xb8, 0x01, 0x85, 0xce, 0x27, 0xcd,
960 ];
961 #[rustfmt::skip]
962 static HASH_EXPECTED: [u8; 32] = [
963 0x18, 0x84, 0xe4, 0x72, 0x40, 0x4e, 0xf4, 0x5a,
964 0xb4, 0x9c, 0x4e, 0xa4, 0x9a, 0xe6, 0x23, 0xa8,
965 0x88, 0x52, 0x7f, 0x7d, 0x8a, 0x06, 0x94, 0x20,
966 0x8f, 0xf1, 0xf7, 0xa9, 0xd5, 0x69, 0x09, 0x59,
967 ];
968 let midstate_engine =
969 sha256::HashEngine::from_midstate(sha256::Midstate::from_byte_array(MIDSTATE), 64);
970 let hash = sha256::Hash::from_engine(midstate_engine);
971 assert_eq!(hash, sha256::Hash(HASH_EXPECTED));
972 }
973
974 #[test]
975 fn const_hash() {
976 assert_eq!(Hash::hash(&[]), Hash::const_hash(&[]));
977
978 let mut bytes = Vec::new();
979 for i in 0..256 {
980 bytes.push(i as u8);
981 assert_eq!(
982 Hash::hash(&bytes),
983 Hash::const_hash(&bytes),
984 "hashes don't match for length {}",
985 i + 1
986 );
987 }
988 }
989
990 #[test]
991 fn const_midstate() {
992 assert_eq!(
993 Midstate::hash_tag(b"TapLeaf"),
994 Midstate([
995 156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211,
996 243, 147, 108, 71, 99, 110, 96, 125, 179, 62, 234, 221, 198, 240, 201,
997 ])
998 )
999 }
1000
1001 #[test]
1002 fn midstate_fmt_roundtrip() {
1003 let midstate = Midstate::hash_tag(b"ArbitraryTag");
1004 let hex = format!("{}", midstate);
1005 let rinsed = hex.parse::<Midstate>().expect("failed to parse hex");
1006 assert_eq!(rinsed, midstate)
1007 }
1008
1009 #[cfg(feature = "serde")]
1010 #[test]
1011 fn sha256_serde() {
1012 use serde_test::{assert_tokens, Configure, Token};
1013
1014 #[rustfmt::skip]
1015 static HASH_BYTES: [u8; 32] = [
1016 0xef, 0x53, 0x7f, 0x25, 0xc8, 0x95, 0xbf, 0xa7,
1017 0x82, 0x52, 0x65, 0x29, 0xa9, 0xb6, 0x3d, 0x97,
1018 0xaa, 0x63, 0x15, 0x64, 0xd5, 0xd7, 0x89, 0xc2,
1019 0xb7, 0x65, 0x44, 0x8c, 0x86, 0x35, 0xfb, 0x6c,
1020 ];
1021
1022 let hash = sha256::Hash::from_slice(&HASH_BYTES).expect("right number of bytes");
1023 assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]);
1024 assert_tokens(
1025 &hash.readable(),
1026 &[Token::Str("ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c")],
1027 );
1028 }
1029
1030 #[cfg(target_arch = "wasm32")]
1031 mod wasm_tests {
1032 extern crate wasm_bindgen_test;
1033 use self::wasm_bindgen_test::*;
1034 use super::*;
1035 #[wasm_bindgen_test]
1036 fn sha256_tests() {
1037 test();
1038 midstate();
1039 engine_with_state();
1040 }
1041 }
1042}
1043
1044#[cfg(bench)]
1045mod benches {
1046 use test::Bencher;
1047
1048 use crate::{sha256, Hash, HashEngine};
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}