aboutsummaryrefslogtreecommitdiff
path: root/test_vectors
diff options
context:
space:
mode:
authorJack O'Connor <[email protected]>2019-12-11 10:50:18 -0500
committerJack O'Connor <[email protected]>2019-12-11 10:50:18 -0500
commitc81d5c2522034357b8a719df24860d70f44eea8d (patch)
tree2c99a857102ce52d06aeb233043332d529d35016 /test_vectors
parent48b3fba83318ddd0ea7b6d715d2d01a00d4a9399 (diff)
test against test_vectors.json in CI
Diffstat (limited to 'test_vectors')
-rw-r--r--test_vectors/src/bin/generate.rs25
-rw-r--r--test_vectors/src/lib.rs214
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(())
}
}