nacl/hash/
sha512.rs

1// Copyright(c) 2018, 2021 3NSoft Inc.
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU Lesser General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU Lesser General Public License for more details.
12//
13// You should have received a copy of the GNU Lesser General Public License
14// along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16#![allow(non_upper_case_globals)]
17
18use crate::util::ops::{ incr, add2, add4, add5 };
19use crate::util::Resetable;
20
21/// Analog of load_bigendian in crypto_hashblocks/sha512/ref/blocks.c
22#[inline]
23fn load_bigendian(x: &[u8]) -> u64 {
24	(x[7] as u64)
25	| ((x[6] as u64) << 8) 
26	| ((x[5] as u64) << 16) 
27	| ((x[4] as u64) << 24) 
28	| ((x[3] as u64) << 32) 
29	| ((x[2] as u64) << 40) 
30	| ((x[1] as u64) << 48) 
31	| ((x[0] as u64) << 56)
32}
33
34/// Analog of store_bigendian in crypto_hashblocks/sha512/ref/blocks.c
35#[inline]
36fn store_bigendian(x: &mut [u8], mut u: u64) {
37	x[7] = u as u8; u >>= 8;
38	x[6] = u as u8; u >>= 8;
39	x[5] = u as u8; u >>= 8;
40	x[4] = u as u8; u >>= 8;
41	x[3] = u as u8; u >>= 8;
42	x[2] = u as u8; u >>= 8;
43	x[1] = u as u8; u >>= 8;
44	x[0] = u as u8;
45}
46
47macro_rules! SHR {
48	($x: expr, $n: expr) => (($x) >> ($n))
49}
50
51macro_rules! ROTR {
52	($x: expr, $n: expr) => ((($x) >> ($n)) | (($x) << (64 - ($n))))
53}
54
55macro_rules! Ch {
56	($x: expr, $y: expr, $z: expr) => (($x & $y) ^ (!$x & $z))
57}
58
59macro_rules! Maj {
60	($x: expr, $y: expr, $z: expr) => (($x & $y) ^ ($x & $z) ^ ($y & $z))
61}
62
63macro_rules! Sigma0 {
64	($x: expr) => (ROTR!($x,28) ^ ROTR!($x,34) ^ ROTR!($x,39))
65}
66
67macro_rules! Sigma1 {
68	($x: expr) => (ROTR!($x,14) ^ ROTR!($x,18) ^ ROTR!($x,41))
69}
70
71macro_rules! sigma0 {
72	($x: expr) => (ROTR!($x, 1) ^ ROTR!($x, 8) ^ SHR!($x,7))
73}
74
75macro_rules! sigma1 {
76	($x: expr) => (ROTR!($x,19) ^ ROTR!($x,61) ^ SHR!($x,6))
77}
78
79macro_rules! M {
80	($w0: expr, $w14: expr, $w9: expr, $w1: expr) => {
81		$w0 = add4!( sigma1!($w14), $w9, sigma0!($w1), $w0 );
82	}
83}
84
85macro_rules! EXPAND {
86	($w0: expr, $w1: expr, $w2: expr, $w3: expr, $w4: expr, $w5: expr,
87			$w6: expr, $w7: expr, $w8: expr, $w9: expr, $w10: expr,
88			$w11: expr, $w12: expr, $w13: expr, $w14: expr, $w15: expr) => {
89		M!($w0 ,$w14,$w9 ,$w1 );
90		M!($w1 ,$w15,$w10,$w2 );
91		M!($w2 ,$w0 ,$w11,$w3 );
92		M!($w3 ,$w1 ,$w12,$w4 );
93		M!($w4 ,$w2 ,$w13,$w5 );
94		M!($w5 ,$w3 ,$w14,$w6 );
95		M!($w6 ,$w4 ,$w15,$w7 );
96		M!($w7 ,$w5 ,$w0 ,$w8 );
97		M!($w8 ,$w6 ,$w1 ,$w9 );
98		M!($w9 ,$w7 ,$w2 ,$w10);
99		M!($w10,$w8 ,$w3 ,$w11);
100		M!($w11,$w9 ,$w4 ,$w12);
101		M!($w12,$w10,$w5 ,$w13);
102		M!($w13,$w11,$w6 ,$w14);
103		M!($w14,$w12,$w7 ,$w15);
104		M!($w15,$w13,$w8 ,$w0 );
105	}
106}
107
108macro_rules! F {
109	($w: expr, $k: expr,
110			$a: expr, $b: expr, $c: expr, $d: expr,
111			$e: expr, $f: expr, $g: expr, $h: expr) => {
112		let t1 = add5!( $h, Sigma1!($e), Ch!($e, $f, $g), $k, $w );
113		let t2 = add2!( Sigma0!($a), Maj!($a, $b, $c) );
114		$h = $g;
115		$g = $f;
116		$f = $e;
117		$e = add2!( $d, t1 );
118		$d = $c;
119		$c = $b;
120		$b = $a;
121		$a = add2!( t1, t2 );
122	}
123}
124
125fn crypto_hashblocks(statebytes: &mut [u8], inc: &[u8]) -> usize {
126	let total_len = inc.len();
127	let mut hashed_len = 0;
128	let mut state: [u64; 8] = [0; 8];
129
130	let mut a = load_bigendian(&statebytes[0..8]);		state[0] = a;
131	let mut b = load_bigendian(&statebytes[8..16]);		state[1] = b;
132	let mut c = load_bigendian(&statebytes[16..24]);	state[2] = c;
133	let mut d = load_bigendian(&statebytes[24..32]);	state[3] = d;
134	let mut e = load_bigendian(&statebytes[32..40]);	state[4] = e;
135	let mut f = load_bigendian(&statebytes[40..48]);	state[5] = f;
136	let mut g = load_bigendian(&statebytes[48..56]);	state[6] = g;
137	let mut h = load_bigendian(&statebytes[56..64]);	state[7] = h;
138
139	while (total_len - hashed_len) >= 128 {
140		let chunk = &inc[hashed_len..hashed_len+128];
141
142		let mut w0  = load_bigendian(&chunk[0..8]);
143		let mut w1  = load_bigendian(&chunk[8..16]);
144		let mut w2  = load_bigendian(&chunk[16..24]);
145		let mut w3  = load_bigendian(&chunk[24..32]);
146		let mut w4  = load_bigendian(&chunk[32..40]);
147		let mut w5  = load_bigendian(&chunk[40..48]);
148		let mut w6  = load_bigendian(&chunk[48..56]);
149		let mut w7  = load_bigendian(&chunk[56..64]);
150		let mut w8  = load_bigendian(&chunk[64..72]);
151		let mut w9  = load_bigendian(&chunk[72..80]);
152		let mut w10 = load_bigendian(&chunk[80..88]);
153		let mut w11 = load_bigendian(&chunk[88..96]);
154		let mut w12 = load_bigendian(&chunk[96..104]);
155		let mut w13 = load_bigendian(&chunk[104..112]);
156		let mut w14 = load_bigendian(&chunk[112..120]);
157		let mut w15 = load_bigendian(&chunk[120..128]);
158
159		F!(w0 ,0x428a2f98d728ae22, a,b,c,d,e,f,g,h);
160		F!(w1 ,0x7137449123ef65cd, a,b,c,d,e,f,g,h);
161		F!(w2 ,0xb5c0fbcfec4d3b2f, a,b,c,d,e,f,g,h);
162		F!(w3 ,0xe9b5dba58189dbbc, a,b,c,d,e,f,g,h);
163		F!(w4 ,0x3956c25bf348b538, a,b,c,d,e,f,g,h);
164		F!(w5 ,0x59f111f1b605d019, a,b,c,d,e,f,g,h);
165		F!(w6 ,0x923f82a4af194f9b, a,b,c,d,e,f,g,h);
166		F!(w7 ,0xab1c5ed5da6d8118, a,b,c,d,e,f,g,h);
167		F!(w8 ,0xd807aa98a3030242, a,b,c,d,e,f,g,h);
168		F!(w9 ,0x12835b0145706fbe, a,b,c,d,e,f,g,h);
169		F!(w10,0x243185be4ee4b28c, a,b,c,d,e,f,g,h);
170		F!(w11,0x550c7dc3d5ffb4e2, a,b,c,d,e,f,g,h);
171		F!(w12,0x72be5d74f27b896f, a,b,c,d,e,f,g,h);
172		F!(w13,0x80deb1fe3b1696b1, a,b,c,d,e,f,g,h);
173		F!(w14,0x9bdc06a725c71235, a,b,c,d,e,f,g,h);
174		F!(w15,0xc19bf174cf692694, a,b,c,d,e,f,g,h);
175
176		EXPAND!(w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15);
177
178		F!(w0 ,0xe49b69c19ef14ad2, a,b,c,d,e,f,g,h);
179		F!(w1 ,0xefbe4786384f25e3, a,b,c,d,e,f,g,h);
180		F!(w2 ,0x0fc19dc68b8cd5b5, a,b,c,d,e,f,g,h);
181		F!(w3 ,0x240ca1cc77ac9c65, a,b,c,d,e,f,g,h);
182		F!(w4 ,0x2de92c6f592b0275, a,b,c,d,e,f,g,h);
183		F!(w5 ,0x4a7484aa6ea6e483, a,b,c,d,e,f,g,h);
184		F!(w6 ,0x5cb0a9dcbd41fbd4, a,b,c,d,e,f,g,h);
185		F!(w7 ,0x76f988da831153b5, a,b,c,d,e,f,g,h);
186		F!(w8 ,0x983e5152ee66dfab, a,b,c,d,e,f,g,h);
187		F!(w9 ,0xa831c66d2db43210, a,b,c,d,e,f,g,h);
188		F!(w10,0xb00327c898fb213f, a,b,c,d,e,f,g,h);
189		F!(w11,0xbf597fc7beef0ee4, a,b,c,d,e,f,g,h);
190		F!(w12,0xc6e00bf33da88fc2, a,b,c,d,e,f,g,h);
191		F!(w13,0xd5a79147930aa725, a,b,c,d,e,f,g,h);
192		F!(w14,0x06ca6351e003826f, a,b,c,d,e,f,g,h);
193		F!(w15,0x142929670a0e6e70, a,b,c,d,e,f,g,h);
194
195		EXPAND!(w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15);
196
197		F!(w0 ,0x27b70a8546d22ffc, a,b,c,d,e,f,g,h);
198		F!(w1 ,0x2e1b21385c26c926, a,b,c,d,e,f,g,h);
199		F!(w2 ,0x4d2c6dfc5ac42aed, a,b,c,d,e,f,g,h);
200		F!(w3 ,0x53380d139d95b3df, a,b,c,d,e,f,g,h);
201		F!(w4 ,0x650a73548baf63de, a,b,c,d,e,f,g,h);
202		F!(w5 ,0x766a0abb3c77b2a8, a,b,c,d,e,f,g,h);
203		F!(w6 ,0x81c2c92e47edaee6, a,b,c,d,e,f,g,h);
204		F!(w7 ,0x92722c851482353b, a,b,c,d,e,f,g,h);
205		F!(w8 ,0xa2bfe8a14cf10364, a,b,c,d,e,f,g,h);
206		F!(w9 ,0xa81a664bbc423001, a,b,c,d,e,f,g,h);
207		F!(w10,0xc24b8b70d0f89791, a,b,c,d,e,f,g,h);
208		F!(w11,0xc76c51a30654be30, a,b,c,d,e,f,g,h);
209		F!(w12,0xd192e819d6ef5218, a,b,c,d,e,f,g,h);
210		F!(w13,0xd69906245565a910, a,b,c,d,e,f,g,h);
211		F!(w14,0xf40e35855771202a, a,b,c,d,e,f,g,h);
212		F!(w15,0x106aa07032bbd1b8, a,b,c,d,e,f,g,h);
213
214		EXPAND!(w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15);
215
216		F!(w0 ,0x19a4c116b8d2d0c8, a,b,c,d,e,f,g,h);
217		F!(w1 ,0x1e376c085141ab53, a,b,c,d,e,f,g,h);
218		F!(w2 ,0x2748774cdf8eeb99, a,b,c,d,e,f,g,h);
219		F!(w3 ,0x34b0bcb5e19b48a8, a,b,c,d,e,f,g,h);
220		F!(w4 ,0x391c0cb3c5c95a63, a,b,c,d,e,f,g,h);
221		F!(w5 ,0x4ed8aa4ae3418acb, a,b,c,d,e,f,g,h);
222		F!(w6 ,0x5b9cca4f7763e373, a,b,c,d,e,f,g,h);
223		F!(w7 ,0x682e6ff3d6b2b8a3, a,b,c,d,e,f,g,h);
224		F!(w8 ,0x748f82ee5defb2fc, a,b,c,d,e,f,g,h);
225		F!(w9 ,0x78a5636f43172f60, a,b,c,d,e,f,g,h);
226		F!(w10,0x84c87814a1f0ab72, a,b,c,d,e,f,g,h);
227		F!(w11,0x8cc702081a6439ec, a,b,c,d,e,f,g,h);
228		F!(w12,0x90befffa23631e28, a,b,c,d,e,f,g,h);
229		F!(w13,0xa4506cebde82bde9, a,b,c,d,e,f,g,h);
230		F!(w14,0xbef9a3f7b2c67915, a,b,c,d,e,f,g,h);
231		F!(w15,0xc67178f2e372532b, a,b,c,d,e,f,g,h);
232
233		EXPAND!(w0,w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13,w14,w15);
234
235		F!(w0 ,0xca273eceea26619c, a,b,c,d,e,f,g,h);
236		F!(w1 ,0xd186b8c721c0c207, a,b,c,d,e,f,g,h);
237		F!(w2 ,0xeada7dd6cde0eb1e, a,b,c,d,e,f,g,h);
238		F!(w3 ,0xf57d4f7fee6ed178, a,b,c,d,e,f,g,h);
239		F!(w4 ,0x06f067aa72176fba, a,b,c,d,e,f,g,h);
240		F!(w5 ,0x0a637dc5a2c898a6, a,b,c,d,e,f,g,h);
241		F!(w6 ,0x113f9804bef90dae, a,b,c,d,e,f,g,h);
242		F!(w7 ,0x1b710b35131c471b, a,b,c,d,e,f,g,h);
243		F!(w8 ,0x28db77f523047d84, a,b,c,d,e,f,g,h);
244		F!(w9 ,0x32caab7b40c72493, a,b,c,d,e,f,g,h);
245		F!(w10,0x3c9ebe0a15c9bebc, a,b,c,d,e,f,g,h);
246		F!(w11,0x431d67c49c100d4c, a,b,c,d,e,f,g,h);
247		F!(w12,0x4cc5d4becb3e42b6, a,b,c,d,e,f,g,h);
248		F!(w13,0x597f299cfc657e2a, a,b,c,d,e,f,g,h);
249		F!(w14,0x5fcb6fab3ad6faec, a,b,c,d,e,f,g,h);
250		F!(w15,0x6c44198c4a475817, a,b,c,d,e,f,g,h);
251
252		incr!( a, state[0] );
253		incr!( b, state[1] );
254		incr!( c, state[2] );
255		incr!( d, state[3] );
256		incr!( e, state[4] );
257		incr!( f, state[5] );
258		incr!( g, state[6] );
259		incr!( h, state[7] );
260
261		state[0] = a;
262		state[1] = b;
263		state[2] = c;
264		state[3] = d;
265		state[4] = e;
266		state[5] = f;
267		state[6] = g;
268		state[7] = h;
269
270		hashed_len += 128;
271	}
272
273	store_bigendian(&mut statebytes[0..8],		state[0]);
274	store_bigendian(&mut statebytes[8..16],	state[1]);
275	store_bigendian(&mut statebytes[16..24],	state[2]);
276	store_bigendian(&mut statebytes[24..32],	state[3]);
277	store_bigendian(&mut statebytes[32..40],	state[4]);
278	store_bigendian(&mut statebytes[40..48],	state[5]);
279	store_bigendian(&mut statebytes[48..56],	state[6]);
280	store_bigendian(&mut statebytes[56..64],	state[7]);
281
282	hashed_len
283}
284
285const iv: [u8; 64] = [
286	0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08,
287	0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b,
288	0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b,
289	0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1,
290	0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1,
291	0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f,
292	0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b,
293	0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 ];
294
295pub fn hash_sha512(out: &mut [u8], inc: &[u8]) {
296	let mut h: [u8; 64] = [0; 64];
297
298	h.copy_from_slice(&iv);
299
300	let hashed_len = crypto_hashblocks(&mut h, inc);
301	let odd_bytes = &inc[hashed_len..];
302
303	hash_padded_block(&mut h, odd_bytes, inc.len());
304
305	out.copy_from_slice(&h);
306}
307
308fn hash_padded_block(h: &mut [u8], odd_bytes: &[u8], total_len: usize) {
309	let mut padded: [u8; 256] = [0; 256];
310	let odd_len = odd_bytes.len();
311
312	padded[0..odd_len].copy_from_slice(odd_bytes);
313	padded[odd_len] = 0x80;
314
315	if odd_len < 112 {
316		padded[119] = (total_len >> 61) as u8;
317		padded[120] = (total_len >> 53) as u8;
318		padded[121] = (total_len >> 45) as u8;
319		padded[122] = (total_len >> 37) as u8;
320		padded[123] = (total_len >> 29) as u8;
321		padded[124] = (total_len >> 21) as u8;
322		padded[125] = (total_len >> 13) as u8;
323		padded[126] = (total_len >> 5) as u8;
324		padded[127] = (total_len << 3) as u8;
325		crypto_hashblocks(h, &padded[0..128]);
326	} else {
327		padded[247] = (total_len >> 61) as u8;
328		padded[248] = (total_len >> 53) as u8;
329		padded[249] = (total_len >> 45) as u8;
330		padded[250] = (total_len >> 37) as u8;
331		padded[251] = (total_len >> 29) as u8;
332		padded[252] = (total_len >> 21) as u8;
333		padded[253] = (total_len >> 13) as u8;
334		padded[254] = (total_len >> 5) as u8;
335		padded[255] = (total_len << 3) as u8;
336		crypto_hashblocks(h, &padded);
337	}
338}
339
340pub struct Sha512 {
341	cache: [u8; 128],
342	cached_bytes: usize,
343	total_len: usize,
344	h: [u8; 64]
345}
346
347impl Sha512 {
348
349	pub fn new() -> Sha512 {
350		Sha512 {
351			cache: [0; 128],
352			h: [0; 64],
353			total_len: 0,
354			cached_bytes: 0,
355		}
356	}
357	
358	/// This absorbs given bytes, hashing even blocks, and internally caching
359	/// odd bytes to hash either with next bytes, or as padded bytes when digest
360	/// is called.
361	/// 
362	pub fn update(&mut self, m: &[u8]) {
363		let mlen = m.len();
364		if mlen == 0 { return; }
365		if self.total_len == 0 {
366			self.h.copy_from_slice(&iv);
367		}
368		self.total_len += m.len();
369		let mut m_start = 0;
370
371		if self.cached_bytes > 0 {
372			let delta = mlen.min(128-self.cached_bytes);
373			for i in 0..delta {
374				self.cache[self.cached_bytes + i] = m[i];
375			}
376			m_start = delta;
377			if (self.cached_bytes + delta) < 128 {
378				self.cached_bytes += delta;
379				return;
380			} else {
381				crypto_hashblocks(&mut self.h, &self.cache);
382				self.cached_bytes = 0;
383				if m_start == m.len() { return; }
384			}
385		}
386		
387		m_start += crypto_hashblocks(&mut self.h, &m[m_start..]);
388		
389		self.cached_bytes = mlen - m_start;
390		for i in 0..self.cached_bytes {
391			self.cache[i] = m[m_start+i];
392		}
393		self.cache[self.cached_bytes..].reset();
394	}
395
396	/// Completes hashing and returns sha512 hash bytes.
397	/// If no bytes were given to update prior to this call, panic will ensue.
398	/// 
399	pub fn digest(&mut self) -> Vec<u8> {
400		if self.total_len == 0 { panic!("No bytes have been hashed"); }
401		hash_padded_block(
402			&mut self.h, &self.cache[0..self.cached_bytes], self.total_len);
403		let v = self.h.to_vec();
404		self.clear();
405		v
406	}
407
408	/// This clears internal state of the hasher.
409	pub fn clear(&mut self) {
410		self.total_len = 0;
411		self.cached_bytes = 0;
412		self.h.reset();
413		self.cache.reset();
414	}
415}
416
417#[cfg(test)]
418mod tests {
419
420	use super::{ hash_sha512, Sha512 };
421	use crate::util::verify::compare;
422
423	// Analog of tests/hash.c, with result printed in tests/hash.out
424	//
425	#[test]
426	fn sha512() {
427		let x = "testing\n".as_bytes();
428		let mut result: [u8; 64] = [0; 64];
429		hash_sha512(&mut result, &x);
430		assert!(compare(&result, &[
431			0x24, 0xf9, 0x50, 0xaa, 0xc7, 0xb9, 0xea, 0x9b, 0x3c, 0xb7,
432			0x28, 0x22, 0x8a, 0x0c, 0x82, 0xb6, 0x7c, 0x39, 0xe9, 0x6b,
433			0x4b, 0x34, 0x47, 0x98, 0x87, 0x0d, 0x5d, 0xae, 0xe9, 0x3e,
434			0x3a, 0xe5, 0x93, 0x1b, 0xaa, 0xe8, 0xc7, 0xca, 0xcf, 0xea,
435			0x4b, 0x62, 0x94, 0x52, 0xc3, 0x80, 0x26, 0xa8, 0x1d, 0x13,
436			0x8b, 0xc7, 0xaa, 0xd1, 0xaf, 0x3e, 0xf7, 0xbf, 0xd5, 0xec,
437			0x64, 0x6d, 0x6c, 0x28 ]));
438	}
439
440	#[test]
441	fn hash_of_short_vector() {
442		let x = [
443			0x24, 0xf9, 0x50, 0xaa, 0xc7, 0xb9, 0xea, 0x9b, 0x3c, 0xb7,
444			0x28, 0x22, 0x8a, 0x0c, 0x82, 0xb6, 0x7c, 0x39, 0xe9, 0x6b,
445			0x4b, 0x34, 0x47, 0x98, 0x87, 0x0d, 0x5d, 0xae, 0xe9, 0x3e,
446			0x3a, 0xe5, 0x93 ];
447		let mut result: [u8; 64] = [0; 64];
448		hash_sha512(&mut result, &x);
449		assert!(compare(&result, &[
450			0xe3, 0x47, 0x65, 0x5d, 0x31, 0xac, 0x3b, 0xfa, 0xe1, 0xd4,
451			0x0b, 0xbd, 0x04, 0x54, 0xfd, 0x58, 0x0b, 0x5d, 0xde, 0xb3,
452			0xe7, 0x63, 0xd1, 0xd7, 0x4d, 0xc3, 0xf0, 0x1c, 0x47, 0x1e,
453			0x6f, 0x10, 0x4a, 0xa5, 0x40, 0x53, 0xef, 0xa1, 0x9b, 0xed,
454			0xd6, 0x27, 0xcd, 0x4b, 0xa1, 0xc0, 0xb4, 0x4d, 0x30, 0xe1,
455			0x4f, 0x7f, 0xc5, 0x91, 0xa0, 0x1c, 0x60, 0xd2, 0xcb, 0x6f,
456			0x45, 0x8f, 0x40, 0x8b ]));
457	}
458
459	#[test]
460	fn hasher_with_short_vector() {
461		let x = [
462			0x24, 0xf9, 0x50, 0xaa, 0xc7, 0xb9, 0xea, 0x9b, 0x3c, 0xb7,
463			0x28, 0x22, 0x8a, 0x0c, 0x82, 0xb6, 0x7c, 0x39, 0xe9, 0x6b,
464			0x4b, 0x34, 0x47, 0x98, 0x87, 0x0d, 0x5d, 0xae, 0xe9, 0x3e,
465			0x3a, 0xe5, 0x93 ];
466		let mut hasher = Sha512::new();
467		hasher.update(&x[0..10]);
468		hasher.update(&x[10..]);
469		let result = hasher.digest();
470		assert!(compare(&result, &[
471			0xe3, 0x47, 0x65, 0x5d, 0x31, 0xac, 0x3b, 0xfa, 0xe1, 0xd4,
472			0x0b, 0xbd, 0x04, 0x54, 0xfd, 0x58, 0x0b, 0x5d, 0xde, 0xb3,
473			0xe7, 0x63, 0xd1, 0xd7, 0x4d, 0xc3, 0xf0, 0x1c, 0x47, 0x1e,
474			0x6f, 0x10, 0x4a, 0xa5, 0x40, 0x53, 0xef, 0xa1, 0x9b, 0xed,
475			0xd6, 0x27, 0xcd, 0x4b, 0xa1, 0xc0, 0xb4, 0x4d, 0x30, 0xe1,
476			0x4f, 0x7f, 0xc5, 0x91, 0xa0, 0x1c, 0x60, 0xd2, 0xcb, 0x6f,
477			0x45, 0x8f, 0x40, 0x8b ]));
478	}
479
480	#[test]
481	fn hasher_with_longer_vector() {
482		let x = [
483			0x24, 0xf9, 0x50, 0xaa, 0xc7, 0xb9, 0xea, 0x9b, 0x3c, 0xb7,
484			0x28, 0x22, 0x8a, 0x0c, 0x82, 0xb6, 0x7c, 0x39, 0xe9, 0x6b,
485			0x4b, 0x34, 0x47, 0x98, 0x87, 0x0d, 0x5d, 0xae, 0xe9, 0x3e,
486			0xe3, 0x47, 0x65, 0x5d, 0x31, 0xac, 0x3b, 0xfa, 0xe1, 0xd4,
487			0x0b, 0xbd, 0x04, 0x54, 0xfd, 0x58, 0x0b, 0x5d, 0xde, 0xb3,
488			0xe7, 0x63, 0xd1, 0xd7, 0x4d, 0xc3, 0xf0, 0x1c, 0x47, 0x1e,
489			0x6f, 0x10, 0x4a, 0xa5, 0x40, 0x53, 0xef, 0xa1, 0x9b, 0xed,
490			0xd6, 0x27, 0xcd, 0x4b, 0xa1, 0xc0, 0xb4, 0x4d, 0x30, 0xe1,
491			0x4f, 0x7f, 0xc5, 0x91, 0xa0, 0x1c, 0x60, 0xd2, 0xcb, 0x6f,
492			0x6f, 0x10, 0x4a, 0xa5, 0x40, 0x53, 0xef, 0xa1, 0x9b, 0xed,
493			0xd6, 0x27, 0xcd, 0x4b, 0xa1, 0xc0, 0xb4, 0x4d, 0x30, 0xe1,
494			0x4f, 0x7f, 0xc5, 0x91, 0xa0, 0x1c, 0x60, 0xd2, 0xcb, 0x6f,
495			0x45, 0x8f, 0x40, 0x8b, 0x3a, 0xe5, 0x93, 0x93 ];
496		let mut hasher = Sha512::new();
497		hasher.update(&x[0..56]);
498		hasher.update(&x[56..]);
499		let result = hasher.digest();
500		assert!(compare(&result, &[
501			0xbd, 0xb1, 0x1, 0x77, 0x73, 0x6b, 0x2b, 0xa2, 0x64, 0xac,
502			0x73, 0x3c, 0xfe, 0xb, 0xaf, 0x21, 0x28, 0x7f, 0x41, 0xfb,
503			0xa6, 0x90, 0xe3, 0xe6, 0xe9, 0xe, 0xd7, 0x88, 0x34, 0xb7,
504			0x93, 0xfa, 0x4f, 0xd7, 0xf, 0x97, 0x4c, 0x2f, 0xa2, 0xc4,
505			0x2e, 0x59, 0x1c, 0xb7, 0xdb, 0xa5, 0x2e, 0x47, 0x17, 0x2,
506			0xd8, 0x86, 0x16, 0x3e, 0x61, 0xbf, 0x4c, 0xc, 0x58, 0xca,
507			0x35, 0x48, 0x23, 0xba ]));
508	}
509
510	#[test]
511	fn hasher_with_longer_vector2() {
512		let x = [
513			0x24, 0xf9, 0x50, 0xaa, 0xc7, 0xb9, 0xea, 0x9b, 0x3c, 0xb7,
514			0x28, 0x22, 0x8a, 0x0c, 0x82, 0xb6, 0x7c, 0x39, 0xe9, 0x6b,
515			0x4b, 0x34, 0x47, 0x98, 0x87, 0x0d, 0x5d, 0xae, 0xe9, 0x3e,
516			0xe3, 0x47, 0x65, 0x5d, 0x31, 0xac, 0x3b, 0xfa, 0xe1, 0xd4,
517			0x0b, 0xbd, 0x04, 0x54, 0xfd, 0x58, 0x0b, 0x5d, 0xde, 0xb3,
518			0xe7, 0x63, 0xd1, 0xd7, 0x4d, 0xc3, 0xf0, 0x1c, 0x47, 0x1e,
519			0x6f, 0x10, 0x4a, 0xa5, 0x40, 0x53, 0xef, 0xa1, 0x9b, 0xed,
520			0xd6, 0x27, 0xcd, 0x4b, 0xa1, 0xc0, 0xb4, 0x4d, 0x30, 0xe1,
521			0x4f, 0x7f, 0xc5, 0x91, 0xa0, 0x1c, 0x60, 0xd2, 0xcb, 0x6f,
522			0x6f, 0x10, 0x4a, 0xa5, 0x40, 0x53, 0xef, 0xa1, 0x9b, 0xed,
523			0xd6, 0x27, 0xcd, 0x4b, 0xa1, 0xc0, 0xb4, 0x4d, 0x30, 0xe1,
524			0x28, 0x22, 0x8a, 0x0c, 0x82, 0xb6, 0x7c, 0x39, 0xe9, 0x6b,
525			0x4b, 0x34, 0x47, 0x98, 0x87, 0x0d, 0x5d, 0xae, 0xe9, 0x3e,
526			0xe3, 0x47, 0x65, 0x5d, 0x31, 0xac, 0x3b, 0xfa, 0xe1, 0xd4,
527			0x0b, 0xbd, 0x04, 0x54, 0xfd, 0x58, 0x0b, 0x5d, 0xde, 0xb3,
528			0xe7, 0x63, 0xd1, 0xd7, 0x4d, 0xc3, 0xf0, 0x1c, 0x47, 0x1e,
529			0x6f, 0x10, 0x4a, 0xa5, 0x40, 0x53, 0xef, 0xa1, 0x9b, 0xed,
530			0xd6, 0x27, 0xcd, 0x4b, 0xa1, 0xc0, 0xb4, 0x4d, 0x30, 0xe1,
531			0x4f, 0x7f, 0xc5, 0x91, 0xa0, 0x1c, 0x60, 0xd2, 0xcb, 0x6f,
532			0x6f, 0x10, 0x4a, 0xa5, 0x40, 0x53, 0xef, 0xa1, 0x9b, 0xed,
533			0x4f, 0x7f, 0xc5, 0x91, 0xa0, 0x1c, 0x60, 0xd2, 0xcb, 0x6f,
534			0x45, 0x8f, 0x40 ];
535		let mut hasher = Sha512::new();
536		hasher.update(&x[0..10]);
537		hasher.update(&x[10..20]);
538		hasher.update(&x[20..]);
539		let result = hasher.digest();
540		assert!(compare(&result, &[
541			0x2a, 0x68, 0x28, 0x7b, 0x3e, 0xb6, 0x7d, 0xa1, 0x5d, 0xf1,
542			0x84, 0x37, 0xca, 0x1e, 0xce, 0x6a, 0x75, 0xe9, 0x2d, 0x60,
543			0x11, 0x3e, 0x48, 0xba, 0x6c, 0x69, 0x9f, 0x7d, 0x76, 0xea,
544			0x6d, 0xef, 0xe5, 0x92, 0xb8, 0x41, 0x8d, 0x10, 0xff, 0xe5,
545			0x6d, 0x74, 0x6d, 0x2c, 0x2e, 0x67, 0xdc, 0x6d, 0x99, 0x3b,
546			0x7b, 0x27, 0xc2, 0xbd, 0x29, 0x62, 0xe7, 0x67, 0x01, 0xd6,
547			0x26, 0xa6, 0x9c, 0x0f ]));
548	}
549
550}