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:
Tobin C. Harding 2025-01-29 10:28:14 +11:00
parent 665fa9de99
commit 7be0db730a
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
12 changed files with 684 additions and 700 deletions

View File

@ -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;
}

View File

@ -2,7 +2,11 @@
//! RIPEMD160 implementation.
#[cfg(bench)]
mod benches;
mod crypto;
#[cfg(bench)]
mod tests;
use core::cmp;
@ -89,149 +93,3 @@ impl crate::HashEngine for HashEngine {
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;
}
}

View File

@ -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")]);
}

View File

@ -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;
}

View File

@ -2,7 +2,11 @@
//! SHA1 implementation.
#[cfg(bench)]
mod benches;
mod crypto;
#[cfg(bench)]
mod tests;
use core::cmp;
@ -81,134 +85,3 @@ impl crate::HashEngine for HashEngine {
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;
}
}

90
hashes/src/sha1/tests.rs Normal file
View File

@ -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")]);
}

View File

@ -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;
}

View File

@ -2,7 +2,11 @@
//! SHA256 implementation.
#[cfg(bench)]
mod benches;
mod crypto;
#[cfg(bench)]
mod tests;
use core::{cmp, convert, fmt};
@ -253,277 +257,3 @@ impl fmt::Display for MidstateError {
#[cfg(feature = "std")]
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;
}
}

233
hashes/src/sha256/tests.rs Normal file
View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -2,7 +2,11 @@
//! SHA512 implementation.
#[cfg(bench)]
mod benches;
mod crypto;
#[cfg(bench)]
mod tests;
use core::cmp;
@ -122,152 +126,3 @@ impl crate::HashEngine for HashEngine {
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;
}
}

108
hashes/src/sha512/tests.rs Normal file
View File

@ -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",
)],
);
}