From 7be0db730a2295c78f1a28bdd0061b62f1aa9881 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 29 Jan 2025 10:28:14 +1100 Subject: [PATCH] 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. --- hashes/src/ripemd160/benches.rs | 33 ++++ hashes/src/ripemd160/mod.rs | 150 +---------------- hashes/src/ripemd160/tests.rs | 105 ++++++++++++ hashes/src/sha1/benches.rs | 33 ++++ hashes/src/sha1/mod.rs | 135 +--------------- hashes/src/sha1/tests.rs | 90 +++++++++++ hashes/src/sha256/benches.rs | 33 ++++ hashes/src/sha256/mod.rs | 278 +------------------------------- hashes/src/sha256/tests.rs | 233 ++++++++++++++++++++++++++ hashes/src/sha512/benches.rs | 33 ++++ hashes/src/sha512/mod.rs | 153 +----------------- hashes/src/sha512/tests.rs | 108 +++++++++++++ 12 files changed, 684 insertions(+), 700 deletions(-) create mode 100644 hashes/src/ripemd160/benches.rs create mode 100644 hashes/src/ripemd160/tests.rs create mode 100644 hashes/src/sha1/benches.rs create mode 100644 hashes/src/sha1/tests.rs create mode 100644 hashes/src/sha256/benches.rs create mode 100644 hashes/src/sha256/tests.rs create mode 100644 hashes/src/sha512/benches.rs create mode 100644 hashes/src/sha512/tests.rs diff --git a/hashes/src/ripemd160/benches.rs b/hashes/src/ripemd160/benches.rs new file mode 100644 index 000000000..cb023a933 --- /dev/null +++ b/hashes/src/ripemd160/benches.rs @@ -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; +} diff --git a/hashes/src/ripemd160/mod.rs b/hashes/src/ripemd160/mod.rs index 8ef659770..759900ce2 100644 --- a/hashes/src/ripemd160/mod.rs +++ b/hashes/src/ripemd160/mod.rs @@ -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::().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; - } -} diff --git a/hashes/src/ripemd160/tests.rs b/hashes/src/ripemd160/tests.rs new file mode 100644 index 000000000..d6340591c --- /dev/null +++ b/hashes/src/ripemd160/tests.rs @@ -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::().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")]); +} diff --git a/hashes/src/sha1/benches.rs b/hashes/src/sha1/benches.rs new file mode 100644 index 000000000..fcf2518df --- /dev/null +++ b/hashes/src/sha1/benches.rs @@ -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; +} diff --git a/hashes/src/sha1/mod.rs b/hashes/src/sha1/mod.rs index f0748c33b..6c198d185 100644 --- a/hashes/src/sha1/mod.rs +++ b/hashes/src/sha1/mod.rs @@ -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::().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; - } -} diff --git a/hashes/src/sha1/tests.rs b/hashes/src/sha1/tests.rs new file mode 100644 index 000000000..2bfe37b1c --- /dev/null +++ b/hashes/src/sha1/tests.rs @@ -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::().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")]); +} diff --git a/hashes/src/sha256/benches.rs b/hashes/src/sha256/benches.rs new file mode 100644 index 000000000..f6e270d90 --- /dev/null +++ b/hashes/src/sha256/benches.rs @@ -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; +} diff --git a/hashes/src/sha256/mod.rs b/hashes/src/sha256/mod.rs index cd6beb24f..70bf9121b 100644 --- a/hashes/src/sha256/mod.rs +++ b/hashes/src/sha256/mod.rs @@ -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::().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::().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; - } -} diff --git a/hashes/src/sha256/tests.rs b/hashes/src/sha256/tests.rs new file mode 100644 index 000000000..2d8d099d7 --- /dev/null +++ b/hashes/src/sha256/tests.rs @@ -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::().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::().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(); + } +} diff --git a/hashes/src/sha512/benches.rs b/hashes/src/sha512/benches.rs new file mode 100644 index 000000000..56b71800b --- /dev/null +++ b/hashes/src/sha512/benches.rs @@ -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; +} diff --git a/hashes/src/sha512/mod.rs b/hashes/src/sha512/mod.rs index 4db0bec54..f72f62e56 100644 --- a/hashes/src/sha512/mod.rs +++ b/hashes/src/sha512/mod.rs @@ -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::().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; - } -} diff --git a/hashes/src/sha512/tests.rs b/hashes/src/sha512/tests.rs new file mode 100644 index 000000000..4b46f0176 --- /dev/null +++ b/hashes/src/sha512/tests.rs @@ -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::().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", + )], + ); +}