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