2012-12-03 18:48:01 -06:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/*!
|
|
|
|
* An implementation of the SHA-1 cryptographic hash.
|
|
|
|
*
|
|
|
|
* First create a `sha1` object using the `sha1` constructor, then
|
|
|
|
* feed it input using the `input` or `input_str` methods, which may be
|
|
|
|
* called any number of times.
|
|
|
|
*
|
|
|
|
* After the entire input has been fed to the hash read the result using
|
|
|
|
* the `result` or `result_str` methods.
|
|
|
|
*
|
|
|
|
* The `sha1` object may be reused to create multiple hashes by calling
|
|
|
|
* the `reset` method.
|
|
|
|
*/
|
2011-10-26 18:24:31 -05:00
|
|
|
|
2012-12-23 16:41:37 -06:00
|
|
|
use core::str;
|
|
|
|
use core::uint;
|
|
|
|
use core::vec;
|
|
|
|
|
2011-02-20 23:56:09 -06:00
|
|
|
/*
|
|
|
|
* A SHA-1 implementation derived from Paul E. Jones's reference
|
|
|
|
* implementation, which is written for clarity, not speed. At some
|
|
|
|
* point this will want to be rewritten.
|
|
|
|
*/
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// The SHA-1 interface
|
2012-08-29 18:09:41 -05:00
|
|
|
trait Sha1 {
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Provide message input as bytes
|
2013-02-12 17:34:48 -06:00
|
|
|
fn input(&mut self, &[const u8]);
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Provide message input as string
|
2013-02-12 17:34:48 -06:00
|
|
|
fn input_str(&mut self, &str);
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Read the digest as a vector of 20 bytes. After calling this no further
|
|
|
|
* input may be provided until reset is called.
|
|
|
|
*/
|
2013-02-12 17:34:48 -06:00
|
|
|
fn result(&mut self) -> ~[u8];
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Read the digest as a hex string. After calling this no further
|
|
|
|
* input may be provided until reset is called.
|
|
|
|
*/
|
2013-02-12 17:34:48 -06:00
|
|
|
fn result_str(&mut self) -> ~str;
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Reset the SHA-1 state for reuse
|
2013-02-12 17:34:48 -06:00
|
|
|
fn reset(&mut self);
|
2012-01-11 05:54:39 -06:00
|
|
|
}
|
2011-10-26 18:24:31 -05:00
|
|
|
|
2011-02-20 23:56:09 -06:00
|
|
|
// Some unexported constants
|
2011-07-27 07:19:39 -05:00
|
|
|
const digest_buf_len: uint = 5u;
|
|
|
|
const msg_block_len: uint = 64u;
|
|
|
|
const work_buf_len: uint = 80u;
|
|
|
|
const k0: u32 = 0x5A827999u32;
|
|
|
|
const k1: u32 = 0x6ED9EBA1u32;
|
|
|
|
const k2: u32 = 0x8F1BBCDCu32;
|
|
|
|
const k3: u32 = 0xCA62C1D6u32;
|
2011-05-11 00:02:27 -05:00
|
|
|
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Construct a `sha` object
|
2012-09-27 20:03:00 -05:00
|
|
|
pub fn sha1() -> Sha1 {
|
2013-02-04 18:48:52 -06:00
|
|
|
struct Sha1State
|
2013-02-12 17:34:48 -06:00
|
|
|
{ h: ~[u32],
|
|
|
|
len_low: u32,
|
|
|
|
len_high: u32,
|
|
|
|
msg_block: ~[u8],
|
|
|
|
msg_block_idx: uint,
|
|
|
|
computed: bool,
|
|
|
|
work_buf: @mut ~[u32]};
|
2011-07-27 07:19:39 -05:00
|
|
|
|
2013-02-12 17:34:48 -06:00
|
|
|
fn add_input(st: &mut Sha1State, msg: &[const u8]) {
|
2011-06-15 13:19:50 -05:00
|
|
|
assert (!st.computed);
|
2013-01-01 23:13:33 -06:00
|
|
|
for vec::each_const(msg) |element| {
|
2012-09-18 23:41:37 -05:00
|
|
|
st.msg_block[st.msg_block_idx] = *element;
|
2011-02-20 23:56:09 -06:00
|
|
|
st.msg_block_idx += 1u;
|
|
|
|
st.len_low += 8u32;
|
2011-07-27 07:19:39 -05:00
|
|
|
if st.len_low == 0u32 {
|
2011-02-20 23:56:09 -06:00
|
|
|
st.len_high += 1u32;
|
2011-07-27 07:19:39 -05:00
|
|
|
if st.len_high == 0u32 {
|
2012-05-03 17:36:47 -05:00
|
|
|
// FIXME: Need better failure mode (#2346)
|
2013-02-11 21:26:38 -06:00
|
|
|
fail!();
|
2011-02-20 23:56:09 -06:00
|
|
|
}
|
|
|
|
}
|
2011-07-27 07:19:39 -05:00
|
|
|
if st.msg_block_idx == msg_block_len { process_msg_block(st); }
|
2011-02-20 23:56:09 -06:00
|
|
|
}
|
|
|
|
}
|
2013-02-12 17:34:48 -06:00
|
|
|
fn process_msg_block(st: &mut Sha1State) {
|
2011-08-15 18:38:23 -05:00
|
|
|
assert (vec::len(st.h) == digest_buf_len);
|
2012-05-24 16:49:39 -05:00
|
|
|
assert (vec::len(*st.work_buf) == work_buf_len);
|
2012-03-14 13:03:56 -05:00
|
|
|
let mut t: int; // Loop counter
|
2013-02-12 17:34:48 -06:00
|
|
|
let mut w = st.work_buf;
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-08-23 15:22:44 -05:00
|
|
|
// Initialize the first 16 words of the vector w
|
2011-02-20 23:56:09 -06:00
|
|
|
t = 0;
|
2011-07-27 07:19:39 -05:00
|
|
|
while t < 16 {
|
2012-03-14 13:03:56 -05:00
|
|
|
let mut tmp;
|
2011-08-19 17:16:48 -05:00
|
|
|
tmp = (st.msg_block[t * 4] as u32) << 24u32;
|
|
|
|
tmp = tmp | (st.msg_block[t * 4 + 1] as u32) << 16u32;
|
|
|
|
tmp = tmp | (st.msg_block[t * 4 + 2] as u32) << 8u32;
|
|
|
|
tmp = tmp | (st.msg_block[t * 4 + 3] as u32);
|
|
|
|
w[t] = tmp;
|
2011-02-20 23:56:09 -06:00
|
|
|
t += 1;
|
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-08-23 15:22:44 -05:00
|
|
|
// Initialize the rest of vector w
|
2011-07-27 07:19:39 -05:00
|
|
|
while t < 80 {
|
2011-08-19 17:16:48 -05:00
|
|
|
let val = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16];
|
|
|
|
w[t] = circular_shift(1u32, val);
|
2011-02-20 23:56:09 -06:00
|
|
|
t += 1;
|
|
|
|
}
|
2012-03-14 13:03:56 -05:00
|
|
|
let mut a = st.h[0];
|
|
|
|
let mut b = st.h[1];
|
|
|
|
let mut c = st.h[2];
|
|
|
|
let mut d = st.h[3];
|
|
|
|
let mut e = st.h[4];
|
|
|
|
let mut temp: u32;
|
2011-02-20 23:56:09 -06:00
|
|
|
t = 0;
|
2011-07-27 07:19:39 -05:00
|
|
|
while t < 20 {
|
2011-08-19 17:16:48 -05:00
|
|
|
temp = circular_shift(5u32, a) + (b & c | !b & d) + e + w[t] + k0;
|
2011-02-20 23:56:09 -06:00
|
|
|
e = d;
|
|
|
|
d = c;
|
|
|
|
c = circular_shift(30u32, b);
|
|
|
|
b = a;
|
|
|
|
a = temp;
|
|
|
|
t += 1;
|
|
|
|
}
|
2011-07-27 07:19:39 -05:00
|
|
|
while t < 40 {
|
2011-08-19 17:16:48 -05:00
|
|
|
temp = circular_shift(5u32, a) + (b ^ c ^ d) + e + w[t] + k1;
|
2011-02-20 23:56:09 -06:00
|
|
|
e = d;
|
|
|
|
d = c;
|
|
|
|
c = circular_shift(30u32, b);
|
|
|
|
b = a;
|
|
|
|
a = temp;
|
|
|
|
t += 1;
|
|
|
|
}
|
2011-07-27 07:19:39 -05:00
|
|
|
while t < 60 {
|
2011-06-15 13:19:50 -05:00
|
|
|
temp =
|
2011-08-19 17:16:48 -05:00
|
|
|
circular_shift(5u32, a) + (b & c | b & d | c & d) + e + w[t] +
|
|
|
|
k2;
|
2011-02-20 23:56:09 -06:00
|
|
|
e = d;
|
|
|
|
d = c;
|
|
|
|
c = circular_shift(30u32, b);
|
|
|
|
b = a;
|
|
|
|
a = temp;
|
|
|
|
t += 1;
|
|
|
|
}
|
2011-07-27 07:19:39 -05:00
|
|
|
while t < 80 {
|
2011-08-19 17:16:48 -05:00
|
|
|
temp = circular_shift(5u32, a) + (b ^ c ^ d) + e + w[t] + k3;
|
2011-02-20 23:56:09 -06:00
|
|
|
e = d;
|
|
|
|
d = c;
|
|
|
|
c = circular_shift(30u32, b);
|
|
|
|
b = a;
|
|
|
|
a = temp;
|
|
|
|
t += 1;
|
|
|
|
}
|
2011-08-19 17:16:48 -05:00
|
|
|
st.h[0] = st.h[0] + a;
|
|
|
|
st.h[1] = st.h[1] + b;
|
|
|
|
st.h[2] = st.h[2] + c;
|
|
|
|
st.h[3] = st.h[3] + d;
|
|
|
|
st.h[4] = st.h[4] + e;
|
2011-02-20 23:56:09 -06:00
|
|
|
st.msg_block_idx = 0u;
|
|
|
|
}
|
2011-07-27 07:19:39 -05:00
|
|
|
fn circular_shift(bits: u32, word: u32) -> u32 {
|
2012-08-01 19:30:05 -05:00
|
|
|
return word << bits | word >> 32u32 - bits;
|
2011-02-20 23:56:09 -06:00
|
|
|
}
|
2013-02-12 17:34:48 -06:00
|
|
|
fn mk_result(st: &mut Sha1State) -> ~[u8] {
|
2012-08-25 17:10:25 -05:00
|
|
|
if !(*st).computed { pad_msg(st); (*st).computed = true; }
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut rs: ~[u8] = ~[];
|
2012-09-18 23:41:37 -05:00
|
|
|
for vec::each_mut((*st).h) |ptr_hpart| {
|
2012-08-23 16:46:59 -05:00
|
|
|
let hpart = *ptr_hpart;
|
2012-02-09 04:50:54 -06:00
|
|
|
let a = (hpart >> 24u32 & 0xFFu32) as u8;
|
|
|
|
let b = (hpart >> 16u32 & 0xFFu32) as u8;
|
|
|
|
let c = (hpart >> 8u32 & 0xFFu32) as u8;
|
|
|
|
let d = (hpart & 0xFFu32) as u8;
|
2012-06-29 18:26:56 -05:00
|
|
|
rs = vec::append(rs, ~[a, b, c, d]);
|
2011-02-20 23:56:09 -06:00
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
return rs;
|
2011-02-20 23:56:09 -06:00
|
|
|
}
|
2011-08-23 15:22:44 -05:00
|
|
|
|
2011-02-20 23:56:09 -06:00
|
|
|
/*
|
|
|
|
* According to the standard, the message must be padded to an even
|
|
|
|
* 512 bits. The first padding bit must be a '1'. The last 64 bits
|
|
|
|
* represent the length of the original message. All bits in between
|
|
|
|
* should be 0. This function will pad the message according to those
|
2011-02-22 17:50:39 -06:00
|
|
|
* rules by filling the msg_block vector accordingly. It will also
|
|
|
|
* call process_msg_block() appropriately. When it returns, it
|
2011-02-20 23:56:09 -06:00
|
|
|
* can be assumed that the message digest has been computed.
|
|
|
|
*/
|
2013-02-12 17:34:48 -06:00
|
|
|
fn pad_msg(st: &mut Sha1State) {
|
2012-08-25 17:10:25 -05:00
|
|
|
assert (vec::len((*st).msg_block) == msg_block_len);
|
2011-08-23 15:22:44 -05:00
|
|
|
|
2011-02-20 23:56:09 -06:00
|
|
|
/*
|
|
|
|
* Check to see if the current message block is too small to hold
|
|
|
|
* the initial padding bits and length. If so, we will pad the
|
|
|
|
* block, process it, and then continue padding into a second block.
|
|
|
|
*/
|
2012-08-25 17:10:25 -05:00
|
|
|
if (*st).msg_block_idx > 55u {
|
|
|
|
(*st).msg_block[(*st).msg_block_idx] = 0x80u8;
|
|
|
|
(*st).msg_block_idx += 1u;
|
|
|
|
while (*st).msg_block_idx < msg_block_len {
|
|
|
|
(*st).msg_block[(*st).msg_block_idx] = 0u8;
|
|
|
|
(*st).msg_block_idx += 1u;
|
2011-02-20 23:56:09 -06:00
|
|
|
}
|
|
|
|
process_msg_block(st);
|
|
|
|
} else {
|
2012-08-25 17:10:25 -05:00
|
|
|
(*st).msg_block[(*st).msg_block_idx] = 0x80u8;
|
|
|
|
(*st).msg_block_idx += 1u;
|
2011-02-20 23:56:09 -06:00
|
|
|
}
|
2012-08-25 17:10:25 -05:00
|
|
|
while (*st).msg_block_idx < 56u {
|
|
|
|
(*st).msg_block[(*st).msg_block_idx] = 0u8;
|
|
|
|
(*st).msg_block_idx += 1u;
|
2011-02-20 23:56:09 -06:00
|
|
|
}
|
2011-06-15 13:19:50 -05:00
|
|
|
|
2011-08-23 15:22:44 -05:00
|
|
|
// Store the message length as the last 8 octets
|
2012-08-25 17:10:25 -05:00
|
|
|
(*st).msg_block[56] = ((*st).len_high >> 24u32 & 0xFFu32) as u8;
|
|
|
|
(*st).msg_block[57] = ((*st).len_high >> 16u32 & 0xFFu32) as u8;
|
|
|
|
(*st).msg_block[58] = ((*st).len_high >> 8u32 & 0xFFu32) as u8;
|
|
|
|
(*st).msg_block[59] = ((*st).len_high & 0xFFu32) as u8;
|
|
|
|
(*st).msg_block[60] = ((*st).len_low >> 24u32 & 0xFFu32) as u8;
|
|
|
|
(*st).msg_block[61] = ((*st).len_low >> 16u32 & 0xFFu32) as u8;
|
|
|
|
(*st).msg_block[62] = ((*st).len_low >> 8u32 & 0xFFu32) as u8;
|
|
|
|
(*st).msg_block[63] = ((*st).len_low & 0xFFu32) as u8;
|
2011-02-20 23:56:09 -06:00
|
|
|
process_msg_block(st);
|
|
|
|
}
|
2012-01-11 05:54:39 -06:00
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Sha1 for Sha1State {
|
2013-02-12 17:34:48 -06:00
|
|
|
fn reset(&mut self) {
|
2012-01-11 05:54:39 -06:00
|
|
|
assert (vec::len(self.h) == digest_buf_len);
|
|
|
|
self.len_low = 0u32;
|
|
|
|
self.len_high = 0u32;
|
|
|
|
self.msg_block_idx = 0u;
|
|
|
|
self.h[0] = 0x67452301u32;
|
|
|
|
self.h[1] = 0xEFCDAB89u32;
|
|
|
|
self.h[2] = 0x98BADCFEu32;
|
|
|
|
self.h[3] = 0x10325476u32;
|
|
|
|
self.h[4] = 0xC3D2E1F0u32;
|
|
|
|
self.computed = false;
|
2011-02-20 23:56:09 -06:00
|
|
|
}
|
2013-02-12 17:34:48 -06:00
|
|
|
fn input(&mut self, msg: &[const u8]) { add_input(self, msg); }
|
|
|
|
fn input_str(&mut self, msg: &str) {
|
2012-08-25 17:10:25 -05:00
|
|
|
let bs = str::to_bytes(msg);
|
2013-02-12 17:34:48 -06:00
|
|
|
add_input(self, bs);
|
2012-08-25 17:10:25 -05:00
|
|
|
}
|
2013-02-12 17:34:48 -06:00
|
|
|
fn result(&mut self) -> ~[u8] { return mk_result(self); }
|
|
|
|
fn result_str(&mut self) -> ~str {
|
|
|
|
let rr = mk_result(self);
|
2012-07-14 00:57:48 -05:00
|
|
|
let mut s = ~"";
|
2012-09-18 23:41:37 -05:00
|
|
|
for vec::each(rr) |b| {
|
2013-01-24 14:47:57 -06:00
|
|
|
s += uint::to_str_radix(*b as uint, 16u);
|
2012-09-18 23:41:37 -05:00
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
return s;
|
2011-03-26 19:36:08 -05:00
|
|
|
}
|
2011-02-20 23:56:09 -06:00
|
|
|
}
|
2013-02-12 17:34:48 -06:00
|
|
|
let mut st = Sha1State {
|
|
|
|
h: vec::from_elem(digest_buf_len, 0u32),
|
|
|
|
len_low: 0u32,
|
|
|
|
len_high: 0u32,
|
|
|
|
msg_block: vec::from_elem(msg_block_len, 0u8),
|
|
|
|
msg_block_idx: 0u,
|
|
|
|
computed: false,
|
|
|
|
work_buf: @mut vec::from_elem(work_buf_len, 0u32)
|
2012-01-11 05:54:39 -06:00
|
|
|
};
|
2013-02-15 01:30:30 -06:00
|
|
|
let mut sh = (st) as Sha1;
|
2011-02-20 23:56:09 -06:00
|
|
|
sh.reset();
|
2012-08-01 19:30:05 -05:00
|
|
|
return sh;
|
2011-02-20 23:56:09 -06:00
|
|
|
}
|
2011-08-23 15:22:44 -05:00
|
|
|
|
2012-01-17 21:05:07 -06:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2012-12-27 20:24:18 -06:00
|
|
|
use sha1;
|
|
|
|
|
|
|
|
use core::str;
|
|
|
|
use core::vec;
|
|
|
|
|
2012-01-17 21:05:07 -06:00
|
|
|
#[test]
|
2013-01-29 14:06:09 -06:00
|
|
|
pub fn test() {
|
2013-01-23 13:43:58 -06:00
|
|
|
unsafe {
|
2013-01-22 10:44:24 -06:00
|
|
|
struct Test {
|
|
|
|
input: ~str,
|
|
|
|
output: ~[u8],
|
|
|
|
}
|
2012-01-17 21:05:07 -06:00
|
|
|
|
2013-01-23 13:43:58 -06:00
|
|
|
fn a_million_letter_a() -> ~str {
|
|
|
|
let mut i = 0;
|
|
|
|
let mut rs = ~"";
|
|
|
|
while i < 100000 {
|
|
|
|
str::push_str(&mut rs, ~"aaaaaaaaaa");
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
return rs;
|
2012-09-21 20:36:32 -05:00
|
|
|
}
|
2013-01-23 13:43:58 -06:00
|
|
|
// Test messages from FIPS 180-1
|
2012-01-17 21:05:07 -06:00
|
|
|
|
2013-01-22 10:44:24 -06:00
|
|
|
let fips_180_1_tests = ~[
|
|
|
|
Test {
|
|
|
|
input: ~"abc",
|
|
|
|
output: ~[
|
|
|
|
0xA9u8, 0x99u8, 0x3Eu8, 0x36u8,
|
|
|
|
0x47u8, 0x06u8, 0x81u8, 0x6Au8,
|
|
|
|
0xBAu8, 0x3Eu8, 0x25u8, 0x71u8,
|
|
|
|
0x78u8, 0x50u8, 0xC2u8, 0x6Cu8,
|
|
|
|
0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8,
|
|
|
|
],
|
|
|
|
},
|
|
|
|
Test {
|
|
|
|
input:
|
|
|
|
~"abcdbcdecdefdefgefghfghighij" +
|
|
|
|
~"hijkijkljklmklmnlmnomnopnopq",
|
|
|
|
output: ~[
|
|
|
|
0x84u8, 0x98u8, 0x3Eu8, 0x44u8,
|
|
|
|
0x1Cu8, 0x3Bu8, 0xD2u8, 0x6Eu8,
|
|
|
|
0xBAu8, 0xAEu8, 0x4Au8, 0xA1u8,
|
|
|
|
0xF9u8, 0x51u8, 0x29u8, 0xE5u8,
|
|
|
|
0xE5u8, 0x46u8, 0x70u8, 0xF1u8,
|
|
|
|
],
|
|
|
|
},
|
|
|
|
Test {
|
|
|
|
input: a_million_letter_a(),
|
|
|
|
output: ~[
|
|
|
|
0x34u8, 0xAAu8, 0x97u8, 0x3Cu8,
|
|
|
|
0xD4u8, 0xC4u8, 0xDAu8, 0xA4u8,
|
|
|
|
0xF6u8, 0x1Eu8, 0xEBu8, 0x2Bu8,
|
|
|
|
0xDBu8, 0xADu8, 0x27u8, 0x31u8,
|
|
|
|
0x65u8, 0x34u8, 0x01u8, 0x6Fu8,
|
|
|
|
],
|
|
|
|
},
|
|
|
|
];
|
2013-01-23 13:43:58 -06:00
|
|
|
// Examples from wikipedia
|
2012-01-17 21:05:07 -06:00
|
|
|
|
2013-01-22 10:44:24 -06:00
|
|
|
let wikipedia_tests = ~[
|
|
|
|
Test {
|
|
|
|
input: ~"The quick brown fox jumps over the lazy dog",
|
|
|
|
output: ~[
|
|
|
|
0x2fu8, 0xd4u8, 0xe1u8, 0xc6u8,
|
|
|
|
0x7au8, 0x2du8, 0x28u8, 0xfcu8,
|
|
|
|
0xedu8, 0x84u8, 0x9eu8, 0xe1u8,
|
|
|
|
0xbbu8, 0x76u8, 0xe7u8, 0x39u8,
|
|
|
|
0x1bu8, 0x93u8, 0xebu8, 0x12u8,
|
|
|
|
],
|
|
|
|
},
|
|
|
|
Test {
|
|
|
|
input: ~"The quick brown fox jumps over the lazy cog",
|
|
|
|
output: ~[
|
|
|
|
0xdeu8, 0x9fu8, 0x2cu8, 0x7fu8,
|
|
|
|
0xd2u8, 0x5eu8, 0x1bu8, 0x3au8,
|
|
|
|
0xfau8, 0xd3u8, 0xe8u8, 0x5au8,
|
|
|
|
0x0bu8, 0xd1u8, 0x7du8, 0x9bu8,
|
|
|
|
0x10u8, 0x0du8, 0xb4u8, 0xb3u8,
|
|
|
|
],
|
|
|
|
},
|
|
|
|
];
|
2013-01-23 13:43:58 -06:00
|
|
|
let tests = fips_180_1_tests + wikipedia_tests;
|
|
|
|
fn check_vec_eq(v0: ~[u8], v1: ~[u8]) {
|
|
|
|
assert (vec::len::<u8>(v0) == vec::len::<u8>(v1));
|
|
|
|
let len = vec::len::<u8>(v0);
|
|
|
|
let mut i = 0u;
|
|
|
|
while i < len {
|
|
|
|
let a = v0[i];
|
|
|
|
let b = v1[i];
|
|
|
|
assert (a == b);
|
|
|
|
i += 1u;
|
|
|
|
}
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
2013-01-23 13:43:58 -06:00
|
|
|
// Test that it works when accepting the message all at once
|
2012-01-17 21:05:07 -06:00
|
|
|
|
2013-02-12 17:34:48 -06:00
|
|
|
let mut sh = sha1::sha1();
|
2013-01-23 13:43:58 -06:00
|
|
|
for vec::each(tests) |t| {
|
|
|
|
sh.input_str(t.input);
|
|
|
|
let out = sh.result();
|
|
|
|
check_vec_eq(t.output, out);
|
|
|
|
sh.reset();
|
|
|
|
}
|
2012-01-17 21:05:07 -06:00
|
|
|
|
|
|
|
|
2013-01-23 13:43:58 -06:00
|
|
|
// Test that it works when accepting the message in pieces
|
|
|
|
for vec::each(tests) |t| {
|
|
|
|
let len = str::len(t.input);
|
|
|
|
let mut left = len;
|
|
|
|
while left > 0u {
|
|
|
|
let take = (left + 1u) / 2u;
|
|
|
|
sh.input_str(str::slice(t.input, len - left,
|
|
|
|
take + len - left));
|
|
|
|
left = left - take;
|
|
|
|
}
|
|
|
|
let out = sh.result();
|
|
|
|
check_vec_eq(t.output, out);
|
|
|
|
sh.reset();
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-20 23:56:09 -06:00
|
|
|
// Local Variables:
|
|
|
|
// mode: rust;
|
|
|
|
// fill-column: 78;
|
|
|
|
// indent-tabs-mode: nil
|
|
|
|
// c-basic-offset: 4
|
|
|
|
// buffer-file-coding-system: utf-8-unix
|
|
|
|
// End:
|