hashes: Move bench and test code into files
We are trying to make the `hashes` crate easier to read and also possibly parseable by machines to see what is different where. Move the test and bench code into separate files. Make special effort to keep formatting as is so the diff is easier to review. We will run the formatter in the next patch. Internal change only.
This commit is contained in:
parent
665fa9de99
commit
7be0db730a
|
@ -0,0 +1,33 @@
|
||||||
|
use test::Bencher;
|
||||||
|
|
||||||
|
use crate::{ripemd160, Hash, HashEngine};
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn ripemd160_10(bh: &mut Bencher) {
|
||||||
|
let mut engine = ripemd160::Hash::engine();
|
||||||
|
let bytes = [1u8; 10];
|
||||||
|
bh.iter(|| {
|
||||||
|
engine.input(&bytes);
|
||||||
|
});
|
||||||
|
bh.bytes = bytes.len() as u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn ripemd160_1k(bh: &mut Bencher) {
|
||||||
|
let mut engine = ripemd160::Hash::engine();
|
||||||
|
let bytes = [1u8; 1024];
|
||||||
|
bh.iter(|| {
|
||||||
|
engine.input(&bytes);
|
||||||
|
});
|
||||||
|
bh.bytes = bytes.len() as u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn ripemd160_64k(bh: &mut Bencher) {
|
||||||
|
let mut engine = ripemd160::Hash::engine();
|
||||||
|
let bytes = [1u8; 65536];
|
||||||
|
bh.iter(|| {
|
||||||
|
engine.input(&bytes);
|
||||||
|
});
|
||||||
|
bh.bytes = bytes.len() as u64;
|
||||||
|
}
|
|
@ -2,7 +2,11 @@
|
||||||
|
|
||||||
//! RIPEMD160 implementation.
|
//! RIPEMD160 implementation.
|
||||||
|
|
||||||
|
#[cfg(bench)]
|
||||||
|
mod benches;
|
||||||
mod crypto;
|
mod crypto;
|
||||||
|
#[cfg(bench)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
use core::cmp;
|
use core::cmp;
|
||||||
|
|
||||||
|
@ -89,149 +93,3 @@ impl crate::HashEngine for HashEngine {
|
||||||
|
|
||||||
crate::internal_macros::engine_input_impl!();
|
crate::internal_macros::engine_input_impl!();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
fn test() {
|
|
||||||
use alloc::string::ToString;
|
|
||||||
|
|
||||||
use crate::{ripemd160, HashEngine};
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct Test {
|
|
||||||
input: &'static str,
|
|
||||||
output: [u8; 20],
|
|
||||||
output_str: &'static str,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
let tests = [
|
|
||||||
// Test messages from FIPS 180-1
|
|
||||||
Test {
|
|
||||||
input: "abc",
|
|
||||||
output: [
|
|
||||||
0x8e, 0xb2, 0x08, 0xf7,
|
|
||||||
0xe0, 0x5d, 0x98, 0x7a,
|
|
||||||
0x9b, 0x04, 0x4a, 0x8e,
|
|
||||||
0x98, 0xc6, 0xb0, 0x87,
|
|
||||||
0xf1, 0x5a, 0x0b, 0xfc,
|
|
||||||
],
|
|
||||||
output_str: "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"
|
|
||||||
},
|
|
||||||
Test {
|
|
||||||
input:
|
|
||||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
|
||||||
output: [
|
|
||||||
0x12, 0xa0, 0x53, 0x38,
|
|
||||||
0x4a, 0x9c, 0x0c, 0x88,
|
|
||||||
0xe4, 0x05, 0xa0, 0x6c,
|
|
||||||
0x27, 0xdc, 0xf4, 0x9a,
|
|
||||||
0xda, 0x62, 0xeb, 0x2b,
|
|
||||||
],
|
|
||||||
output_str: "12a053384a9c0c88e405a06c27dcf49ada62eb2b"
|
|
||||||
},
|
|
||||||
// Examples from wikipedia
|
|
||||||
Test {
|
|
||||||
input: "The quick brown fox jumps over the lazy dog",
|
|
||||||
output: [
|
|
||||||
0x37, 0xf3, 0x32, 0xf6,
|
|
||||||
0x8d, 0xb7, 0x7b, 0xd9,
|
|
||||||
0xd7, 0xed, 0xd4, 0x96,
|
|
||||||
0x95, 0x71, 0xad, 0x67,
|
|
||||||
0x1c, 0xf9, 0xdd, 0x3b,
|
|
||||||
],
|
|
||||||
output_str: "37f332f68db77bd9d7edd4969571ad671cf9dd3b",
|
|
||||||
},
|
|
||||||
Test {
|
|
||||||
input: "The quick brown fox jumps over the lazy cog",
|
|
||||||
output: [
|
|
||||||
0x13, 0x20, 0x72, 0xdf,
|
|
||||||
0x69, 0x09, 0x33, 0x83,
|
|
||||||
0x5e, 0xb8, 0xb6, 0xad,
|
|
||||||
0x0b, 0x77, 0xe7, 0xb6,
|
|
||||||
0xf1, 0x4a, 0xca, 0xd7,
|
|
||||||
],
|
|
||||||
output_str: "132072df690933835eb8b6ad0b77e7b6f14acad7",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for mut test in tests {
|
|
||||||
// Hash through high-level API, check hex encoding/decoding
|
|
||||||
let hash = ripemd160::Hash::hash(test.input.as_bytes());
|
|
||||||
assert_eq!(hash, test.output_str.parse::<ripemd160::Hash>().expect("parse hex"));
|
|
||||||
assert_eq!(hash.as_byte_array(), &test.output);
|
|
||||||
assert_eq!(hash.to_string(), test.output_str);
|
|
||||||
assert_eq!(ripemd160::Hash::from_bytes_ref(&test.output), &hash);
|
|
||||||
assert_eq!(ripemd160::Hash::from_bytes_mut(&mut test.output), &hash);
|
|
||||||
|
|
||||||
// Hash through engine, checking that we can input byte by byte
|
|
||||||
let mut engine = ripemd160::Hash::engine();
|
|
||||||
for ch in test.input.as_bytes() {
|
|
||||||
engine.input(&[*ch]);
|
|
||||||
}
|
|
||||||
let manual_hash = ripemd160::Hash::from_engine(engine);
|
|
||||||
assert_eq!(hash, manual_hash);
|
|
||||||
assert_eq!(hash.to_byte_array(), test.output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
fn ripemd_serde() {
|
|
||||||
use serde_test::{assert_tokens, Configure, Token};
|
|
||||||
|
|
||||||
use crate::ripemd160;
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
static HASH_BYTES: [u8; 20] = [
|
|
||||||
0x13, 0x20, 0x72, 0xdf,
|
|
||||||
0x69, 0x09, 0x33, 0x83,
|
|
||||||
0x5e, 0xb8, 0xb6, 0xad,
|
|
||||||
0x0b, 0x77, 0xe7, 0xb6,
|
|
||||||
0xf1, 0x4a, 0xca, 0xd7,
|
|
||||||
];
|
|
||||||
|
|
||||||
let hash = ripemd160::Hash::from_slice(&HASH_BYTES).expect("right number of bytes");
|
|
||||||
assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]);
|
|
||||||
assert_tokens(&hash.readable(), &[Token::Str("132072df690933835eb8b6ad0b77e7b6f14acad7")]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(bench)]
|
|
||||||
mod benches {
|
|
||||||
use test::Bencher;
|
|
||||||
|
|
||||||
use crate::{ripemd160, Hash, HashEngine};
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
pub fn ripemd160_10(bh: &mut Bencher) {
|
|
||||||
let mut engine = ripemd160::Hash::engine();
|
|
||||||
let bytes = [1u8; 10];
|
|
||||||
bh.iter(|| {
|
|
||||||
engine.input(&bytes);
|
|
||||||
});
|
|
||||||
bh.bytes = bytes.len() as u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
pub fn ripemd160_1k(bh: &mut Bencher) {
|
|
||||||
let mut engine = ripemd160::Hash::engine();
|
|
||||||
let bytes = [1u8; 1024];
|
|
||||||
bh.iter(|| {
|
|
||||||
engine.input(&bytes);
|
|
||||||
});
|
|
||||||
bh.bytes = bytes.len() as u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
pub fn ripemd160_64k(bh: &mut Bencher) {
|
|
||||||
let mut engine = ripemd160::Hash::engine();
|
|
||||||
let bytes = [1u8; 65536];
|
|
||||||
bh.iter(|| {
|
|
||||||
engine.input(&bytes);
|
|
||||||
});
|
|
||||||
bh.bytes = bytes.len() as u64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
fn test() {
|
||||||
|
use alloc::string::ToString;
|
||||||
|
|
||||||
|
use crate::{ripemd160, HashEngine};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Test {
|
||||||
|
input: &'static str,
|
||||||
|
output: [u8; 20],
|
||||||
|
output_str: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
let tests = [
|
||||||
|
// Test messages from FIPS 180-1
|
||||||
|
Test {
|
||||||
|
input: "abc",
|
||||||
|
output: [
|
||||||
|
0x8e, 0xb2, 0x08, 0xf7,
|
||||||
|
0xe0, 0x5d, 0x98, 0x7a,
|
||||||
|
0x9b, 0x04, 0x4a, 0x8e,
|
||||||
|
0x98, 0xc6, 0xb0, 0x87,
|
||||||
|
0xf1, 0x5a, 0x0b, 0xfc,
|
||||||
|
],
|
||||||
|
output_str: "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"
|
||||||
|
},
|
||||||
|
Test {
|
||||||
|
input:
|
||||||
|
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||||
|
output: [
|
||||||
|
0x12, 0xa0, 0x53, 0x38,
|
||||||
|
0x4a, 0x9c, 0x0c, 0x88,
|
||||||
|
0xe4, 0x05, 0xa0, 0x6c,
|
||||||
|
0x27, 0xdc, 0xf4, 0x9a,
|
||||||
|
0xda, 0x62, 0xeb, 0x2b,
|
||||||
|
],
|
||||||
|
output_str: "12a053384a9c0c88e405a06c27dcf49ada62eb2b"
|
||||||
|
},
|
||||||
|
// Examples from wikipedia
|
||||||
|
Test {
|
||||||
|
input: "The quick brown fox jumps over the lazy dog",
|
||||||
|
output: [
|
||||||
|
0x37, 0xf3, 0x32, 0xf6,
|
||||||
|
0x8d, 0xb7, 0x7b, 0xd9,
|
||||||
|
0xd7, 0xed, 0xd4, 0x96,
|
||||||
|
0x95, 0x71, 0xad, 0x67,
|
||||||
|
0x1c, 0xf9, 0xdd, 0x3b,
|
||||||
|
],
|
||||||
|
output_str: "37f332f68db77bd9d7edd4969571ad671cf9dd3b",
|
||||||
|
},
|
||||||
|
Test {
|
||||||
|
input: "The quick brown fox jumps over the lazy cog",
|
||||||
|
output: [
|
||||||
|
0x13, 0x20, 0x72, 0xdf,
|
||||||
|
0x69, 0x09, 0x33, 0x83,
|
||||||
|
0x5e, 0xb8, 0xb6, 0xad,
|
||||||
|
0x0b, 0x77, 0xe7, 0xb6,
|
||||||
|
0xf1, 0x4a, 0xca, 0xd7,
|
||||||
|
],
|
||||||
|
output_str: "132072df690933835eb8b6ad0b77e7b6f14acad7",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for mut test in tests {
|
||||||
|
// Hash through high-level API, check hex encoding/decoding
|
||||||
|
let hash = ripemd160::Hash::hash(test.input.as_bytes());
|
||||||
|
assert_eq!(hash, test.output_str.parse::<ripemd160::Hash>().expect("parse hex"));
|
||||||
|
assert_eq!(hash.as_byte_array(), &test.output);
|
||||||
|
assert_eq!(hash.to_string(), test.output_str);
|
||||||
|
assert_eq!(ripemd160::Hash::from_bytes_ref(&test.output), &hash);
|
||||||
|
assert_eq!(ripemd160::Hash::from_bytes_mut(&mut test.output), &hash);
|
||||||
|
|
||||||
|
// Hash through engine, checking that we can input byte by byte
|
||||||
|
let mut engine = ripemd160::Hash::engine();
|
||||||
|
for ch in test.input.as_bytes() {
|
||||||
|
engine.input(&[*ch]);
|
||||||
|
}
|
||||||
|
let manual_hash = ripemd160::Hash::from_engine(engine);
|
||||||
|
assert_eq!(hash, manual_hash);
|
||||||
|
assert_eq!(hash.to_byte_array(), test.output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
fn ripemd_serde() {
|
||||||
|
use serde_test::{assert_tokens, Configure, Token};
|
||||||
|
|
||||||
|
use crate::ripemd160;
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
static HASH_BYTES: [u8; 20] = [
|
||||||
|
0x13, 0x20, 0x72, 0xdf,
|
||||||
|
0x69, 0x09, 0x33, 0x83,
|
||||||
|
0x5e, 0xb8, 0xb6, 0xad,
|
||||||
|
0x0b, 0x77, 0xe7, 0xb6,
|
||||||
|
0xf1, 0x4a, 0xca, 0xd7,
|
||||||
|
];
|
||||||
|
|
||||||
|
let hash = ripemd160::Hash::from_slice(&HASH_BYTES).expect("right number of bytes");
|
||||||
|
assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]);
|
||||||
|
assert_tokens(&hash.readable(), &[Token::Str("132072df690933835eb8b6ad0b77e7b6f14acad7")]);
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
use test::Bencher;
|
||||||
|
|
||||||
|
use crate::{sha1, Hash, HashEngine};
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn sha1_10(bh: &mut Bencher) {
|
||||||
|
let mut engine = sha1::Hash::engine();
|
||||||
|
let bytes = [1u8; 10];
|
||||||
|
bh.iter(|| {
|
||||||
|
engine.input(&bytes);
|
||||||
|
});
|
||||||
|
bh.bytes = bytes.len() as u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn sha1_1k(bh: &mut Bencher) {
|
||||||
|
let mut engine = sha1::Hash::engine();
|
||||||
|
let bytes = [1u8; 1024];
|
||||||
|
bh.iter(|| {
|
||||||
|
engine.input(&bytes);
|
||||||
|
});
|
||||||
|
bh.bytes = bytes.len() as u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn sha1_64k(bh: &mut Bencher) {
|
||||||
|
let mut engine = sha1::Hash::engine();
|
||||||
|
let bytes = [1u8; 65536];
|
||||||
|
bh.iter(|| {
|
||||||
|
engine.input(&bytes);
|
||||||
|
});
|
||||||
|
bh.bytes = bytes.len() as u64;
|
||||||
|
}
|
|
@ -2,7 +2,11 @@
|
||||||
|
|
||||||
//! SHA1 implementation.
|
//! SHA1 implementation.
|
||||||
|
|
||||||
|
#[cfg(bench)]
|
||||||
|
mod benches;
|
||||||
mod crypto;
|
mod crypto;
|
||||||
|
#[cfg(bench)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
use core::cmp;
|
use core::cmp;
|
||||||
|
|
||||||
|
@ -81,134 +85,3 @@ impl crate::HashEngine for HashEngine {
|
||||||
|
|
||||||
crate::internal_macros::engine_input_impl!();
|
crate::internal_macros::engine_input_impl!();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
fn test() {
|
|
||||||
use alloc::string::ToString;
|
|
||||||
|
|
||||||
use crate::{sha1, HashEngine};
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct Test {
|
|
||||||
input: &'static str,
|
|
||||||
output: [u8; 20],
|
|
||||||
output_str: &'static str,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
let tests = [
|
|
||||||
// Examples from wikipedia
|
|
||||||
Test {
|
|
||||||
input: "",
|
|
||||||
output: [
|
|
||||||
0xda, 0x39, 0xa3, 0xee,
|
|
||||||
0x5e, 0x6b, 0x4b, 0x0d,
|
|
||||||
0x32, 0x55, 0xbf, 0xef,
|
|
||||||
0x95, 0x60, 0x18, 0x90,
|
|
||||||
0xaf, 0xd8, 0x07, 0x09,
|
|
||||||
],
|
|
||||||
output_str: "da39a3ee5e6b4b0d3255bfef95601890afd80709"
|
|
||||||
},
|
|
||||||
Test {
|
|
||||||
input: "The quick brown fox jumps over the lazy dog",
|
|
||||||
output: [
|
|
||||||
0x2f, 0xd4, 0xe1, 0xc6,
|
|
||||||
0x7a, 0x2d, 0x28, 0xfc,
|
|
||||||
0xed, 0x84, 0x9e, 0xe1,
|
|
||||||
0xbb, 0x76, 0xe7, 0x39,
|
|
||||||
0x1b, 0x93, 0xeb, 0x12,
|
|
||||||
],
|
|
||||||
output_str: "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12",
|
|
||||||
},
|
|
||||||
Test {
|
|
||||||
input: "The quick brown fox jumps over the lazy cog",
|
|
||||||
output: [
|
|
||||||
0xde, 0x9f, 0x2c, 0x7f,
|
|
||||||
0xd2, 0x5e, 0x1b, 0x3a,
|
|
||||||
0xfa, 0xd3, 0xe8, 0x5a,
|
|
||||||
0x0b, 0xd1, 0x7d, 0x9b,
|
|
||||||
0x10, 0x0d, 0xb4, 0xb3,
|
|
||||||
],
|
|
||||||
output_str: "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for test in tests {
|
|
||||||
// Hash through high-level API, check hex encoding/decoding
|
|
||||||
let hash = sha1::Hash::hash(test.input.as_bytes());
|
|
||||||
assert_eq!(hash, test.output_str.parse::<sha1::Hash>().expect("parse hex"));
|
|
||||||
assert_eq!(hash.as_byte_array(), &test.output);
|
|
||||||
assert_eq!(hash.to_string(), test.output_str);
|
|
||||||
|
|
||||||
// Hash through engine, checking that we can input byte by byte
|
|
||||||
let mut engine = sha1::Hash::engine();
|
|
||||||
for ch in test.input.as_bytes() {
|
|
||||||
engine.input(&[*ch]);
|
|
||||||
}
|
|
||||||
let manual_hash = sha1::Hash::from_engine(engine);
|
|
||||||
assert_eq!(hash, manual_hash);
|
|
||||||
assert_eq!(hash.to_byte_array(), test.output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
fn sha1_serde() {
|
|
||||||
use serde_test::{assert_tokens, Configure, Token};
|
|
||||||
|
|
||||||
use crate::sha1;
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
static HASH_BYTES: [u8; 20] = [
|
|
||||||
0x13, 0x20, 0x72, 0xdf,
|
|
||||||
0x69, 0x09, 0x33, 0x83,
|
|
||||||
0x5e, 0xb8, 0xb6, 0xad,
|
|
||||||
0x0b, 0x77, 0xe7, 0xb6,
|
|
||||||
0xf1, 0x4a, 0xca, 0xd7,
|
|
||||||
];
|
|
||||||
|
|
||||||
let hash = sha1::Hash::from_slice(&HASH_BYTES).expect("right number of bytes");
|
|
||||||
assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]);
|
|
||||||
assert_tokens(&hash.readable(), &[Token::Str("132072df690933835eb8b6ad0b77e7b6f14acad7")]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(bench)]
|
|
||||||
mod benches {
|
|
||||||
use test::Bencher;
|
|
||||||
|
|
||||||
use crate::{sha1, Hash, HashEngine};
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
pub fn sha1_10(bh: &mut Bencher) {
|
|
||||||
let mut engine = sha1::Hash::engine();
|
|
||||||
let bytes = [1u8; 10];
|
|
||||||
bh.iter(|| {
|
|
||||||
engine.input(&bytes);
|
|
||||||
});
|
|
||||||
bh.bytes = bytes.len() as u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
pub fn sha1_1k(bh: &mut Bencher) {
|
|
||||||
let mut engine = sha1::Hash::engine();
|
|
||||||
let bytes = [1u8; 1024];
|
|
||||||
bh.iter(|| {
|
|
||||||
engine.input(&bytes);
|
|
||||||
});
|
|
||||||
bh.bytes = bytes.len() as u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
pub fn sha1_64k(bh: &mut Bencher) {
|
|
||||||
let mut engine = sha1::Hash::engine();
|
|
||||||
let bytes = [1u8; 65536];
|
|
||||||
bh.iter(|| {
|
|
||||||
engine.input(&bytes);
|
|
||||||
});
|
|
||||||
bh.bytes = bytes.len() as u64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
fn test() {
|
||||||
|
use alloc::string::ToString;
|
||||||
|
|
||||||
|
use crate::{sha1, HashEngine};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Test {
|
||||||
|
input: &'static str,
|
||||||
|
output: [u8; 20],
|
||||||
|
output_str: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
let tests = [
|
||||||
|
// Examples from wikipedia
|
||||||
|
Test {
|
||||||
|
input: "",
|
||||||
|
output: [
|
||||||
|
0xda, 0x39, 0xa3, 0xee,
|
||||||
|
0x5e, 0x6b, 0x4b, 0x0d,
|
||||||
|
0x32, 0x55, 0xbf, 0xef,
|
||||||
|
0x95, 0x60, 0x18, 0x90,
|
||||||
|
0xaf, 0xd8, 0x07, 0x09,
|
||||||
|
],
|
||||||
|
output_str: "da39a3ee5e6b4b0d3255bfef95601890afd80709"
|
||||||
|
},
|
||||||
|
Test {
|
||||||
|
input: "The quick brown fox jumps over the lazy dog",
|
||||||
|
output: [
|
||||||
|
0x2f, 0xd4, 0xe1, 0xc6,
|
||||||
|
0x7a, 0x2d, 0x28, 0xfc,
|
||||||
|
0xed, 0x84, 0x9e, 0xe1,
|
||||||
|
0xbb, 0x76, 0xe7, 0x39,
|
||||||
|
0x1b, 0x93, 0xeb, 0x12,
|
||||||
|
],
|
||||||
|
output_str: "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12",
|
||||||
|
},
|
||||||
|
Test {
|
||||||
|
input: "The quick brown fox jumps over the lazy cog",
|
||||||
|
output: [
|
||||||
|
0xde, 0x9f, 0x2c, 0x7f,
|
||||||
|
0xd2, 0x5e, 0x1b, 0x3a,
|
||||||
|
0xfa, 0xd3, 0xe8, 0x5a,
|
||||||
|
0x0b, 0xd1, 0x7d, 0x9b,
|
||||||
|
0x10, 0x0d, 0xb4, 0xb3,
|
||||||
|
],
|
||||||
|
output_str: "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for test in tests {
|
||||||
|
// Hash through high-level API, check hex encoding/decoding
|
||||||
|
let hash = sha1::Hash::hash(test.input.as_bytes());
|
||||||
|
assert_eq!(hash, test.output_str.parse::<sha1::Hash>().expect("parse hex"));
|
||||||
|
assert_eq!(hash.as_byte_array(), &test.output);
|
||||||
|
assert_eq!(hash.to_string(), test.output_str);
|
||||||
|
|
||||||
|
// Hash through engine, checking that we can input byte by byte
|
||||||
|
let mut engine = sha1::Hash::engine();
|
||||||
|
for ch in test.input.as_bytes() {
|
||||||
|
engine.input(&[*ch]);
|
||||||
|
}
|
||||||
|
let manual_hash = sha1::Hash::from_engine(engine);
|
||||||
|
assert_eq!(hash, manual_hash);
|
||||||
|
assert_eq!(hash.to_byte_array(), test.output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
fn sha1_serde() {
|
||||||
|
use serde_test::{assert_tokens, Configure, Token};
|
||||||
|
|
||||||
|
use crate::sha1;
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
static HASH_BYTES: [u8; 20] = [
|
||||||
|
0x13, 0x20, 0x72, 0xdf,
|
||||||
|
0x69, 0x09, 0x33, 0x83,
|
||||||
|
0x5e, 0xb8, 0xb6, 0xad,
|
||||||
|
0x0b, 0x77, 0xe7, 0xb6,
|
||||||
|
0xf1, 0x4a, 0xca, 0xd7,
|
||||||
|
];
|
||||||
|
|
||||||
|
let hash = sha1::Hash::from_slice(&HASH_BYTES).expect("right number of bytes");
|
||||||
|
assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]);
|
||||||
|
assert_tokens(&hash.readable(), &[Token::Str("132072df690933835eb8b6ad0b77e7b6f14acad7")]);
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
use test::Bencher;
|
||||||
|
|
||||||
|
use crate::{sha256, Hash, HashEngine};
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn sha256_10(bh: &mut Bencher) {
|
||||||
|
let mut engine = sha256::Hash::engine();
|
||||||
|
let bytes = [1u8; 10];
|
||||||
|
bh.iter(|| {
|
||||||
|
engine.input(&bytes);
|
||||||
|
});
|
||||||
|
bh.bytes = bytes.len() as u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn sha256_1k(bh: &mut Bencher) {
|
||||||
|
let mut engine = sha256::Hash::engine();
|
||||||
|
let bytes = [1u8; 1024];
|
||||||
|
bh.iter(|| {
|
||||||
|
engine.input(&bytes);
|
||||||
|
});
|
||||||
|
bh.bytes = bytes.len() as u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn sha256_64k(bh: &mut Bencher) {
|
||||||
|
let mut engine = sha256::Hash::engine();
|
||||||
|
let bytes = [1u8; 65536];
|
||||||
|
bh.iter(|| {
|
||||||
|
engine.input(&bytes);
|
||||||
|
});
|
||||||
|
bh.bytes = bytes.len() as u64;
|
||||||
|
}
|
|
@ -2,7 +2,11 @@
|
||||||
|
|
||||||
//! SHA256 implementation.
|
//! SHA256 implementation.
|
||||||
|
|
||||||
|
#[cfg(bench)]
|
||||||
|
mod benches;
|
||||||
mod crypto;
|
mod crypto;
|
||||||
|
#[cfg(bench)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
use core::{cmp, convert, fmt};
|
use core::{cmp, convert, fmt};
|
||||||
|
|
||||||
|
@ -253,277 +257,3 @@ impl fmt::Display for MidstateError {
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl std::error::Error for MidstateError {}
|
impl std::error::Error for MidstateError {}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use core::array;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
use crate::{sha256, HashEngine};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
fn test() {
|
|
||||||
use alloc::string::ToString;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct Test {
|
|
||||||
input: &'static str,
|
|
||||||
output: [u8; 32],
|
|
||||||
output_str: &'static str,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
let tests = [
|
|
||||||
// Examples from wikipedia
|
|
||||||
Test {
|
|
||||||
input: "",
|
|
||||||
output: [
|
|
||||||
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
|
|
||||||
0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
|
|
||||||
0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
|
|
||||||
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
|
|
||||||
],
|
|
||||||
output_str: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
|
||||||
},
|
|
||||||
Test {
|
|
||||||
input: "The quick brown fox jumps over the lazy dog",
|
|
||||||
output: [
|
|
||||||
0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94,
|
|
||||||
0x69, 0xca, 0x9a, 0xbc, 0xb0, 0x08, 0x2e, 0x4f,
|
|
||||||
0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76,
|
|
||||||
0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92,
|
|
||||||
],
|
|
||||||
output_str: "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
|
|
||||||
},
|
|
||||||
Test {
|
|
||||||
input: "The quick brown fox jumps over the lazy dog.",
|
|
||||||
output: [
|
|
||||||
0xef, 0x53, 0x7f, 0x25, 0xc8, 0x95, 0xbf, 0xa7,
|
|
||||||
0x82, 0x52, 0x65, 0x29, 0xa9, 0xb6, 0x3d, 0x97,
|
|
||||||
0xaa, 0x63, 0x15, 0x64, 0xd5, 0xd7, 0x89, 0xc2,
|
|
||||||
0xb7, 0x65, 0x44, 0x8c, 0x86, 0x35, 0xfb, 0x6c,
|
|
||||||
],
|
|
||||||
output_str: "ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for test in tests {
|
|
||||||
// Hash through high-level API, check hex encoding/decoding
|
|
||||||
let hash = sha256::Hash::hash(test.input.as_bytes());
|
|
||||||
assert_eq!(hash, test.output_str.parse::<sha256::Hash>().expect("parse hex"));
|
|
||||||
assert_eq!(hash.as_byte_array(), &test.output);
|
|
||||||
assert_eq!(hash.to_string(), test.output_str);
|
|
||||||
|
|
||||||
// Hash through engine, checking that we can input byte by byte
|
|
||||||
let mut engine = sha256::Hash::engine();
|
|
||||||
for ch in test.input.as_bytes() {
|
|
||||||
engine.input(&[*ch]);
|
|
||||||
}
|
|
||||||
let manual_hash = sha256::Hash::from_engine(engine);
|
|
||||||
assert_eq!(hash, manual_hash);
|
|
||||||
assert_eq!(hash.to_byte_array(), test.output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
fn fmt_roundtrips() {
|
|
||||||
use alloc::format;
|
|
||||||
|
|
||||||
let hash = sha256::Hash::hash(b"some arbitrary bytes");
|
|
||||||
let hex = format!("{}", hash);
|
|
||||||
let rinsed = hex.parse::<sha256::Hash>().expect("failed to parse hex");
|
|
||||||
assert_eq!(rinsed, hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[rustfmt::skip]
|
|
||||||
pub(crate) fn midstate() {
|
|
||||||
// Test vector obtained by doing an asset issuance on Elements
|
|
||||||
let mut engine = sha256::Hash::engine();
|
|
||||||
// sha256dhash of outpoint
|
|
||||||
// 73828cbc65fd68ab78dc86992b76ae50ae2bf8ceedbe8de0483172f0886219f7:0
|
|
||||||
engine.input(&[
|
|
||||||
0x9d, 0xd0, 0x1b, 0x56, 0xb1, 0x56, 0x45, 0x14,
|
|
||||||
0x3e, 0xad, 0x15, 0x8d, 0xec, 0x19, 0xf8, 0xce,
|
|
||||||
0xa9, 0x0b, 0xd0, 0xa9, 0xb2, 0xf8, 0x1d, 0x21,
|
|
||||||
0xff, 0xa3, 0xa4, 0xc6, 0x44, 0x81, 0xd4, 0x1c,
|
|
||||||
]);
|
|
||||||
// 32 bytes of zeroes representing "new asset"
|
|
||||||
engine.input(&[0; 32]);
|
|
||||||
|
|
||||||
// RPC output
|
|
||||||
static WANT: Midstate = sha256::Midstate::new([
|
|
||||||
0x0b, 0xcf, 0xe0, 0xe5, 0x4e, 0x6c, 0xc7, 0xd3,
|
|
||||||
0x4f, 0x4f, 0x7c, 0x1d, 0xf0, 0xb0, 0xf5, 0x03,
|
|
||||||
0xf2, 0xf7, 0x12, 0x91, 0x2a, 0x06, 0x05, 0xb4,
|
|
||||||
0x14, 0xed, 0x33, 0x7f, 0x7f, 0x03, 0x2e, 0x03,
|
|
||||||
], 64);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
engine.midstate().expect("total_bytes_hashed is valid"),
|
|
||||||
WANT,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn engine_with_state() {
|
|
||||||
let mut engine = sha256::Hash::engine();
|
|
||||||
let midstate_engine = sha256::HashEngine::from_midstate(engine.midstate_unchecked());
|
|
||||||
// Fresh engine and engine initialized with fresh state should have same state
|
|
||||||
assert_eq!(engine.h, midstate_engine.h);
|
|
||||||
|
|
||||||
// Midstate changes after writing 64 bytes
|
|
||||||
engine.input(&[1; 63]);
|
|
||||||
assert_eq!(engine.h, midstate_engine.h);
|
|
||||||
engine.input(&[2; 1]);
|
|
||||||
assert_ne!(engine.h, midstate_engine.h);
|
|
||||||
|
|
||||||
// Initializing an engine with midstate from another engine should result in
|
|
||||||
// both engines producing the same hashes
|
|
||||||
let data_vec: &[&[u8]] = &[&[3u8; 1], &[4u8; 63], &[5u8; 65], &[6u8; 66]];
|
|
||||||
for data in data_vec {
|
|
||||||
let mut engine = engine.clone();
|
|
||||||
let mut midstate_engine =
|
|
||||||
sha256::HashEngine::from_midstate(engine.midstate_unchecked());
|
|
||||||
assert_eq!(engine.h, midstate_engine.h);
|
|
||||||
assert_eq!(engine.bytes_hashed, midstate_engine.bytes_hashed);
|
|
||||||
engine.input(data);
|
|
||||||
midstate_engine.input(data);
|
|
||||||
assert_eq!(engine.h, midstate_engine.h);
|
|
||||||
let hash1 = sha256::Hash::from_engine(engine);
|
|
||||||
let hash2 = sha256::Hash::from_engine(midstate_engine);
|
|
||||||
assert_eq!(hash1, hash2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that a specific midstate results in a specific hash. Midstate was
|
|
||||||
// obtained by applying sha256 to sha256("MuSig coefficient")||sha256("MuSig
|
|
||||||
// coefficient").
|
|
||||||
#[rustfmt::skip]
|
|
||||||
static MIDSTATE: [u8; 32] = [
|
|
||||||
0x0f, 0xd0, 0x69, 0x0c, 0xfe, 0xfe, 0xae, 0x97,
|
|
||||||
0x99, 0x6e, 0xac, 0x7f, 0x5c, 0x30, 0xd8, 0x64,
|
|
||||||
0x8c, 0x4a, 0x05, 0x73, 0xac, 0xa1, 0xa2, 0x2f,
|
|
||||||
0x6f, 0x43, 0xb8, 0x01, 0x85, 0xce, 0x27, 0xcd,
|
|
||||||
];
|
|
||||||
#[rustfmt::skip]
|
|
||||||
static HASH_EXPECTED: [u8; 32] = [
|
|
||||||
0x18, 0x84, 0xe4, 0x72, 0x40, 0x4e, 0xf4, 0x5a,
|
|
||||||
0xb4, 0x9c, 0x4e, 0xa4, 0x9a, 0xe6, 0x23, 0xa8,
|
|
||||||
0x88, 0x52, 0x7f, 0x7d, 0x8a, 0x06, 0x94, 0x20,
|
|
||||||
0x8f, 0xf1, 0xf7, 0xa9, 0xd5, 0x69, 0x09, 0x59,
|
|
||||||
];
|
|
||||||
let midstate_engine =
|
|
||||||
sha256::HashEngine::from_midstate(sha256::Midstate::new(MIDSTATE, 64));
|
|
||||||
let hash = sha256::Hash::from_engine(midstate_engine);
|
|
||||||
assert_eq!(hash, sha256::Hash(HASH_EXPECTED));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn hash_unoptimized() {
|
|
||||||
let bytes: [u8; 256] = array::from_fn(|i| i as u8);
|
|
||||||
|
|
||||||
for i in 0..=256 {
|
|
||||||
let bytes = &bytes[0..i];
|
|
||||||
assert_eq!(
|
|
||||||
Hash::hash(bytes),
|
|
||||||
Hash::hash_unoptimized(bytes),
|
|
||||||
"hashes don't match for n_bytes_hashed {}",
|
|
||||||
i + 1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The midstate of an empty hash engine tagged with "TapLeaf".
|
|
||||||
const TAP_LEAF_MIDSTATE: Midstate = Midstate::new(
|
|
||||||
[
|
|
||||||
156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211, 243,
|
|
||||||
147, 108, 71, 99, 110, 96, 125, 179, 62, 234, 221, 198, 240, 201,
|
|
||||||
],
|
|
||||||
64,
|
|
||||||
);
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn const_midstate() { assert_eq!(Midstate::hash_tag(b"TapLeaf"), TAP_LEAF_MIDSTATE,) }
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
fn regression_midstate_debug_format() {
|
|
||||||
use alloc::format;
|
|
||||||
|
|
||||||
let want = "Midstate { bytes: 9ce0e4e67c116c3938b3caf2c30f5089d3f3936c47636e607db33eeaddc6f0c9, length: 64 }";
|
|
||||||
let got = format!("{:?}", TAP_LEAF_MIDSTATE);
|
|
||||||
assert_eq!(got, want);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
fn sha256_serde() {
|
|
||||||
use serde_test::{assert_tokens, Configure, Token};
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
static HASH_BYTES: [u8; 32] = [
|
|
||||||
0xef, 0x53, 0x7f, 0x25, 0xc8, 0x95, 0xbf, 0xa7,
|
|
||||||
0x82, 0x52, 0x65, 0x29, 0xa9, 0xb6, 0x3d, 0x97,
|
|
||||||
0xaa, 0x63, 0x15, 0x64, 0xd5, 0xd7, 0x89, 0xc2,
|
|
||||||
0xb7, 0x65, 0x44, 0x8c, 0x86, 0x35, 0xfb, 0x6c,
|
|
||||||
];
|
|
||||||
|
|
||||||
let hash = sha256::Hash::from_slice(&HASH_BYTES).expect("right number of bytes");
|
|
||||||
assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]);
|
|
||||||
assert_tokens(
|
|
||||||
&hash.readable(),
|
|
||||||
&[Token::Str("ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c")],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
mod wasm_tests {
|
|
||||||
use super::*;
|
|
||||||
#[test]
|
|
||||||
#[wasm_bindgen_test::wasm_bindgen_test]
|
|
||||||
fn sha256_tests() {
|
|
||||||
test();
|
|
||||||
midstate();
|
|
||||||
engine_with_state();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(bench)]
|
|
||||||
mod benches {
|
|
||||||
use test::Bencher;
|
|
||||||
|
|
||||||
use crate::{sha256, Hash, HashEngine};
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
pub fn sha256_10(bh: &mut Bencher) {
|
|
||||||
let mut engine = sha256::Hash::engine();
|
|
||||||
let bytes = [1u8; 10];
|
|
||||||
bh.iter(|| {
|
|
||||||
engine.input(&bytes);
|
|
||||||
});
|
|
||||||
bh.bytes = bytes.len() as u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
pub fn sha256_1k(bh: &mut Bencher) {
|
|
||||||
let mut engine = sha256::Hash::engine();
|
|
||||||
let bytes = [1u8; 1024];
|
|
||||||
bh.iter(|| {
|
|
||||||
engine.input(&bytes);
|
|
||||||
});
|
|
||||||
bh.bytes = bytes.len() as u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
pub fn sha256_64k(bh: &mut Bencher) {
|
|
||||||
let mut engine = sha256::Hash::engine();
|
|
||||||
let bytes = [1u8; 65536];
|
|
||||||
bh.iter(|| {
|
|
||||||
engine.input(&bytes);
|
|
||||||
});
|
|
||||||
bh.bytes = bytes.len() as u64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,233 @@
|
||||||
|
use core::array;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::{sha256, HashEngine};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
fn test() {
|
||||||
|
use alloc::string::ToString;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Test {
|
||||||
|
input: &'static str,
|
||||||
|
output: [u8; 32],
|
||||||
|
output_str: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
let tests = [
|
||||||
|
// Examples from wikipedia
|
||||||
|
Test {
|
||||||
|
input: "",
|
||||||
|
output: [
|
||||||
|
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
|
||||||
|
0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
|
||||||
|
0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
|
||||||
|
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
|
||||||
|
],
|
||||||
|
output_str: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||||
|
},
|
||||||
|
Test {
|
||||||
|
input: "The quick brown fox jumps over the lazy dog",
|
||||||
|
output: [
|
||||||
|
0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94,
|
||||||
|
0x69, 0xca, 0x9a, 0xbc, 0xb0, 0x08, 0x2e, 0x4f,
|
||||||
|
0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76,
|
||||||
|
0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92,
|
||||||
|
],
|
||||||
|
output_str: "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
|
||||||
|
},
|
||||||
|
Test {
|
||||||
|
input: "The quick brown fox jumps over the lazy dog.",
|
||||||
|
output: [
|
||||||
|
0xef, 0x53, 0x7f, 0x25, 0xc8, 0x95, 0xbf, 0xa7,
|
||||||
|
0x82, 0x52, 0x65, 0x29, 0xa9, 0xb6, 0x3d, 0x97,
|
||||||
|
0xaa, 0x63, 0x15, 0x64, 0xd5, 0xd7, 0x89, 0xc2,
|
||||||
|
0xb7, 0x65, 0x44, 0x8c, 0x86, 0x35, 0xfb, 0x6c,
|
||||||
|
],
|
||||||
|
output_str: "ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for test in tests {
|
||||||
|
// Hash through high-level API, check hex encoding/decoding
|
||||||
|
let hash = sha256::Hash::hash(test.input.as_bytes());
|
||||||
|
assert_eq!(hash, test.output_str.parse::<sha256::Hash>().expect("parse hex"));
|
||||||
|
assert_eq!(hash.as_byte_array(), &test.output);
|
||||||
|
assert_eq!(hash.to_string(), test.output_str);
|
||||||
|
|
||||||
|
// Hash through engine, checking that we can input byte by byte
|
||||||
|
let mut engine = sha256::Hash::engine();
|
||||||
|
for ch in test.input.as_bytes() {
|
||||||
|
engine.input(&[*ch]);
|
||||||
|
}
|
||||||
|
let manual_hash = sha256::Hash::from_engine(engine);
|
||||||
|
assert_eq!(hash, manual_hash);
|
||||||
|
assert_eq!(hash.to_byte_array(), test.output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
fn fmt_roundtrips() {
|
||||||
|
use alloc::format;
|
||||||
|
|
||||||
|
let hash = sha256::Hash::hash(b"some arbitrary bytes");
|
||||||
|
let hex = format!("{}", hash);
|
||||||
|
let rinsed = hex.parse::<sha256::Hash>().expect("failed to parse hex");
|
||||||
|
assert_eq!(rinsed, hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[rustfmt::skip]
|
||||||
|
pub(crate) fn midstate() {
|
||||||
|
// Test vector obtained by doing an asset issuance on Elements
|
||||||
|
let mut engine = sha256::Hash::engine();
|
||||||
|
// sha256dhash of outpoint
|
||||||
|
// 73828cbc65fd68ab78dc86992b76ae50ae2bf8ceedbe8de0483172f0886219f7:0
|
||||||
|
engine.input(&[
|
||||||
|
0x9d, 0xd0, 0x1b, 0x56, 0xb1, 0x56, 0x45, 0x14,
|
||||||
|
0x3e, 0xad, 0x15, 0x8d, 0xec, 0x19, 0xf8, 0xce,
|
||||||
|
0xa9, 0x0b, 0xd0, 0xa9, 0xb2, 0xf8, 0x1d, 0x21,
|
||||||
|
0xff, 0xa3, 0xa4, 0xc6, 0x44, 0x81, 0xd4, 0x1c,
|
||||||
|
]);
|
||||||
|
// 32 bytes of zeroes representing "new asset"
|
||||||
|
engine.input(&[0; 32]);
|
||||||
|
|
||||||
|
// RPC output
|
||||||
|
static WANT: Midstate = sha256::Midstate::new([
|
||||||
|
0x0b, 0xcf, 0xe0, 0xe5, 0x4e, 0x6c, 0xc7, 0xd3,
|
||||||
|
0x4f, 0x4f, 0x7c, 0x1d, 0xf0, 0xb0, 0xf5, 0x03,
|
||||||
|
0xf2, 0xf7, 0x12, 0x91, 0x2a, 0x06, 0x05, 0xb4,
|
||||||
|
0x14, 0xed, 0x33, 0x7f, 0x7f, 0x03, 0x2e, 0x03,
|
||||||
|
], 64);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
engine.midstate().expect("total_bytes_hashed is valid"),
|
||||||
|
WANT,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn engine_with_state() {
|
||||||
|
let mut engine = sha256::Hash::engine();
|
||||||
|
let midstate_engine = sha256::HashEngine::from_midstate(engine.midstate_unchecked());
|
||||||
|
// Fresh engine and engine initialized with fresh state should have same state
|
||||||
|
assert_eq!(engine.h, midstate_engine.h);
|
||||||
|
|
||||||
|
// Midstate changes after writing 64 bytes
|
||||||
|
engine.input(&[1; 63]);
|
||||||
|
assert_eq!(engine.h, midstate_engine.h);
|
||||||
|
engine.input(&[2; 1]);
|
||||||
|
assert_ne!(engine.h, midstate_engine.h);
|
||||||
|
|
||||||
|
// Initializing an engine with midstate from another engine should result in
|
||||||
|
// both engines producing the same hashes
|
||||||
|
let data_vec: &[&[u8]] = &[&[3u8; 1], &[4u8; 63], &[5u8; 65], &[6u8; 66]];
|
||||||
|
for data in data_vec {
|
||||||
|
let mut engine = engine.clone();
|
||||||
|
let mut midstate_engine =
|
||||||
|
sha256::HashEngine::from_midstate(engine.midstate_unchecked());
|
||||||
|
assert_eq!(engine.h, midstate_engine.h);
|
||||||
|
assert_eq!(engine.bytes_hashed, midstate_engine.bytes_hashed);
|
||||||
|
engine.input(data);
|
||||||
|
midstate_engine.input(data);
|
||||||
|
assert_eq!(engine.h, midstate_engine.h);
|
||||||
|
let hash1 = sha256::Hash::from_engine(engine);
|
||||||
|
let hash2 = sha256::Hash::from_engine(midstate_engine);
|
||||||
|
assert_eq!(hash1, hash2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that a specific midstate results in a specific hash. Midstate was
|
||||||
|
// obtained by applying sha256 to sha256("MuSig coefficient")||sha256("MuSig
|
||||||
|
// coefficient").
|
||||||
|
#[rustfmt::skip]
|
||||||
|
static MIDSTATE: [u8; 32] = [
|
||||||
|
0x0f, 0xd0, 0x69, 0x0c, 0xfe, 0xfe, 0xae, 0x97,
|
||||||
|
0x99, 0x6e, 0xac, 0x7f, 0x5c, 0x30, 0xd8, 0x64,
|
||||||
|
0x8c, 0x4a, 0x05, 0x73, 0xac, 0xa1, 0xa2, 0x2f,
|
||||||
|
0x6f, 0x43, 0xb8, 0x01, 0x85, 0xce, 0x27, 0xcd,
|
||||||
|
];
|
||||||
|
#[rustfmt::skip]
|
||||||
|
static HASH_EXPECTED: [u8; 32] = [
|
||||||
|
0x18, 0x84, 0xe4, 0x72, 0x40, 0x4e, 0xf4, 0x5a,
|
||||||
|
0xb4, 0x9c, 0x4e, 0xa4, 0x9a, 0xe6, 0x23, 0xa8,
|
||||||
|
0x88, 0x52, 0x7f, 0x7d, 0x8a, 0x06, 0x94, 0x20,
|
||||||
|
0x8f, 0xf1, 0xf7, 0xa9, 0xd5, 0x69, 0x09, 0x59,
|
||||||
|
];
|
||||||
|
let midstate_engine =
|
||||||
|
sha256::HashEngine::from_midstate(sha256::Midstate::new(MIDSTATE, 64));
|
||||||
|
let hash = sha256::Hash::from_engine(midstate_engine);
|
||||||
|
assert_eq!(hash, sha256::Hash(HASH_EXPECTED));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hash_unoptimized() {
|
||||||
|
let bytes: [u8; 256] = array::from_fn(|i| i as u8);
|
||||||
|
|
||||||
|
for i in 0..=256 {
|
||||||
|
let bytes = &bytes[0..i];
|
||||||
|
assert_eq!(
|
||||||
|
Hash::hash(bytes),
|
||||||
|
Hash::hash_unoptimized(bytes),
|
||||||
|
"hashes don't match for n_bytes_hashed {}",
|
||||||
|
i + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The midstate of an empty hash engine tagged with "TapLeaf".
|
||||||
|
const TAP_LEAF_MIDSTATE: Midstate = Midstate::new(
|
||||||
|
[
|
||||||
|
156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211, 243,
|
||||||
|
147, 108, 71, 99, 110, 96, 125, 179, 62, 234, 221, 198, 240, 201,
|
||||||
|
],
|
||||||
|
64,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn const_midstate() { assert_eq!(Midstate::hash_tag(b"TapLeaf"), TAP_LEAF_MIDSTATE,) }
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
fn regression_midstate_debug_format() {
|
||||||
|
use alloc::format;
|
||||||
|
|
||||||
|
let want = "Midstate { bytes: 9ce0e4e67c116c3938b3caf2c30f5089d3f3936c47636e607db33eeaddc6f0c9, length: 64 }";
|
||||||
|
let got = format!("{:?}", TAP_LEAF_MIDSTATE);
|
||||||
|
assert_eq!(got, want);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
fn sha256_serde() {
|
||||||
|
use serde_test::{assert_tokens, Configure, Token};
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
static HASH_BYTES: [u8; 32] = [
|
||||||
|
0xef, 0x53, 0x7f, 0x25, 0xc8, 0x95, 0xbf, 0xa7,
|
||||||
|
0x82, 0x52, 0x65, 0x29, 0xa9, 0xb6, 0x3d, 0x97,
|
||||||
|
0xaa, 0x63, 0x15, 0x64, 0xd5, 0xd7, 0x89, 0xc2,
|
||||||
|
0xb7, 0x65, 0x44, 0x8c, 0x86, 0x35, 0xfb, 0x6c,
|
||||||
|
];
|
||||||
|
|
||||||
|
let hash = sha256::Hash::from_slice(&HASH_BYTES).expect("right number of bytes");
|
||||||
|
assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]);
|
||||||
|
assert_tokens(
|
||||||
|
&hash.readable(),
|
||||||
|
&[Token::Str("ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c")],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
mod wasm_tests {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
#[wasm_bindgen_test::wasm_bindgen_test]
|
||||||
|
fn sha256_tests() {
|
||||||
|
test();
|
||||||
|
midstate();
|
||||||
|
engine_with_state();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
use test::Bencher;
|
||||||
|
|
||||||
|
use crate::{sha512, Hash, HashEngine};
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn sha512_10(bh: &mut Bencher) {
|
||||||
|
let mut engine = sha512::Hash::engine();
|
||||||
|
let bytes = [1u8; 10];
|
||||||
|
bh.iter(|| {
|
||||||
|
engine.input(&bytes);
|
||||||
|
});
|
||||||
|
bh.bytes = bytes.len() as u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn sha512_1k(bh: &mut Bencher) {
|
||||||
|
let mut engine = sha512::Hash::engine();
|
||||||
|
let bytes = [1u8; 1024];
|
||||||
|
bh.iter(|| {
|
||||||
|
engine.input(&bytes);
|
||||||
|
});
|
||||||
|
bh.bytes = bytes.len() as u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
pub fn sha512_64k(bh: &mut Bencher) {
|
||||||
|
let mut engine = sha512::Hash::engine();
|
||||||
|
let bytes = [1u8; 65536];
|
||||||
|
bh.iter(|| {
|
||||||
|
engine.input(&bytes);
|
||||||
|
});
|
||||||
|
bh.bytes = bytes.len() as u64;
|
||||||
|
}
|
|
@ -2,7 +2,11 @@
|
||||||
|
|
||||||
//! SHA512 implementation.
|
//! SHA512 implementation.
|
||||||
|
|
||||||
|
#[cfg(bench)]
|
||||||
|
mod benches;
|
||||||
mod crypto;
|
mod crypto;
|
||||||
|
#[cfg(bench)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
use core::cmp;
|
use core::cmp;
|
||||||
|
|
||||||
|
@ -122,152 +126,3 @@ impl crate::HashEngine for HashEngine {
|
||||||
|
|
||||||
crate::internal_macros::engine_input_impl!();
|
crate::internal_macros::engine_input_impl!();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
fn test() {
|
|
||||||
use alloc::string::ToString;
|
|
||||||
|
|
||||||
use crate::{sha512, HashEngine};
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct Test {
|
|
||||||
input: &'static str,
|
|
||||||
output: [u8; 64],
|
|
||||||
output_str: &'static str,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
let tests = [
|
|
||||||
// Test vectors computed with `sha512sum`
|
|
||||||
Test {
|
|
||||||
input: "",
|
|
||||||
output: [
|
|
||||||
0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
|
|
||||||
0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
|
|
||||||
0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
|
|
||||||
0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
|
|
||||||
0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
|
|
||||||
0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
|
|
||||||
0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
|
|
||||||
0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e,
|
|
||||||
],
|
|
||||||
output_str: "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
|
|
||||||
},
|
|
||||||
Test {
|
|
||||||
input: "The quick brown fox jumps over the lazy dog",
|
|
||||||
output: [
|
|
||||||
0x07, 0xe5, 0x47, 0xd9, 0x58, 0x6f, 0x6a, 0x73,
|
|
||||||
0xf7, 0x3f, 0xba, 0xc0, 0x43, 0x5e, 0xd7, 0x69,
|
|
||||||
0x51, 0x21, 0x8f, 0xb7, 0xd0, 0xc8, 0xd7, 0x88,
|
|
||||||
0xa3, 0x09, 0xd7, 0x85, 0x43, 0x6b, 0xbb, 0x64,
|
|
||||||
0x2e, 0x93, 0xa2, 0x52, 0xa9, 0x54, 0xf2, 0x39,
|
|
||||||
0x12, 0x54, 0x7d, 0x1e, 0x8a, 0x3b, 0x5e, 0xd6,
|
|
||||||
0xe1, 0xbf, 0xd7, 0x09, 0x78, 0x21, 0x23, 0x3f,
|
|
||||||
0xa0, 0x53, 0x8f, 0x3d, 0xb8, 0x54, 0xfe, 0xe6,
|
|
||||||
],
|
|
||||||
output_str: "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6",
|
|
||||||
},
|
|
||||||
Test {
|
|
||||||
input: "The quick brown fox jumps over the lazy dog.",
|
|
||||||
output: [
|
|
||||||
0x91, 0xea, 0x12, 0x45, 0xf2, 0x0d, 0x46, 0xae,
|
|
||||||
0x9a, 0x03, 0x7a, 0x98, 0x9f, 0x54, 0xf1, 0xf7,
|
|
||||||
0x90, 0xf0, 0xa4, 0x76, 0x07, 0xee, 0xb8, 0xa1,
|
|
||||||
0x4d, 0x12, 0x89, 0x0c, 0xea, 0x77, 0xa1, 0xbb,
|
|
||||||
0xc6, 0xc7, 0xed, 0x9c, 0xf2, 0x05, 0xe6, 0x7b,
|
|
||||||
0x7f, 0x2b, 0x8f, 0xd4, 0xc7, 0xdf, 0xd3, 0xa7,
|
|
||||||
0xa8, 0x61, 0x7e, 0x45, 0xf3, 0xc4, 0x63, 0xd4,
|
|
||||||
0x81, 0xc7, 0xe5, 0x86, 0xc3, 0x9a, 0xc1, 0xed,
|
|
||||||
],
|
|
||||||
output_str: "91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for test in tests {
|
|
||||||
// Hash through high-level API, check hex encoding/decoding
|
|
||||||
let hash = sha512::Hash::hash(test.input.as_bytes());
|
|
||||||
assert_eq!(hash, test.output_str.parse::<sha512::Hash>().expect("parse hex"));
|
|
||||||
assert_eq!(hash.as_byte_array(), &test.output);
|
|
||||||
assert_eq!(hash.to_string(), test.output_str);
|
|
||||||
|
|
||||||
// Hash through engine, checking that we can input byte by byte
|
|
||||||
let mut engine = sha512::Hash::engine();
|
|
||||||
for ch in test.input.as_bytes() {
|
|
||||||
engine.input(&[*ch]);
|
|
||||||
}
|
|
||||||
let manual_hash = sha512::Hash::from_engine(engine);
|
|
||||||
assert_eq!(hash, manual_hash);
|
|
||||||
assert_eq!(hash.to_byte_array(), test.output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
fn sha512_serde() {
|
|
||||||
use serde_test::{assert_tokens, Configure, Token};
|
|
||||||
|
|
||||||
use crate::sha512;
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
static HASH_BYTES: [u8; 64] = [
|
|
||||||
0x8b, 0x41, 0xe1, 0xb7, 0x8a, 0xd1, 0x15, 0x21,
|
|
||||||
0x11, 0x3c, 0x52, 0xff, 0x18, 0x2a, 0x1b, 0x8e,
|
|
||||||
0x0a, 0x19, 0x57, 0x54, 0xaa, 0x52, 0x7f, 0xcd,
|
|
||||||
0x00, 0xa4, 0x11, 0x62, 0x0b, 0x46, 0xf2, 0x0f,
|
|
||||||
0xff, 0xfb, 0x80, 0x88, 0xcc, 0xf8, 0x54, 0x97,
|
|
||||||
0x12, 0x1a, 0xd4, 0x49, 0x9e, 0x08, 0x45, 0xb8,
|
|
||||||
0x76, 0xf6, 0xdd, 0x66, 0x40, 0x08, 0x8a, 0x2f,
|
|
||||||
0x0b, 0x2d, 0x8a, 0x60, 0x0b, 0xdf, 0x4c, 0x0c,
|
|
||||||
];
|
|
||||||
|
|
||||||
let hash = sha512::Hash::from_slice(&HASH_BYTES).expect("right number of bytes");
|
|
||||||
assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]);
|
|
||||||
assert_tokens(
|
|
||||||
&hash.readable(),
|
|
||||||
&[Token::Str(
|
|
||||||
"8b41e1b78ad11521113c52ff182a1b8e0a195754aa527fcd00a411620b46f20f\
|
|
||||||
fffb8088ccf85497121ad4499e0845b876f6dd6640088a2f0b2d8a600bdf4c0c",
|
|
||||||
)],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(bench)]
|
|
||||||
mod benches {
|
|
||||||
use test::Bencher;
|
|
||||||
|
|
||||||
use crate::{sha512, Hash, HashEngine};
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
pub fn sha512_10(bh: &mut Bencher) {
|
|
||||||
let mut engine = sha512::Hash::engine();
|
|
||||||
let bytes = [1u8; 10];
|
|
||||||
bh.iter(|| {
|
|
||||||
engine.input(&bytes);
|
|
||||||
});
|
|
||||||
bh.bytes = bytes.len() as u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
pub fn sha512_1k(bh: &mut Bencher) {
|
|
||||||
let mut engine = sha512::Hash::engine();
|
|
||||||
let bytes = [1u8; 1024];
|
|
||||||
bh.iter(|| {
|
|
||||||
engine.input(&bytes);
|
|
||||||
});
|
|
||||||
bh.bytes = bytes.len() as u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
pub fn sha512_64k(bh: &mut Bencher) {
|
|
||||||
let mut engine = sha512::Hash::engine();
|
|
||||||
let bytes = [1u8; 65536];
|
|
||||||
bh.iter(|| {
|
|
||||||
engine.input(&bytes);
|
|
||||||
});
|
|
||||||
bh.bytes = bytes.len() as u64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
fn test() {
|
||||||
|
use alloc::string::ToString;
|
||||||
|
|
||||||
|
use crate::{sha512, HashEngine};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Test {
|
||||||
|
input: &'static str,
|
||||||
|
output: [u8; 64],
|
||||||
|
output_str: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
let tests = [
|
||||||
|
// Test vectors computed with `sha512sum`
|
||||||
|
Test {
|
||||||
|
input: "",
|
||||||
|
output: [
|
||||||
|
0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
|
||||||
|
0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
|
||||||
|
0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
|
||||||
|
0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
|
||||||
|
0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
|
||||||
|
0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
|
||||||
|
0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
|
||||||
|
0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e,
|
||||||
|
],
|
||||||
|
output_str: "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
|
||||||
|
},
|
||||||
|
Test {
|
||||||
|
input: "The quick brown fox jumps over the lazy dog",
|
||||||
|
output: [
|
||||||
|
0x07, 0xe5, 0x47, 0xd9, 0x58, 0x6f, 0x6a, 0x73,
|
||||||
|
0xf7, 0x3f, 0xba, 0xc0, 0x43, 0x5e, 0xd7, 0x69,
|
||||||
|
0x51, 0x21, 0x8f, 0xb7, 0xd0, 0xc8, 0xd7, 0x88,
|
||||||
|
0xa3, 0x09, 0xd7, 0x85, 0x43, 0x6b, 0xbb, 0x64,
|
||||||
|
0x2e, 0x93, 0xa2, 0x52, 0xa9, 0x54, 0xf2, 0x39,
|
||||||
|
0x12, 0x54, 0x7d, 0x1e, 0x8a, 0x3b, 0x5e, 0xd6,
|
||||||
|
0xe1, 0xbf, 0xd7, 0x09, 0x78, 0x21, 0x23, 0x3f,
|
||||||
|
0xa0, 0x53, 0x8f, 0x3d, 0xb8, 0x54, 0xfe, 0xe6,
|
||||||
|
],
|
||||||
|
output_str: "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6",
|
||||||
|
},
|
||||||
|
Test {
|
||||||
|
input: "The quick brown fox jumps over the lazy dog.",
|
||||||
|
output: [
|
||||||
|
0x91, 0xea, 0x12, 0x45, 0xf2, 0x0d, 0x46, 0xae,
|
||||||
|
0x9a, 0x03, 0x7a, 0x98, 0x9f, 0x54, 0xf1, 0xf7,
|
||||||
|
0x90, 0xf0, 0xa4, 0x76, 0x07, 0xee, 0xb8, 0xa1,
|
||||||
|
0x4d, 0x12, 0x89, 0x0c, 0xea, 0x77, 0xa1, 0xbb,
|
||||||
|
0xc6, 0xc7, 0xed, 0x9c, 0xf2, 0x05, 0xe6, 0x7b,
|
||||||
|
0x7f, 0x2b, 0x8f, 0xd4, 0xc7, 0xdf, 0xd3, 0xa7,
|
||||||
|
0xa8, 0x61, 0x7e, 0x45, 0xf3, 0xc4, 0x63, 0xd4,
|
||||||
|
0x81, 0xc7, 0xe5, 0x86, 0xc3, 0x9a, 0xc1, 0xed,
|
||||||
|
],
|
||||||
|
output_str: "91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for test in tests {
|
||||||
|
// Hash through high-level API, check hex encoding/decoding
|
||||||
|
let hash = sha512::Hash::hash(test.input.as_bytes());
|
||||||
|
assert_eq!(hash, test.output_str.parse::<sha512::Hash>().expect("parse hex"));
|
||||||
|
assert_eq!(hash.as_byte_array(), &test.output);
|
||||||
|
assert_eq!(hash.to_string(), test.output_str);
|
||||||
|
|
||||||
|
// Hash through engine, checking that we can input byte by byte
|
||||||
|
let mut engine = sha512::Hash::engine();
|
||||||
|
for ch in test.input.as_bytes() {
|
||||||
|
engine.input(&[*ch]);
|
||||||
|
}
|
||||||
|
let manual_hash = sha512::Hash::from_engine(engine);
|
||||||
|
assert_eq!(hash, manual_hash);
|
||||||
|
assert_eq!(hash.to_byte_array(), test.output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
fn sha512_serde() {
|
||||||
|
use serde_test::{assert_tokens, Configure, Token};
|
||||||
|
|
||||||
|
use crate::sha512;
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
static HASH_BYTES: [u8; 64] = [
|
||||||
|
0x8b, 0x41, 0xe1, 0xb7, 0x8a, 0xd1, 0x15, 0x21,
|
||||||
|
0x11, 0x3c, 0x52, 0xff, 0x18, 0x2a, 0x1b, 0x8e,
|
||||||
|
0x0a, 0x19, 0x57, 0x54, 0xaa, 0x52, 0x7f, 0xcd,
|
||||||
|
0x00, 0xa4, 0x11, 0x62, 0x0b, 0x46, 0xf2, 0x0f,
|
||||||
|
0xff, 0xfb, 0x80, 0x88, 0xcc, 0xf8, 0x54, 0x97,
|
||||||
|
0x12, 0x1a, 0xd4, 0x49, 0x9e, 0x08, 0x45, 0xb8,
|
||||||
|
0x76, 0xf6, 0xdd, 0x66, 0x40, 0x08, 0x8a, 0x2f,
|
||||||
|
0x0b, 0x2d, 0x8a, 0x60, 0x0b, 0xdf, 0x4c, 0x0c,
|
||||||
|
];
|
||||||
|
|
||||||
|
let hash = sha512::Hash::from_slice(&HASH_BYTES).expect("right number of bytes");
|
||||||
|
assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]);
|
||||||
|
assert_tokens(
|
||||||
|
&hash.readable(),
|
||||||
|
&[Token::Str(
|
||||||
|
"8b41e1b78ad11521113c52ff182a1b8e0a195754aa527fcd00a411620b46f20f\
|
||||||
|
fffb8088ccf85497121ad4499e0845b876f6dd6640088a2f0b2d8a600bdf4c0c",
|
||||||
|
)],
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue