diff options
| author | Jack O'Connor <[email protected]> | 2019-12-11 10:50:18 -0500 |
|---|---|---|
| committer | Jack O'Connor <[email protected]> | 2019-12-11 10:50:18 -0500 |
| commit | c81d5c2522034357b8a719df24860d70f44eea8d (patch) | |
| tree | 2c99a857102ce52d06aeb233043332d529d35016 /test_vectors | |
| parent | 48b3fba83318ddd0ea7b6d715d2d01a00d4a9399 (diff) | |
test against test_vectors.json in CI
Diffstat (limited to 'test_vectors')
| -rw-r--r-- | test_vectors/src/bin/generate.rs | 25 | ||||
| -rw-r--r-- | test_vectors/src/lib.rs | 214 |
2 files changed, 216 insertions, 23 deletions
diff --git a/test_vectors/src/bin/generate.rs b/test_vectors/src/bin/generate.rs index 290d335..9fb8ba4 100644 --- a/test_vectors/src/bin/generate.rs +++ b/test_vectors/src/bin/generate.rs @@ -1,24 +1,7 @@ -use serde::Serialize; - // A non-multiple of 4 is important, since one possible bug is to fail to emit // partial words. const OUTPUT_LEN: usize = 2 * blake3::BLOCK_LEN + 3; -#[derive(Serialize)] -struct Cases { - _comment: &'static str, - key: &'static str, - cases: Vec<Case>, -} - -#[derive(Serialize)] -struct Case { - input_len: usize, - hash: String, - keyed_hash: String, - derive_key: String, -} - fn main() { let mut cases = Vec::new(); for &input_len in test_vectors::TEST_CASES { @@ -40,7 +23,7 @@ fn main() { .update(&input) .finalize_xof(&mut derive_key_out); - cases.push(Case { + cases.push(test_vectors::Case { input_len, hash: hex::encode(&hash_out[..]), keyed_hash: hex::encode(&keyed_hash_out[..]), @@ -48,9 +31,9 @@ fn main() { }); } - let output = serde_json::to_string_pretty(&Cases { - _comment: "Each test is an input length and three outputs, one for each of the hash, keyed_hash, and derive_key modes. The input in each case is filled with a 251-byte-long repeating pattern: 0, 1, 2, ..., 249, 250, 0, 1, ... The key used with keyed_hash and derive_key is the 32-byte ASCII string given below. Outputs are encoded as hexadecimal. Each case is an extended output, and implementations should also check that the first 32 bytes match their default-length output.", - key: std::str::from_utf8(test_vectors::TEST_KEY).unwrap(), + let output = serde_json::to_string_pretty(&test_vectors::Cases { + _comment: "Each test is an input length and three outputs, one for each of the hash, keyed_hash, and derive_key modes. The input in each case is filled with a 251-byte-long repeating pattern: 0, 1, 2, ..., 249, 250, 0, 1, ... The key used with keyed_hash and derive_key is the 32-byte ASCII string given below. Outputs are encoded as hexadecimal. Each case is an extended output, and implementations should also check that the first 32 bytes match their default-length output.".to_string(), + key: std::str::from_utf8(test_vectors::TEST_KEY).unwrap().to_string(), cases, }).unwrap(); diff --git a/test_vectors/src/lib.rs b/test_vectors/src/lib.rs index e38d9f2..51eb595 100644 --- a/test_vectors/src/lib.rs +++ b/test_vectors/src/lib.rs @@ -1,4 +1,5 @@ use blake3::CHUNK_LEN; +use serde::{Deserialize, Serialize}; pub const TEST_CASES: &[usize] = &[ 0, @@ -36,10 +37,219 @@ pub fn paint_test_input(buf: &mut [u8]) { } } +#[derive(Serialize, Deserialize)] +pub struct Cases { + pub _comment: String, + pub key: String, + pub cases: Vec<Case>, +} + +#[derive(Serialize, Deserialize)] +pub struct Case { + pub input_len: usize, + pub hash: String, + pub keyed_hash: String, + pub derive_key: String, +} + #[cfg(test)] mod tests { + use super::*; + use std::convert::TryInto; + + fn test_reference_impl_all_at_once( + key: &[u8; blake3::KEY_LEN], + input: &[u8], + expected_hash: &[u8], + expected_keyed_hash: &[u8], + expected_derive_key: &[u8], + ) { + let mut out = vec![0; expected_hash.len()]; + let mut hasher = reference_impl::Hasher::new(); + hasher.update(input); + hasher.finalize(&mut out); + assert_eq!(expected_hash, &out[..]); + + let mut out = vec![0; expected_keyed_hash.len()]; + let mut hasher = reference_impl::Hasher::new_keyed(key); + hasher.update(input); + hasher.finalize(&mut out); + assert_eq!(expected_keyed_hash, &out[..]); + + let mut out = vec![0; expected_derive_key.len()]; + let mut hasher = reference_impl::Hasher::new_derive_key(key); + hasher.update(input); + hasher.finalize(&mut out); + assert_eq!(expected_derive_key, &out[..]); + } + + fn test_reference_impl_one_at_a_time( + key: &[u8; blake3::KEY_LEN], + input: &[u8], + expected_hash: &[u8], + expected_keyed_hash: &[u8], + expected_derive_key: &[u8], + ) { + let mut out = vec![0; expected_hash.len()]; + let mut hasher = reference_impl::Hasher::new(); + for &b in input { + hasher.update(&[b]); + } + hasher.finalize(&mut out); + assert_eq!(expected_hash, &out[..]); + + let mut out = vec![0; expected_keyed_hash.len()]; + let mut hasher = reference_impl::Hasher::new_keyed(key); + for &b in input { + hasher.update(&[b]); + } + hasher.finalize(&mut out); + assert_eq!(expected_keyed_hash, &out[..]); + + let mut out = vec![0; expected_derive_key.len()]; + let mut hasher = reference_impl::Hasher::new_derive_key(key); + for &b in input { + hasher.update(&[b]); + } + hasher.finalize(&mut out); + assert_eq!(expected_derive_key, &out[..]); + } + + fn test_incremental_all_at_once( + key: &[u8; blake3::KEY_LEN], + input: &[u8], + expected_hash: &[u8], + expected_keyed_hash: &[u8], + expected_derive_key: &[u8], + ) { + let mut out = vec![0; expected_hash.len()]; + let mut hasher = blake3::Hasher::new(); + hasher.update(input); + hasher.finalize_xof(&mut out); + assert_eq!(expected_hash, &out[..]); + assert_eq!(&expected_hash[..32], hasher.finalize().as_bytes()); + + let mut out = vec![0; expected_keyed_hash.len()]; + let mut hasher = blake3::Hasher::new_keyed(key); + hasher.update(input); + hasher.finalize_xof(&mut out); + assert_eq!(expected_keyed_hash, &out[..]); + assert_eq!(&expected_keyed_hash[..32], hasher.finalize().as_bytes()); + + let mut out = vec![0; expected_derive_key.len()]; + let mut hasher = blake3::Hasher::new_derive_key(key); + hasher.update(input); + hasher.finalize_xof(&mut out); + assert_eq!(expected_derive_key, &out[..]); + assert_eq!(&expected_derive_key[..32], hasher.finalize().as_bytes()); + } + + fn test_incremental_one_at_a_time( + key: &[u8; blake3::KEY_LEN], + input: &[u8], + expected_hash: &[u8], + expected_keyed_hash: &[u8], + expected_derive_key: &[u8], + ) { + let mut out = vec![0; expected_hash.len()]; + let mut hasher = blake3::Hasher::new(); + for &b in input { + hasher.update(&[b]); + } + hasher.finalize_xof(&mut out); + assert_eq!(expected_hash, &out[..]); + assert_eq!(&expected_hash[..32], hasher.finalize().as_bytes()); + + let mut out = vec![0; expected_keyed_hash.len()]; + let mut hasher = blake3::Hasher::new_keyed(key); + for &b in input { + hasher.update(&[b]); + } + hasher.finalize_xof(&mut out); + assert_eq!(expected_keyed_hash, &out[..]); + assert_eq!(&expected_keyed_hash[..32], hasher.finalize().as_bytes()); + + let mut out = vec![0; expected_derive_key.len()]; + let mut hasher = blake3::Hasher::new_derive_key(key); + for &b in input { + hasher.update(&[b]); + } + hasher.finalize_xof(&mut out); + assert_eq!(expected_derive_key, &out[..]); + assert_eq!(&expected_derive_key[..32], hasher.finalize().as_bytes()); + } + + fn test_recursive( + key: &[u8; blake3::KEY_LEN], + input: &[u8], + expected_hash: &[u8], + expected_keyed_hash: &[u8], + expected_derive_key: &[u8], + ) { + assert_eq!(&expected_hash[..32], blake3::hash(input).as_bytes()); + assert_eq!( + &expected_keyed_hash[..32], + blake3::keyed_hash(key, input).as_bytes() + ); + assert_eq!( + &expected_derive_key[..32], + blake3::derive_key(key, input).as_bytes() + ); + } + #[test] - fn it_works() { - assert_eq!(2 + 2, 4); + fn run_test_vectors() -> Result<(), Box<dyn std::error::Error>> { + let test_vectors_file_path = "./test_vectors.json"; + let test_vectors_json = std::fs::read_to_string(test_vectors_file_path)?; + let cases: Cases = serde_json::from_str(&test_vectors_json)?; + let key: &[u8; blake3::KEY_LEN] = cases.key.as_bytes().try_into()?; + for case in &cases.cases { + let mut input = vec![0; case.input_len]; + paint_test_input(&mut input); + let expected_hash = hex::decode(&case.hash)?; + let expected_keyed_hash = hex::decode(&case.keyed_hash)?; + let expected_derive_key = hex::decode(&case.derive_key)?; + + test_reference_impl_all_at_once( + key, + &input, + &expected_hash, + &expected_keyed_hash, + &expected_derive_key, + ); + + test_reference_impl_one_at_a_time( + key, + &input, + &expected_hash, + &expected_keyed_hash, + &expected_derive_key, + ); + + test_incremental_all_at_once( + key, + &input, + &expected_hash, + &expected_keyed_hash, + &expected_derive_key, + ); + + test_incremental_one_at_a_time( + key, + &input, + &expected_hash, + &expected_keyed_hash, + &expected_derive_key, + ); + + test_recursive( + key, + &input, + &expected_hash, + &expected_keyed_hash, + &expected_derive_key, + ); + } + Ok(()) } } |
