mirror of
https://github.com/BLAKE3-team/BLAKE3
synced 2024-06-07 07:06:05 +02:00
hash_chunks and hash_parents
This commit is contained in:
parent
1cb2797abc
commit
2722065bb4
|
@ -1,5 +1,6 @@
|
|||
use crate::{portable, CVWords, IncrementCounter, BLOCK_LEN, CHUNK_LEN, UNIVERSAL_HASH_LEN};
|
||||
use arrayref::{array_mut_ref, array_ref};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
|
||||
|
@ -295,19 +296,10 @@ impl Platform {
|
|||
// XXX: should separate the thing that hashes the remainder from this interface
|
||||
}
|
||||
|
||||
// Writes out N=num_cvs/2 transposed parent CVs in-place over the first N columns of the input
|
||||
// CVs. Columns N and above are unmodified. N must be less than or equal to 2*simd_degree. If
|
||||
// num_cvs is odd, the final input CV is ignored, and the caller should copy it from column
|
||||
// 2N+1 to column N after this function returns. The PARENT flag is added internally.
|
||||
pub fn hash_parents(
|
||||
&self,
|
||||
cvs: &mut TransposedVectors,
|
||||
num_cvs: usize,
|
||||
key: &[u32; 8],
|
||||
flags: u8,
|
||||
) {
|
||||
debug_assert!(num_cvs <= 2 * self.simd_degree());
|
||||
portable::hash_parents(cvs, num_cvs, key, flags);
|
||||
pub fn hash_parents(&self, in_out: ParentInOut, key: &[u32; 8], flags: u8) {
|
||||
let (_, num_parents) = in_out.input();
|
||||
debug_assert!(num_parents <= self.simd_degree());
|
||||
portable::hash_parents(in_out, key, flags);
|
||||
// XXX: should separate the thing that copies the last CV over from this interface
|
||||
}
|
||||
|
||||
|
@ -559,6 +551,58 @@ pub fn le_bytes_from_words_64(words: &[u32; 16]) -> [u8; 64] {
|
|||
}
|
||||
|
||||
#[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), repr(C, align(64)))]
|
||||
#[derive(Default)]
|
||||
pub struct TransposedVectors(pub [[u32; 2 * MAX_SIMD_DEGREE]; 8]);
|
||||
|
||||
pub struct StridedOutput(*mut u32);
|
||||
impl Deref for TransposedVectors {
|
||||
type Target = [[u32; 2 * MAX_SIMD_DEGREE]; 8];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for TransposedVectors {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ParentInOut<'a> {
|
||||
InPlace {
|
||||
in_out: &'a mut TransposedVectors,
|
||||
num_parents: usize,
|
||||
},
|
||||
Separate {
|
||||
input: &'a TransposedVectors,
|
||||
num_parents: usize,
|
||||
output: &'a mut TransposedVectors,
|
||||
output_column: usize,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a> ParentInOut<'a> {
|
||||
// (vectors, num_parents)
|
||||
pub fn input(&self) -> (&TransposedVectors, usize) {
|
||||
match self {
|
||||
ParentInOut::InPlace {
|
||||
in_out,
|
||||
num_parents,
|
||||
} => (in_out, *num_parents),
|
||||
ParentInOut::Separate {
|
||||
input, num_parents, ..
|
||||
} => (input, *num_parents),
|
||||
}
|
||||
}
|
||||
|
||||
// (vectors, output_column)
|
||||
pub fn output(&mut self) -> (&mut TransposedVectors, usize) {
|
||||
match self {
|
||||
ParentInOut::InPlace { in_out, .. } => (in_out, 0),
|
||||
ParentInOut::Separate {
|
||||
output,
|
||||
output_column,
|
||||
..
|
||||
} => (output, *output_column),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::platform::{ParentInOut, TransposedVectors};
|
||||
use crate::{
|
||||
counter_high, counter_low, platform::TransposedVectors, CVBytes, CVWords, IncrementCounter,
|
||||
BLOCK_LEN, CHUNK_LEN, IV, MSG_SCHEDULE, OUT_LEN, UNIVERSAL_HASH_LEN,
|
||||
counter_high, counter_low, CVBytes, CVWords, IncrementCounter, BLOCK_LEN, CHUNK_LEN, IV,
|
||||
MSG_SCHEDULE, OUT_LEN, UNIVERSAL_HASH_LEN,
|
||||
};
|
||||
use arrayref::{array_mut_ref, array_ref};
|
||||
use core::cmp;
|
||||
|
@ -178,46 +179,68 @@ pub fn hash_many<const N: usize>(
|
|||
}
|
||||
}
|
||||
|
||||
/// General contract:
|
||||
/// - `input` is N chunks, each exactly 1 KiB, 1 <= N <= DEGREE
|
||||
/// - `output_column` is a multiple of DEGREE.
|
||||
/// The CHUNK_START and CHUNK_END flags are set internally. Writes N transposed CVs to the output,
|
||||
/// from `output_column` to `output_column+N-1`. Columns prior to `output_column` must be
|
||||
/// unmodified.
|
||||
///
|
||||
/// The DEGREE of this portable implementation is 1, so the input here is always exactly 1 KiB.
|
||||
pub fn hash_chunks(
|
||||
input: &[u8],
|
||||
key: &[u32; 8],
|
||||
counter: u64,
|
||||
flags: u8,
|
||||
output: &mut TransposedVectors,
|
||||
output_offset: usize,
|
||||
output_column: usize,
|
||||
) {
|
||||
const LAST_BLOCK_INDEX: usize = (CHUNK_LEN / BLOCK_LEN) - 1;
|
||||
// There might be a partial chunk at the end. If so, we ignore it here, and the caller will
|
||||
// hash it separately.
|
||||
let num_chunks = input.len() / CHUNK_LEN;
|
||||
for chunk_index in 0..num_chunks {
|
||||
let mut cv = *key;
|
||||
for block_index in 0..CHUNK_LEN / BLOCK_LEN {
|
||||
compress_in_place(
|
||||
&mut cv,
|
||||
input[CHUNK_LEN * chunk_index + BLOCK_LEN * block_index..][..BLOCK_LEN]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
BLOCK_LEN as u8,
|
||||
counter + chunk_index as u64,
|
||||
match block_index {
|
||||
0 => flags | crate::CHUNK_START,
|
||||
LAST_BLOCK_INDEX => flags | crate::CHUNK_END,
|
||||
_ => flags,
|
||||
},
|
||||
);
|
||||
}
|
||||
for word_index in 0..cv.len() {
|
||||
output.0[word_index][output_offset + chunk_index] = cv[word_index];
|
||||
}
|
||||
debug_assert_eq!(CHUNK_LEN, input.len());
|
||||
let mut cv = *key;
|
||||
for block_index in 0..16 {
|
||||
let block_flags = match block_index {
|
||||
0 => flags | crate::CHUNK_START,
|
||||
15 => flags | crate::CHUNK_END,
|
||||
_ => flags,
|
||||
};
|
||||
compress_in_place(
|
||||
&mut cv,
|
||||
input[BLOCK_LEN * block_index..][..BLOCK_LEN]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
BLOCK_LEN as u8,
|
||||
counter as u64,
|
||||
block_flags,
|
||||
);
|
||||
}
|
||||
for word_index in 0..cv.len() {
|
||||
output[word_index][output_column] = cv[word_index];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hash_parents(cvs: &mut TransposedVectors, num_cvs: usize, key: &[u32; 8], flags: u8) {
|
||||
// Note that there may be an odd number of children. If there's a leftover child, it gets
|
||||
// appended to the outputs by the caller. We will not overwrite it.
|
||||
let num_parents = num_cvs / 2;
|
||||
todo!()
|
||||
/// General contract:
|
||||
/// - `cvs` contains `2*num_parents` transposed CVs, 1 <= num_parents <= DEGREE, starting at column 0
|
||||
/// There may be additional CVs present beyond the `2*num_parents` CVs indicated, but this function
|
||||
/// isn't aware of them and must not modify them. No flags are set internally (the caller must set
|
||||
/// `PARENT` in `flags`). Writes `num_parents` transposed parent CVs to the output, starting at
|
||||
/// column 0.
|
||||
///
|
||||
/// The DEGREE of this portable implementation is 1, so the input here is always exactly 2 CVs
|
||||
/// (num_parents == 1).
|
||||
pub fn hash_parents(mut in_out: ParentInOut, key: &[u32; 8], flags: u8) {
|
||||
let (input, num_parents) = in_out.input();
|
||||
debug_assert_eq!(num_parents, 1);
|
||||
let mut block = [0u8; BLOCK_LEN];
|
||||
for i in 0..8 {
|
||||
block[4 * i..][..4].copy_from_slice(&input[i][0].to_le_bytes());
|
||||
block[4 * (i + 8)..][..4].copy_from_slice(&input[i][1].to_le_bytes());
|
||||
}
|
||||
let mut cv = *key;
|
||||
compress_in_place(&mut cv, &block, BLOCK_LEN as u8, 0, flags);
|
||||
let (output, output_column) = in_out.output();
|
||||
for i in 0..8 {
|
||||
output[i][output_column] = cv[i];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn xof(
|
||||
|
@ -290,6 +313,8 @@ pub fn universal_hash(
|
|||
pub mod test {
|
||||
use super::*;
|
||||
|
||||
const DEGREE: usize = 1;
|
||||
|
||||
// These are basically testing the portable implementation against itself, but we also check
|
||||
// that compress_in_place and compress_xof are consistent. And there are tests against the
|
||||
// reference implementation and against hardcoded test vectors elsewhere.
|
||||
|
@ -305,6 +330,16 @@ pub mod test {
|
|||
crate::test::test_hash_many_fn(hash_many, hash_many);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash_chunks() {
|
||||
crate::test::test_hash_chunks_fn(hash_chunks, DEGREE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash_parents() {
|
||||
crate::test::test_hash_parents_fn(hash_parents, DEGREE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_xof_and_xor() {
|
||||
crate::test::test_xof_and_xor_fns(xof, xof_xor);
|
||||
|
|
206
src/test.rs
206
src/test.rs
|
@ -1,6 +1,8 @@
|
|||
use crate::platform::{ParentInOut, TransposedVectors, MAX_SIMD_DEGREE};
|
||||
use crate::{
|
||||
CVBytes, CVWords, IncrementCounter, BLOCK_LEN, CHUNK_LEN, OUT_LEN, UNIVERSAL_HASH_LEN,
|
||||
};
|
||||
|
||||
use arrayref::array_ref;
|
||||
use arrayvec::ArrayVec;
|
||||
use core::cmp;
|
||||
|
@ -49,8 +51,8 @@ pub const TEST_CASES: &[usize] = &[
|
|||
pub const TEST_CASES_MAX: usize = 100 * CHUNK_LEN;
|
||||
|
||||
// There's a test to make sure these two are equal below.
|
||||
pub const TEST_KEY: CVBytes = *b"whats the Elvish word for friend";
|
||||
pub const TEST_KEY_WORDS: CVWords = [
|
||||
pub const TEST_KEY: &CVBytes = b"whats the Elvish word for friend";
|
||||
pub const TEST_KEY_WORDS: &CVWords = &[
|
||||
1952540791, 1752440947, 1816469605, 1752394102, 1919907616, 1868963940, 1919295602, 1684956521,
|
||||
];
|
||||
|
||||
|
@ -84,7 +86,7 @@ type CompressXofFn = unsafe fn(
|
|||
|
||||
// A shared helper function for platform-specific tests.
|
||||
pub fn test_compress_fn(compress_in_place_fn: CompressInPlaceFn, compress_xof_fn: CompressXofFn) {
|
||||
let initial_state = TEST_KEY_WORDS;
|
||||
let initial_state = *TEST_KEY_WORDS;
|
||||
let block_len: u8 = 61;
|
||||
let mut block = [0; BLOCK_LEN];
|
||||
paint_test_input(&mut block[..block_len as usize]);
|
||||
|
@ -128,7 +130,7 @@ pub fn test_hash_many_fn(
|
|||
// 31 (16 + 8 + 4 + 2 + 1) inputs
|
||||
const NUM_INPUTS: usize = 31;
|
||||
let mut input_buf = [0; CHUNK_LEN * NUM_INPUTS];
|
||||
crate::test::paint_test_input(&mut input_buf);
|
||||
paint_test_input(&mut input_buf);
|
||||
|
||||
// First hash chunks.
|
||||
let mut chunks = ArrayVec::<&[u8; CHUNK_LEN], NUM_INPUTS>::new();
|
||||
|
@ -138,7 +140,7 @@ pub fn test_hash_many_fn(
|
|||
let mut portable_chunks_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
crate::portable::hash_many(
|
||||
&chunks,
|
||||
&TEST_KEY_WORDS,
|
||||
TEST_KEY_WORDS,
|
||||
counter,
|
||||
IncrementCounter::Yes,
|
||||
crate::KEYED_HASH,
|
||||
|
@ -151,7 +153,7 @@ pub fn test_hash_many_fn(
|
|||
unsafe {
|
||||
hash_many_chunks_fn(
|
||||
&chunks[..],
|
||||
&TEST_KEY_WORDS,
|
||||
TEST_KEY_WORDS,
|
||||
counter,
|
||||
IncrementCounter::Yes,
|
||||
crate::KEYED_HASH,
|
||||
|
@ -177,7 +179,7 @@ pub fn test_hash_many_fn(
|
|||
let mut portable_parents_out = [0; NUM_INPUTS * OUT_LEN];
|
||||
crate::portable::hash_many(
|
||||
&parents,
|
||||
&TEST_KEY_WORDS,
|
||||
TEST_KEY_WORDS,
|
||||
counter,
|
||||
IncrementCounter::No,
|
||||
crate::KEYED_HASH | crate::PARENT,
|
||||
|
@ -190,7 +192,7 @@ pub fn test_hash_many_fn(
|
|||
unsafe {
|
||||
hash_many_parents_fn(
|
||||
&parents[..],
|
||||
&TEST_KEY_WORDS,
|
||||
TEST_KEY_WORDS,
|
||||
counter,
|
||||
IncrementCounter::No,
|
||||
crate::KEYED_HASH | crate::PARENT,
|
||||
|
@ -210,6 +212,156 @@ pub fn test_hash_many_fn(
|
|||
}
|
||||
}
|
||||
|
||||
// Both xof() and xof_xof() have this signature.
|
||||
type HashChunksFn = unsafe fn(
|
||||
input: &[u8],
|
||||
key: &[u32; 8],
|
||||
counter: u64,
|
||||
flags: u8,
|
||||
output: &mut TransposedVectors,
|
||||
output_column: usize,
|
||||
);
|
||||
|
||||
pub fn test_hash_chunks_fn(target_fn: HashChunksFn, degree: usize) {
|
||||
assert!(degree <= MAX_SIMD_DEGREE);
|
||||
let mut input = [0u8; MAX_SIMD_DEGREE * CHUNK_LEN];
|
||||
paint_test_input(&mut input);
|
||||
for test_degree in 1..=degree {
|
||||
for &counter in INITIAL_COUNTERS {
|
||||
// Make two calls, to test the output_column parameter.
|
||||
let mut test_output = TransposedVectors::default();
|
||||
unsafe {
|
||||
target_fn(
|
||||
&input[..test_degree * CHUNK_LEN],
|
||||
TEST_KEY_WORDS,
|
||||
counter,
|
||||
crate::KEYED_HASH,
|
||||
&mut test_output,
|
||||
0,
|
||||
);
|
||||
target_fn(
|
||||
&input[..test_degree * CHUNK_LEN],
|
||||
TEST_KEY_WORDS,
|
||||
counter + test_degree as u64,
|
||||
crate::KEYED_HASH,
|
||||
&mut test_output,
|
||||
test_degree,
|
||||
);
|
||||
}
|
||||
|
||||
let mut portable_output = TransposedVectors::default();
|
||||
for i in 0..2 * test_degree {
|
||||
crate::portable::hash_chunks(
|
||||
&input[..test_degree * CHUNK_LEN],
|
||||
TEST_KEY_WORDS,
|
||||
counter + i as u64,
|
||||
crate::KEYED_HASH,
|
||||
&mut portable_output,
|
||||
i,
|
||||
);
|
||||
}
|
||||
|
||||
assert_eq!(portable_output.0, test_output.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn paint_transposed_input(input: &mut TransposedVectors) {
|
||||
let mut val = 0;
|
||||
for row in 0..8 {
|
||||
for col in 0..2 * MAX_SIMD_DEGREE {
|
||||
input[row][col] = val;
|
||||
val += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Both xof() and xof_xof() have this signature.
|
||||
type HashParentsFn = unsafe fn(in_out: ParentInOut, key: &[u32; 8], flags: u8);
|
||||
|
||||
pub fn test_hash_parents_fn(target_fn: HashParentsFn, degree: usize) {
|
||||
assert!(degree <= MAX_SIMD_DEGREE);
|
||||
for test_degree in 1..=degree {
|
||||
// separate
|
||||
{
|
||||
let mut input = TransposedVectors::default();
|
||||
paint_transposed_input(&mut input);
|
||||
let mut test_output = TransposedVectors(input.0);
|
||||
unsafe {
|
||||
target_fn(
|
||||
ParentInOut::Separate {
|
||||
input: &input,
|
||||
num_parents: test_degree,
|
||||
output: &mut test_output,
|
||||
output_column: 0,
|
||||
},
|
||||
TEST_KEY_WORDS,
|
||||
crate::KEYED_HASH | crate::PARENT,
|
||||
);
|
||||
}
|
||||
|
||||
let mut portable_output = TransposedVectors(input.0);
|
||||
for i in 0..test_degree {
|
||||
for row in 0..8 {
|
||||
input[row][0] = input[row][2 * i];
|
||||
input[row][1] = input[row][2 * i + 1];
|
||||
}
|
||||
crate::portable::hash_parents(
|
||||
ParentInOut::Separate {
|
||||
input: &input,
|
||||
num_parents: 1,
|
||||
output: &mut portable_output,
|
||||
output_column: i,
|
||||
},
|
||||
TEST_KEY_WORDS,
|
||||
crate::KEYED_HASH | crate::PARENT,
|
||||
);
|
||||
}
|
||||
|
||||
assert_eq!(portable_output.0, test_output.0);
|
||||
}
|
||||
|
||||
// in-place
|
||||
{
|
||||
let mut test_io = TransposedVectors::default();
|
||||
paint_transposed_input(&mut test_io);
|
||||
unsafe {
|
||||
target_fn(
|
||||
ParentInOut::InPlace {
|
||||
in_out: &mut test_io,
|
||||
num_parents: test_degree,
|
||||
},
|
||||
TEST_KEY_WORDS,
|
||||
crate::KEYED_HASH | crate::PARENT,
|
||||
);
|
||||
}
|
||||
|
||||
let mut portable_input = TransposedVectors::default();
|
||||
let mut portable_output = TransposedVectors::default();
|
||||
paint_transposed_input(&mut portable_input);
|
||||
paint_transposed_input(&mut portable_output);
|
||||
for i in 0..test_degree {
|
||||
for row in 0..8 {
|
||||
portable_input[row][0] = portable_input[row][2 * i];
|
||||
portable_input[row][1] = portable_input[row][2 * i + 1];
|
||||
}
|
||||
crate::portable::hash_parents(
|
||||
ParentInOut::Separate {
|
||||
input: &portable_input,
|
||||
num_parents: 1,
|
||||
output: &mut portable_output,
|
||||
output_column: i,
|
||||
},
|
||||
TEST_KEY_WORDS,
|
||||
crate::KEYED_HASH | crate::PARENT,
|
||||
);
|
||||
}
|
||||
|
||||
assert_eq!(portable_output.0, test_io.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Both xof() and xof_xof() have this signature.
|
||||
type XofFn = unsafe fn(
|
||||
block: &[u8; BLOCK_LEN],
|
||||
|
@ -229,7 +381,7 @@ pub fn test_xof_and_xor_fns(target_xof: XofFn, target_xof_xor: XofFn) {
|
|||
];
|
||||
for input_len in [0, 1, BLOCK_LEN] {
|
||||
let mut input_block = [0u8; BLOCK_LEN];
|
||||
crate::test::paint_test_input(&mut input_block[..input_len]);
|
||||
paint_test_input(&mut input_block[..input_len]);
|
||||
for output_len in [0, 1, BLOCK_LEN, BLOCK_LEN + 1, BLOCK_LEN * NUM_OUTPUTS] {
|
||||
let mut test_output_buf = [0xff; BLOCK_LEN * NUM_OUTPUTS];
|
||||
for &counter in INITIAL_COUNTERS {
|
||||
|
@ -238,7 +390,7 @@ pub fn test_xof_and_xor_fns(target_xof: XofFn, target_xof_xor: XofFn) {
|
|||
crate::portable::xof(
|
||||
&input_block,
|
||||
input_len as u8,
|
||||
&TEST_KEY_WORDS,
|
||||
TEST_KEY_WORDS,
|
||||
counter,
|
||||
flags,
|
||||
&mut expected_output_buf[..output_len],
|
||||
|
@ -248,7 +400,7 @@ pub fn test_xof_and_xor_fns(target_xof: XofFn, target_xof_xor: XofFn) {
|
|||
target_xof(
|
||||
&input_block,
|
||||
input_len as u8,
|
||||
&TEST_KEY_WORDS,
|
||||
TEST_KEY_WORDS,
|
||||
counter,
|
||||
flags,
|
||||
&mut test_output_buf[..output_len],
|
||||
|
@ -267,7 +419,7 @@ pub fn test_xof_and_xor_fns(target_xof: XofFn, target_xof_xor: XofFn) {
|
|||
target_xof_xor(
|
||||
&input_block,
|
||||
input_len as u8,
|
||||
&TEST_KEY_WORDS,
|
||||
TEST_KEY_WORDS,
|
||||
counter,
|
||||
flags,
|
||||
&mut test_output_buf[..output_len],
|
||||
|
@ -281,7 +433,7 @@ pub fn test_xof_and_xor_fns(target_xof: XofFn, target_xof_xor: XofFn) {
|
|||
target_xof_xor(
|
||||
&input_block,
|
||||
input_len as u8,
|
||||
&TEST_KEY_WORDS,
|
||||
TEST_KEY_WORDS,
|
||||
counter,
|
||||
flags,
|
||||
&mut test_output_buf[..output_len],
|
||||
|
@ -306,7 +458,7 @@ fn test_compare_reference_impl_xof() {
|
|||
input_block[..input.len()].copy_from_slice(input);
|
||||
|
||||
let mut reference_output_buf = [0; BLOCK_LEN * NUM_OUTPUTS];
|
||||
let mut reference_hasher = reference_impl::Hasher::new_keyed(&TEST_KEY);
|
||||
let mut reference_hasher = reference_impl::Hasher::new_keyed(TEST_KEY);
|
||||
reference_hasher.update(input);
|
||||
reference_hasher.finalize(&mut reference_output_buf);
|
||||
|
||||
|
@ -315,7 +467,7 @@ fn test_compare_reference_impl_xof() {
|
|||
crate::platform::Platform::detect().xof(
|
||||
&input_block,
|
||||
input.len() as u8,
|
||||
&TEST_KEY_WORDS,
|
||||
TEST_KEY_WORDS,
|
||||
0,
|
||||
crate::KEYED_HASH | crate::CHUNK_START | crate::CHUNK_END | crate::ROOT,
|
||||
&mut test_output_buf[..output_len],
|
||||
|
@ -334,7 +486,7 @@ fn test_compare_reference_impl_xof() {
|
|||
crate::platform::Platform::detect().xof(
|
||||
&input_block,
|
||||
input.len() as u8,
|
||||
&TEST_KEY_WORDS,
|
||||
TEST_KEY_WORDS,
|
||||
1,
|
||||
crate::KEYED_HASH | crate::CHUNK_START | crate::CHUNK_END | crate::ROOT,
|
||||
&mut test_output_buf[..output_len - BLOCK_LEN],
|
||||
|
@ -354,12 +506,12 @@ pub fn test_universal_hash_fn(target_fn: UniversalHashFn) {
|
|||
// 31 (16 + 8 + 4 + 2 + 1) inputs
|
||||
const NUM_INPUTS: usize = 31;
|
||||
let mut input_buf = [0; BLOCK_LEN * NUM_INPUTS];
|
||||
crate::test::paint_test_input(&mut input_buf);
|
||||
paint_test_input(&mut input_buf);
|
||||
for len in [0, 1, BLOCK_LEN, BLOCK_LEN + 1, input_buf.len()] {
|
||||
for &counter in INITIAL_COUNTERS {
|
||||
let portable_output =
|
||||
crate::portable::universal_hash(&input_buf[..len], &TEST_KEY_WORDS, counter);
|
||||
let test_output = unsafe { target_fn(&input_buf[..len], &TEST_KEY_WORDS, counter) };
|
||||
crate::portable::universal_hash(&input_buf[..len], TEST_KEY_WORDS, counter);
|
||||
let test_output = unsafe { target_fn(&input_buf[..len], TEST_KEY_WORDS, counter) };
|
||||
assert_eq!(portable_output, test_output);
|
||||
}
|
||||
}
|
||||
|
@ -396,12 +548,12 @@ fn reference_impl_universal_hash(
|
|||
fn test_compare_reference_impl_universal_hash() {
|
||||
const NUM_INPUTS: usize = 31;
|
||||
let mut input_buf = [0; BLOCK_LEN * NUM_INPUTS];
|
||||
crate::test::paint_test_input(&mut input_buf);
|
||||
paint_test_input(&mut input_buf);
|
||||
for len in [0, 1, BLOCK_LEN, BLOCK_LEN + 1, input_buf.len()] {
|
||||
let reference_output = reference_impl_universal_hash(&input_buf[..len], &TEST_KEY);
|
||||
let reference_output = reference_impl_universal_hash(&input_buf[..len], TEST_KEY);
|
||||
let test_output = crate::platform::Platform::detect().universal_hash(
|
||||
&input_buf[..len],
|
||||
&TEST_KEY_WORDS,
|
||||
TEST_KEY_WORDS,
|
||||
0,
|
||||
);
|
||||
assert_eq!(reference_output, test_output);
|
||||
|
@ -412,7 +564,7 @@ fn test_compare_reference_impl_universal_hash() {
|
|||
fn test_key_bytes_equal_key_words() {
|
||||
assert_eq!(
|
||||
TEST_KEY_WORDS,
|
||||
crate::platform::words_from_le_bytes_32(&TEST_KEY),
|
||||
&crate::platform::words_from_le_bytes_32(TEST_KEY),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -516,23 +668,23 @@ fn test_compare_reference_impl() {
|
|||
|
||||
// keyed
|
||||
{
|
||||
let mut reference_hasher = reference_impl::Hasher::new_keyed(&TEST_KEY);
|
||||
let mut reference_hasher = reference_impl::Hasher::new_keyed(TEST_KEY);
|
||||
reference_hasher.update(input);
|
||||
let mut expected_out = [0; OUT];
|
||||
reference_hasher.finalize(&mut expected_out);
|
||||
|
||||
// all at once
|
||||
let test_out = crate::keyed_hash(&TEST_KEY, input);
|
||||
let test_out = crate::keyed_hash(TEST_KEY, input);
|
||||
assert_eq!(test_out, *array_ref!(expected_out, 0, 32));
|
||||
// incremental
|
||||
let mut hasher = crate::Hasher::new_keyed(&TEST_KEY);
|
||||
let mut hasher = crate::Hasher::new_keyed(TEST_KEY);
|
||||
hasher.update(input);
|
||||
assert_eq!(hasher.finalize(), *array_ref!(expected_out, 0, 32));
|
||||
assert_eq!(hasher.finalize(), test_out);
|
||||
// incremental (rayon)
|
||||
#[cfg(feature = "rayon")]
|
||||
{
|
||||
let mut hasher = crate::Hasher::new_keyed(&TEST_KEY);
|
||||
let mut hasher = crate::Hasher::new_keyed(TEST_KEY);
|
||||
hasher.update_rayon(input);
|
||||
assert_eq!(hasher.finalize(), *array_ref!(expected_out, 0, 32));
|
||||
assert_eq!(hasher.finalize(), test_out);
|
||||
|
|
Loading…
Reference in New Issue