1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 /*!
12 An implementation of the SHA-1 cryptographic hash algorithm.
13
14 To use this module, first create a `Sha1` object using the `Sha1` constructor,
15 then feed it an input message using the `input` or `input_str` methods,
16 which may be called any number of times; they will buffer the input until
17 there is enough to call the block algorithm.
18
19 After the entire input has been fed to the hash read the result using
20 the `result` or `result_str` methods. The first will return bytes, and
21 the second will return a `String` object of the same bytes represented
22 in hexadecimal form.
23
24 The `Sha1` object may be reused to create multiple hashes by calling
25 the `reset()` method. These traits are implemented by all hash digest
26 algorithms that implement the `Digest` trait. An example of use is:
27
28 ```rust
29 use self::crypto::digest::Digest;
30 use self::crypto::sha1::Sha1;
31
32 // create a Sha1 object
33 let mut hasher = Sha1::new();
34
35 // write input message
36 hasher.input_str("hello world");
37
38 // read hash digest
39 let hex = hasher.result_str();
40
41 assert_eq!(hex, "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed");
42 ```
43
44 # Mathematics
45
46 The mathematics of the SHA-1 algorithm are quite interesting. In its
47 definition, The SHA-1 algorithm uses:
48
49 * 1 binary operation on bit-arrays:
50 * "exclusive or" (XOR)
51 * 2 binary operations on integers:
52 * "addition" (ADD)
53 * "rotate left" (ROL)
54 * 3 ternary operations on bit-arrays:
55 * "choose" (CH)
56 * "parity" (PAR)
57 * "majority" (MAJ)
58
59 Some of these functions are commonly found in all hash digest
60 algorithms, but some, like "parity" is only found in SHA-1.
61 */
62
63 use digest::Digest;
64 use cryptoutil::{write_u32_be, read_u32v_be, add_bytes_to_bits, FixedBuffer, FixedBuffer64, StandardPadding};
65 use simd::u32x4;
66
67 const STATE_LEN: usize = 5;
68 const BLOCK_LEN: usize = 16;
69
70 const K0: u32 = 0x5A827999u32;
71 const K1: u32 = 0x6ED9EBA1u32;
72 const K2: u32 = 0x8F1BBCDCu32;
73 const K3: u32 = 0xCA62C1D6u32;
74
75 /// Not an intrinsic, but gets the first element of a vector.
76 #[inline]
sha1_first(w0: u32x4) -> u3277 pub fn sha1_first(w0: u32x4) -> u32 {
78 w0.0
79 }
80
81 /// Not an intrinsic, but adds a word to the first element of a vector.
82 #[inline]
sha1_first_add(e: u32, w0: u32x4) -> u32x483 pub fn sha1_first_add(e: u32, w0: u32x4) -> u32x4 {
84 let u32x4(a, b, c, d) = w0;
85 u32x4(e.wrapping_add(a), b, c, d)
86 }
87
88 /// Emulates `llvm.x86.sha1msg1` intrinsic.
sha1msg1(a: u32x4, b: u32x4) -> u32x489 fn sha1msg1(a: u32x4, b: u32x4) -> u32x4 {
90 let u32x4(_, _, w2, w3) = a;
91 let u32x4(w4, w5, _, _) = b;
92 a ^ u32x4(w2, w3, w4, w5)
93 }
94
95 /// Emulates `llvm.x86.sha1msg2` intrinsic.
sha1msg2(a: u32x4, b: u32x4) -> u32x496 fn sha1msg2(a: u32x4, b: u32x4) -> u32x4 {
97 let u32x4(x0, x1, x2, x3) = a;
98 let u32x4(_, w13, w14, w15) = b;
99
100 let w16 = (x0 ^ w13).rotate_left(1);
101 let w17 = (x1 ^ w14).rotate_left(1);
102 let w18 = (x2 ^ w15).rotate_left(1);
103 let w19 = (x3 ^ w16).rotate_left(1);
104
105 u32x4(w16, w17, w18, w19)
106 }
107
108 /// Performs 4 rounds of the message schedule update.
sha1_schedule_x4(v0: u32x4, v1: u32x4, v2: u32x4, v3: u32x4) -> u32x4109 pub fn sha1_schedule_x4(v0: u32x4, v1: u32x4, v2: u32x4, v3: u32x4) -> u32x4 {
110 sha1msg2(sha1msg1(v0, v1) ^ v2, v3)
111 }
112
113 /// Emulates `llvm.x86.sha1nexte` intrinsic.
114 #[inline]
sha1_first_half(abcd: u32x4, msg: u32x4) -> u32x4115 pub fn sha1_first_half(abcd: u32x4, msg: u32x4) -> u32x4 {
116 sha1_first_add(sha1_first(abcd).rotate_left(30), msg)
117 }
118
119 /// Emulates `llvm.x86.sha1rnds4` intrinsic.
120 /// Performs 4 rounds of the message block digest.
sha1_digest_round_x4(abcd: u32x4, work: u32x4, i: i8) -> u32x4121 pub fn sha1_digest_round_x4(abcd: u32x4, work: u32x4, i: i8) -> u32x4 {
122 const K0V: u32x4 = u32x4(K0, K0, K0, K0);
123 const K1V: u32x4 = u32x4(K1, K1, K1, K1);
124 const K2V: u32x4 = u32x4(K2, K2, K2, K2);
125 const K3V: u32x4 = u32x4(K3, K3, K3, K3);
126
127 match i {
128 0 => sha1rnds4c(abcd, work + K0V),
129 1 => sha1rnds4p(abcd, work + K1V),
130 2 => sha1rnds4m(abcd, work + K2V),
131 3 => sha1rnds4p(abcd, work + K3V),
132 _ => panic!("unknown icosaround index")
133 }
134 }
135
136 /// Not an intrinsic, but helps emulate `llvm.x86.sha1rnds4` intrinsic.
sha1rnds4c(abcd: u32x4, msg: u32x4) -> u32x4137 fn sha1rnds4c(abcd: u32x4, msg: u32x4) -> u32x4 {
138 let u32x4(mut a, mut b, mut c, mut d) = abcd;
139 let u32x4(t, u, v, w) = msg;
140 let mut e = 0u32;
141
142 macro_rules! bool3ary_202 {
143 ($a:expr, $b:expr, $c:expr) => (($c ^ ($a & ($b ^ $c))))
144 } // Choose, MD5F, SHA1C
145
146 e = e.wrapping_add(a.rotate_left(5)).wrapping_add(bool3ary_202!(b, c, d)).wrapping_add(t);
147 b = b.rotate_left(30);
148
149 d = d.wrapping_add(e.rotate_left(5)).wrapping_add(bool3ary_202!(a, b, c)).wrapping_add(u);
150 a = a.rotate_left(30);
151
152 c = c.wrapping_add(d.rotate_left(5)).wrapping_add(bool3ary_202!(e, a, b)).wrapping_add(v);
153 e = e.rotate_left(30);
154
155 b = b.wrapping_add(c.rotate_left(5)).wrapping_add(bool3ary_202!(d, e, a)).wrapping_add(w);
156 d = d.rotate_left(30);
157
158 u32x4(b, c, d, e)
159 }
160
161 /// Not an intrinsic, but helps emulate `llvm.x86.sha1rnds4` intrinsic.
sha1rnds4p(abcd: u32x4, msg: u32x4) -> u32x4162 fn sha1rnds4p(abcd: u32x4, msg: u32x4) -> u32x4 {
163 let u32x4(mut a, mut b, mut c, mut d) = abcd;
164 let u32x4(t, u, v, w) = msg;
165 let mut e = 0u32;
166
167 macro_rules! bool3ary_150 {
168 ($a:expr, $b:expr, $c:expr) => (($a ^ $b ^ $c))
169 } // Parity, XOR, MD5H, SHA1P
170
171 e = e.wrapping_add(a.rotate_left(5)).wrapping_add(bool3ary_150!(b, c, d)).wrapping_add(t);
172 b = b.rotate_left(30);
173
174 d = d.wrapping_add(e.rotate_left(5)).wrapping_add(bool3ary_150!(a, b, c)).wrapping_add(u);
175 a = a.rotate_left(30);
176
177 c = c.wrapping_add(d.rotate_left(5)).wrapping_add(bool3ary_150!(e, a, b)).wrapping_add(v);
178 e = e.rotate_left(30);
179
180 b = b.wrapping_add(c.rotate_left(5)).wrapping_add(bool3ary_150!(d, e, a)).wrapping_add(w);
181 d = d.rotate_left(30);
182
183 u32x4(b, c, d, e)
184 }
185
186 /// Not an intrinsic, but helps emulate `llvm.x86.sha1rnds4` intrinsic.
sha1rnds4m(abcd: u32x4, msg: u32x4) -> u32x4187 fn sha1rnds4m(abcd: u32x4, msg: u32x4) -> u32x4 {
188 let u32x4(mut a, mut b, mut c, mut d) = abcd;
189 let u32x4(t, u, v, w) = msg;
190 let mut e = 0u32;
191
192 macro_rules! bool3ary_232 {
193 ($a:expr, $b:expr, $c:expr) => (($a & $b) ^ ($a & $c) ^ ($b & $c))
194 } // Majority, SHA1M
195
196 e = e.wrapping_add(a.rotate_left(5)).wrapping_add(bool3ary_232!(b, c, d)).wrapping_add(t);
197 b = b.rotate_left(30);
198
199 d = d.wrapping_add(e.rotate_left(5)).wrapping_add(bool3ary_232!(a, b, c)).wrapping_add(u);
200 a = a.rotate_left(30);
201
202 c = c.wrapping_add(d.rotate_left(5)).wrapping_add(bool3ary_232!(e, a, b)).wrapping_add(v);
203 e = e.rotate_left(30);
204
205 b = b.wrapping_add(c.rotate_left(5)).wrapping_add(bool3ary_232!(d, e, a)).wrapping_add(w);
206 d = d.rotate_left(30);
207
208 u32x4(b, c, d, e)
209 }
210
211 /// Process a block with the SHA-1 algorithm.
sha1_digest_block_u32(state: &mut [u32; 5], block: &[u32; 16])212 pub fn sha1_digest_block_u32(state: &mut [u32; 5], block: &[u32; 16]) {
213
214 macro_rules! schedule {
215 ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => (
216 sha1msg2(sha1msg1($v0, $v1) ^ $v2, $v3)
217 )
218 }
219
220 macro_rules! rounds4 {
221 ($h0:ident, $h1:ident, $wk:expr, $i:expr) => (
222 sha1_digest_round_x4($h0, sha1_first_half($h1, $wk), $i)
223 )
224 }
225
226 // Rounds 0..20
227 let mut h0 = u32x4(state[0],
228 state[1],
229 state[2],
230 state[3]);
231 let mut w0 = u32x4(block[0],
232 block[1],
233 block[2],
234 block[3]);
235 let mut h1 = sha1_digest_round_x4(h0, sha1_first_add(state[4], w0), 0);
236 let mut w1 = u32x4(block[4],
237 block[5],
238 block[6],
239 block[7]);
240 h0 = rounds4!(h1, h0, w1, 0);
241 let mut w2 = u32x4(block[8],
242 block[9],
243 block[10],
244 block[11]);
245 h1 = rounds4!(h0, h1, w2, 0);
246 let mut w3 = u32x4(block[12],
247 block[13],
248 block[14],
249 block[15]);
250 h0 = rounds4!(h1, h0, w3, 0);
251 let mut w4 = schedule!(w0, w1, w2, w3);
252 h1 = rounds4!(h0, h1, w4, 0);
253
254 // Rounds 20..40
255 w0 = schedule!(w1, w2, w3, w4);
256 h0 = rounds4!(h1, h0, w0, 1);
257 w1 = schedule!(w2, w3, w4, w0);
258 h1 = rounds4!(h0, h1, w1, 1);
259 w2 = schedule!(w3, w4, w0, w1);
260 h0 = rounds4!(h1, h0, w2, 1);
261 w3 = schedule!(w4, w0, w1, w2);
262 h1 = rounds4!(h0, h1, w3, 1);
263 w4 = schedule!(w0, w1, w2, w3);
264 h0 = rounds4!(h1, h0, w4, 1);
265
266 // Rounds 40..60
267 w0 = schedule!(w1, w2, w3, w4);
268 h1 = rounds4!(h0, h1, w0, 2);
269 w1 = schedule!(w2, w3, w4, w0);
270 h0 = rounds4!(h1, h0, w1, 2);
271 w2 = schedule!(w3, w4, w0, w1);
272 h1 = rounds4!(h0, h1, w2, 2);
273 w3 = schedule!(w4, w0, w1, w2);
274 h0 = rounds4!(h1, h0, w3, 2);
275 w4 = schedule!(w0, w1, w2, w3);
276 h1 = rounds4!(h0, h1, w4, 2);
277
278 // Rounds 60..80
279 w0 = schedule!(w1, w2, w3, w4);
280 h0 = rounds4!(h1, h0, w0, 3);
281 w1 = schedule!(w2, w3, w4, w0);
282 h1 = rounds4!(h0, h1, w1, 3);
283 w2 = schedule!(w3, w4, w0, w1);
284 h0 = rounds4!(h1, h0, w2, 3);
285 w3 = schedule!(w4, w0, w1, w2);
286 h1 = rounds4!(h0, h1, w3, 3);
287 w4 = schedule!(w0, w1, w2, w3);
288 h0 = rounds4!(h1, h0, w4, 3);
289
290 let e = sha1_first(h1).rotate_left(30);
291 let u32x4(a, b, c, d) = h0;
292
293 state[0] = state[0].wrapping_add(a);
294 state[1] = state[1].wrapping_add(b);
295 state[2] = state[2].wrapping_add(c);
296 state[3] = state[3].wrapping_add(d);
297 state[4] = state[4].wrapping_add(e);
298 }
299
300 /// Process a block with the SHA-1 algorithm. (See more...)
301 ///
302 /// SHA-1 is a cryptographic hash function, and as such, it operates
303 /// on an arbitrary number of bytes. This function operates on a fixed
304 /// number of bytes. If you call this function with anything other than
305 /// 64 bytes, then it will panic! This function takes two arguments:
306 ///
307 /// * `state` is reference to an **array** of 5 words.
308 /// * `block` is reference to a **slice** of 64 bytes.
309 ///
310 /// If you want the function that performs a message digest on an arbitrary
311 /// number of bytes, then see also the `Sha1` struct above.
312 ///
313 /// # Implementation
314 ///
315 /// First, some background. Both ARM and Intel are releasing documentation
316 /// that they plan to include instruction set extensions for SHA1 and SHA256
317 /// sometime in the near future. Second, LLVM won't lower these intrinsics yet,
318 /// so these functions were written emulate these instructions. Finally,
319 /// the block function implemented with these emulated intrinsics turned out
320 /// to be quite fast! What follows is a discussion of this CPU-level view
321 /// of the SHA-1 algorithm and how it relates to the mathematical definition.
322 ///
323 /// The SHA instruction set extensions can be divided up into two categories:
324 ///
325 /// * message work schedule update calculation ("schedule" v., "work" n.)
326 /// * message block 80-round digest calculation ("digest" v., "block" n.)
327 ///
328 /// The schedule-related functions can be used to easily perform 4 rounds
329 /// of the message work schedule update calculation, as shown below:
330 ///
331 /// ```ignore
332 /// macro_rules! schedule_x4 {
333 /// ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => (
334 /// sha1msg2(sha1msg1($v0, $v1) ^ $v2, $v3)
335 /// )
336 /// }
337 ///
338 /// macro_rules! round_x4 {
339 /// ($h0:ident, $h1:ident, $wk:expr, $i:expr) => (
340 /// sha1rnds4($h0, sha1_first_half($h1, $wk), $i)
341 /// )
342 /// }
343 /// ```
344 ///
345 /// and also shown above is how the digest-related functions can be used to
346 /// perform 4 rounds of the message block digest calculation.
347 ///
sha1_digest_block(state: &mut [u32; 5], block: &[u8 ])348 pub fn sha1_digest_block(state: &mut [u32; 5], block: &[u8/*; 64*/]) {
349 assert_eq!(block.len(), BLOCK_LEN*4);
350 let mut block2 = [0u32; BLOCK_LEN];
351 read_u32v_be(&mut block2[..], block);
352 sha1_digest_block_u32(state, &block2);
353 }
354
add_input(st: &mut Sha1, msg: &[u8])355 fn add_input(st: &mut Sha1, msg: &[u8]) {
356 assert!((!st.computed));
357 // Assumes that msg.len() can be converted to u64 without overflow
358 st.length_bits = add_bytes_to_bits(st.length_bits, msg.len() as u64);
359 let st_h = &mut st.h;
360 st.buffer.input(msg, |d: &[u8]| { sha1_digest_block(st_h, d); });
361 }
362
mk_result(st: &mut Sha1, rs: &mut [u8])363 fn mk_result(st: &mut Sha1, rs: &mut [u8]) {
364 if !st.computed {
365 let st_h = &mut st.h;
366 st.buffer.standard_padding(8, |d: &[u8]| { sha1_digest_block(&mut *st_h, d) });
367 write_u32_be(st.buffer.next(4), (st.length_bits >> 32) as u32 );
368 write_u32_be(st.buffer.next(4), st.length_bits as u32);
369 sha1_digest_block(st_h, st.buffer.full_buffer());
370
371 st.computed = true;
372 }
373
374 write_u32_be(&mut rs[0..4], st.h[0]);
375 write_u32_be(&mut rs[4..8], st.h[1]);
376 write_u32_be(&mut rs[8..12], st.h[2]);
377 write_u32_be(&mut rs[12..16], st.h[3]);
378 write_u32_be(&mut rs[16..20], st.h[4]);
379 }
380
381 /// Structure representing the state of a Sha1 computation
382 #[derive(Clone, Copy)]
383 pub struct Sha1 {
384 h: [u32; STATE_LEN],
385 length_bits: u64,
386 buffer: FixedBuffer64,
387 computed: bool,
388 }
389
390 impl Sha1 {
391 /// Construct a `sha` object
new() -> Sha1392 pub fn new() -> Sha1 {
393 let mut st = Sha1 {
394 h: [0u32; STATE_LEN],
395 length_bits: 0u64,
396 buffer: FixedBuffer64::new(),
397 computed: false,
398 };
399 st.reset();
400 st
401 }
402 }
403
404 impl Digest for Sha1 {
reset(&mut self)405 fn reset(&mut self) {
406 self.length_bits = 0;
407 self.h[0] = 0x67452301u32;
408 self.h[1] = 0xEFCDAB89u32;
409 self.h[2] = 0x98BADCFEu32;
410 self.h[3] = 0x10325476u32;
411 self.h[4] = 0xC3D2E1F0u32;
412 self.buffer.reset();
413 self.computed = false;
414 }
input(&mut self, msg: &[u8])415 fn input(&mut self, msg: &[u8]) { add_input(self, msg); }
result(&mut self, out: &mut [u8])416 fn result(&mut self, out: &mut [u8]) { mk_result(self, out) }
output_bits(&self) -> usize417 fn output_bits(&self) -> usize { 160 }
block_size(&self) -> usize418 fn block_size(&self) -> usize { 64 }
419 }
420
421 #[cfg(test)]
422 mod tests {
423 use cryptoutil::test::test_digest_1million_random;
424 use digest::Digest;
425 use sha1::Sha1;
426
427 #[derive(Clone)]
428 struct Test {
429 input: &'static str,
430 output: Vec<u8>,
431 output_str: &'static str,
432 }
433
434 #[test]
test()435 fn test() {
436 let tests = vec![
437 // Test messages from FIPS 180-1
438 Test {
439 input: "abc",
440 output: vec![
441 0xA9u8, 0x99u8, 0x3Eu8, 0x36u8,
442 0x47u8, 0x06u8, 0x81u8, 0x6Au8,
443 0xBAu8, 0x3Eu8, 0x25u8, 0x71u8,
444 0x78u8, 0x50u8, 0xC2u8, 0x6Cu8,
445 0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8,
446 ],
447 output_str: "a9993e364706816aba3e25717850c26c9cd0d89d"
448 },
449 Test {
450 input:
451 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
452 output: vec![
453 0x84u8, 0x98u8, 0x3Eu8, 0x44u8,
454 0x1Cu8, 0x3Bu8, 0xD2u8, 0x6Eu8,
455 0xBAu8, 0xAEu8, 0x4Au8, 0xA1u8,
456 0xF9u8, 0x51u8, 0x29u8, 0xE5u8,
457 0xE5u8, 0x46u8, 0x70u8, 0xF1u8,
458 ],
459 output_str: "84983e441c3bd26ebaae4aa1f95129e5e54670f1"
460 },
461 // Examples from wikipedia
462 Test {
463 input: "The quick brown fox jumps over the lazy dog",
464 output: vec![
465 0x2fu8, 0xd4u8, 0xe1u8, 0xc6u8,
466 0x7au8, 0x2du8, 0x28u8, 0xfcu8,
467 0xedu8, 0x84u8, 0x9eu8, 0xe1u8,
468 0xbbu8, 0x76u8, 0xe7u8, 0x39u8,
469 0x1bu8, 0x93u8, 0xebu8, 0x12u8,
470 ],
471 output_str: "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12",
472 },
473 Test {
474 input: "The quick brown fox jumps over the lazy cog",
475 output: vec![
476 0xdeu8, 0x9fu8, 0x2cu8, 0x7fu8,
477 0xd2u8, 0x5eu8, 0x1bu8, 0x3au8,
478 0xfau8, 0xd3u8, 0xe8u8, 0x5au8,
479 0x0bu8, 0xd1u8, 0x7du8, 0x9bu8,
480 0x10u8, 0x0du8, 0xb4u8, 0xb3u8,
481 ],
482 output_str: "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3",
483 },
484 ];
485
486 // Test that it works when accepting the message all at once
487
488 let mut out = [0u8; 20];
489
490 let mut sh = Box::new(Sha1::new());
491 for t in tests.iter() {
492 (*sh).input_str(t.input);
493 sh.result(&mut out);
494 assert!(t.output[..] == out[..]);
495
496 let out_str = (*sh).result_str();
497 assert_eq!(out_str.len(), 40);
498 assert!(&out_str[..] == t.output_str);
499
500 sh.reset();
501 }
502
503
504 // Test that it works when accepting the message in pieces
505 for t in tests.iter() {
506 let len = t.input.len();
507 let mut left = len;
508 while left > 0 {
509 let take = (left + 1) / 2;
510 (*sh).input_str(&t.input[len - left..take + len - left]);
511 left = left - take;
512 }
513 sh.result(&mut out);
514 assert!(t.output[..] == out[..]);
515
516 let out_str = (*sh).result_str();
517 assert_eq!(out_str.len(), 40);
518 assert!(&out_str[..] == t.output_str);
519
520 sh.reset();
521 }
522 }
523
524 #[test]
test_1million_random_sha1()525 fn test_1million_random_sha1() {
526 let mut sh = Sha1::new();
527 test_digest_1million_random(
528 &mut sh,
529 64,
530 "34aa973cd4c4daa4f61eeb2bdbad27316534016f");
531 }
532 }
533
534 #[cfg(all(test, feature = "with-bench"))]
535 mod bench {
536 use test::Bencher;
537 use digest::Digest;
538 use sha1::{STATE_LEN, BLOCK_LEN};
539 use sha1::{Sha1, sha1_digest_block_u32};
540
541 #[bench]
sha1_block(bh: & mut Bencher)542 pub fn sha1_block(bh: & mut Bencher) {
543 let mut state = [0u32; STATE_LEN];
544 let words = [1u32; BLOCK_LEN];
545 bh.iter( || {
546 sha1_digest_block_u32(&mut state, &words);
547 });
548 bh.bytes = 64u64;
549 }
550
551 #[bench]
sha1_10(bh: & mut Bencher)552 pub fn sha1_10(bh: & mut Bencher) {
553 let mut sh = Sha1::new();
554 let bytes = [1u8; 10];
555 bh.iter( || {
556 sh.input(&bytes);
557 });
558 bh.bytes = bytes.len() as u64;
559 }
560
561 #[bench]
sha1_1k(bh: & mut Bencher)562 pub fn sha1_1k(bh: & mut Bencher) {
563 let mut sh = Sha1::new();
564 let bytes = [1u8; 1024];
565 bh.iter( || {
566 sh.input(&bytes);
567 });
568 bh.bytes = bytes.len() as u64;
569 }
570
571 #[bench]
sha1_64k(bh: & mut Bencher)572 pub fn sha1_64k(bh: & mut Bencher) {
573 let mut sh = Sha1::new();
574 let bytes = [1u8; 65536];
575 bh.iter( || {
576 sh.input(&bytes);
577 });
578 bh.bytes = bytes.len() as u64;
579 }
580
581 }
582