From a40dde8988ae65390e855bee50213ab6baaec533 Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Thu, 6 Nov 2025 18:31:45 +0900 Subject: [PATCH] feat(k12)!: Implement KT256 Implement KT256 as specified in RFC 9861. Also, rename existing types to KT128 in accordance with RFC 9861 (e.g. `KangarooTwelveReader` to `Kt128Reader`). --- k12/benches/mod.rs | 19 ++- k12/src/block_api.rs | 369 ++++++++++++++++++++++++------------------- k12/src/lib.rs | 185 +++++++++++++--------- k12/tests/mod.rs | 146 ++++++++++++++--- 4 files changed, 461 insertions(+), 258 deletions(-) diff --git a/k12/benches/mod.rs b/k12/benches/mod.rs index 0074e2a22..6c8dfac43 100644 --- a/k12/benches/mod.rs +++ b/k12/benches/mod.rs @@ -5,10 +5,19 @@ use digest::bench_update; use test::Bencher; bench_update!( - k12::KangarooTwelve::default(); - k12_10 10; - k12_100 100; + k12::Kt128::default(); + kt128_10 10; + kt128_100 100; // the bigger sizes result in OOM - // k12_1000 1000; - // k12_10000 10000; + // kt128_1000 1000; + // kt128_10000 10000; +); + +bench_update!( + k12::Kt256::default(); + kt256_10 10; + kt256_100 100; + // the bigger sizes result in OOM + // kt256_1000 1000; + // kt256_10000 10000; ); diff --git a/k12/src/block_api.rs b/k12/src/block_api.rs index 8800fecc5..a4d631d39 100644 --- a/k12/src/block_api.rs +++ b/k12/src/block_api.rs @@ -5,207 +5,250 @@ use digest::{ AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, Eager, ExtendableOutputCore, UpdateCore, XofReaderCore, }, - consts::{U128, U168}, + consts::{U128, U136, U168}, }; -use sha3::{TurboShake128, TurboShake128Reader}; +use sha3::{TurboShake128, TurboShake128Reader, TurboShake256, TurboShake256Reader}; const CHUNK_SIZE: usize = 8192; -const CHAINING_VALUE_SIZE: usize = 32; const LENGTH_ENCODE_SIZE: usize = 255; -/// Core [`KangarooTwelve`] hasher state. -#[derive(Clone)] -#[allow(non_camel_case_types)] -pub struct KangarooTwelveCore<'cs> { - customization: &'cs [u8], - buffer: [u8; CHUNK_SIZE], - bufpos: usize, - final_tshk: TurboShake128<0x06>, - chain_tshk: TurboShake128<0x0B>, - chain_length: usize, -} - -impl<'cs> KangarooTwelveCore<'cs> { - /// Creates a new KangarooTwelve instance with the given customization. - pub fn new(customization: &'cs [u8]) -> Self { - Self { - customization, - buffer: [0u8; CHUNK_SIZE], - bufpos: 0usize, - final_tshk: Default::default(), - chain_tshk: Default::default(), - chain_length: 0usize, +macro_rules! impl_k12_core { + ( + $name:ident, $reader_name:ident, $ts_name:ident, $ts_reader_name:ident, $cv_size:literal, + $alg_name:literal, + ) => { + #[doc = "Core"] + #[doc = $alg_name] + #[doc = "hasher state."] + #[derive(Clone)] + #[allow(non_camel_case_types)] + pub struct $name<'cs> { + customization: &'cs [u8], + buffer: [u8; CHUNK_SIZE], + bufpos: usize, + final_tshk: $ts_name<0x06>, + chain_tshk: $ts_name<0x0B>, + chain_length: usize, } - } - fn process_chunk(&mut self) { - debug_assert!(self.bufpos == CHUNK_SIZE); - if self.chain_length == 0 { - self.final_tshk.update(&self.buffer); - } else { - self.process_chaining_chunk(); - } + impl<'cs> $name<'cs> { + const CHAINING_VALUE_SIZE: usize = $cv_size; + + #[doc = "Creates a new"] + #[doc = $alg_name] + #[doc = "instance with the given customization."] + pub fn new(customization: &'cs [u8]) -> Self { + Self { + customization, + buffer: [0u8; CHUNK_SIZE], + bufpos: 0usize, + final_tshk: Default::default(), + chain_tshk: Default::default(), + chain_length: 0usize, + } + } - self.chain_length += 1; - self.buffer = [0u8; CHUNK_SIZE]; - self.bufpos = 0; - } + fn process_chunk(&mut self) { + debug_assert!(self.bufpos == CHUNK_SIZE); + if self.chain_length == 0 { + self.final_tshk.update(&self.buffer); + } else { + self.process_chaining_chunk(); + } + + self.chain_length += 1; + self.buffer = [0u8; CHUNK_SIZE]; + self.bufpos = 0; + } - fn process_chaining_chunk(&mut self) { - debug_assert!(self.bufpos != 0); - if self.chain_length == 1 { - self.final_tshk - .update(&[0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + fn process_chaining_chunk(&mut self) { + debug_assert!(self.bufpos != 0); + if self.chain_length == 1 { + self.final_tshk + .update(&[0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + } + + let mut result = [0u8; Self::CHAINING_VALUE_SIZE]; + self.chain_tshk.update(&self.buffer[..self.bufpos]); + self.chain_tshk.finalize_xof_reset_into(&mut result); + self.final_tshk.update(&result); + } } - let mut result = [0u8; CHAINING_VALUE_SIZE]; - self.chain_tshk.update(&self.buffer[..self.bufpos]); - self.chain_tshk.finalize_xof_reset_into(&mut result); - self.final_tshk.update(&result); - } -} - -impl HashMarker for KangarooTwelveCore<'_> {} + impl HashMarker for $name<'_> {} -impl BlockSizeUser for KangarooTwelveCore<'_> { - type BlockSize = U128; -} + impl BlockSizeUser for $name<'_> { + type BlockSize = U128; + } -impl BufferKindUser for KangarooTwelveCore<'_> { - type BufferKind = Eager; -} + impl BufferKindUser for $name<'_> { + type BufferKind = Eager; + } -impl UpdateCore for KangarooTwelveCore<'_> { - #[inline] - fn update_blocks(&mut self, blocks: &[Block]) { - for block in blocks { - if self.bufpos == CHUNK_SIZE { - self.process_chunk(); + impl UpdateCore for $name<'_> { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + for block in blocks { + if self.bufpos == CHUNK_SIZE { + self.process_chunk(); + } + + self.buffer[self.bufpos..self.bufpos + 128].clone_from_slice(block); + self.bufpos += 128; + } } - - self.buffer[self.bufpos..self.bufpos + 128].clone_from_slice(block); - self.bufpos += 128; } - } -} - -impl ExtendableOutputCore for KangarooTwelveCore<'_> { - type ReaderCore = KangarooTwelveReaderCore; - #[inline] - fn finalize_xof_core(&mut self, buffer: &mut Buffer) -> Self::ReaderCore { - let mut lenbuf = [0u8; LENGTH_ENCODE_SIZE]; - - // Digest customization - buffer.digest_blocks(self.customization, |block| self.update_blocks(block)); - buffer.digest_blocks( - length_encode(self.customization.len(), &mut lenbuf), - |block| self.update_blocks(block), - ); - - if self.bufpos == CHUNK_SIZE && buffer.get_pos() != 0 { - self.process_chunk(); + impl ExtendableOutputCore for $name<'_> { + type ReaderCore = $reader_name; + + #[inline] + fn finalize_xof_core(&mut self, buffer: &mut Buffer) -> Self::ReaderCore { + let mut lenbuf = [0u8; LENGTH_ENCODE_SIZE]; + + // Digest customization + buffer.digest_blocks(self.customization, |block| self.update_blocks(block)); + buffer.digest_blocks( + length_encode(self.customization.len(), &mut lenbuf), + |block| self.update_blocks(block), + ); + + if self.bufpos == CHUNK_SIZE && buffer.get_pos() != 0 { + self.process_chunk(); + } + + // Read leftover data from buffer + self.buffer[self.bufpos..(self.bufpos + buffer.get_pos())] + .copy_from_slice(buffer.get_data()); + self.bufpos += buffer.get_pos(); + + // Calculate final node + if self.chain_length == 0 { + // Input did not exceed a single chaining value + let tshk = $ts_name::<0x07>::default() + .chain(&self.buffer[..self.bufpos]) + .finalize_xof_reset(); + return $reader_name { tshk }; + } + + // Calculate last chaining value + self.process_chaining_chunk(); + + // Pad final node calculation + self.final_tshk + .update(length_encode(self.chain_length, &mut lenbuf)); + self.final_tshk.update(&[0xff, 0xff]); + + $reader_name { + tshk: self.final_tshk.finalize_xof_reset(), + } + } } - // Read leftover data from buffer - self.buffer[self.bufpos..(self.bufpos + buffer.get_pos())] - .copy_from_slice(buffer.get_data()); - self.bufpos += buffer.get_pos(); - - // Calculate final node - if self.chain_length == 0 { - // Input did not exceed a single chaining value - let tshk = TurboShake128::<0x07>::default() - .chain(&self.buffer[..self.bufpos]) - .finalize_xof_reset(); - return KangarooTwelveReaderCore { tshk }; + impl Default for $name<'_> { + #[inline] + fn default() -> Self { + Self { + customization: &[], + buffer: [0u8; CHUNK_SIZE], + bufpos: 0usize, + final_tshk: Default::default(), + chain_tshk: Default::default(), + chain_length: 0usize, + } + } } - // Calculate last chaining value - self.process_chaining_chunk(); - - // Pad final node calculation - self.final_tshk - .update(length_encode(self.chain_length, &mut lenbuf)); - self.final_tshk.update(&[0xff, 0xff]); - - KangarooTwelveReaderCore { - tshk: self.final_tshk.finalize_xof_reset(), + impl Reset for $name<'_> { + #[inline] + fn reset(&mut self) { + *self = Self::new(self.customization); + } } - } -} -impl Default for KangarooTwelveCore<'_> { - #[inline] - fn default() -> Self { - Self { - customization: &[], - buffer: [0u8; CHUNK_SIZE], - bufpos: 0usize, - final_tshk: Default::default(), - chain_tshk: Default::default(), - chain_length: 0usize, + impl AlgorithmName for $name<'_> { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str($alg_name) + } } - } -} -impl Reset for KangarooTwelveCore<'_> { - #[inline] - fn reset(&mut self) { - *self = Self::new(self.customization); - } -} - -impl AlgorithmName for KangarooTwelveCore<'_> { - fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(stringify!(KangarooTwelve)) - } -} + impl fmt::Debug for $name<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(concat!(stringify!($name), " { ... }")) + } + } -impl fmt::Debug for KangarooTwelveCore<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(concat!(stringify!(KangarooTwelveCore), " { ... }")) - } -} + impl Drop for $name<'_> { + fn drop(&mut self) { + #[cfg(feature = "zeroize")] + { + use digest::zeroize::Zeroize; + self.buffer.zeroize(); + self.bufpos.zeroize(); + self.chain_length.zeroize(); + // final_tshk and chain_tshk zeroized by their Drop impl + } + } + } -impl Drop for KangarooTwelveCore<'_> { - fn drop(&mut self) { #[cfg(feature = "zeroize")] - { - use digest::zeroize::Zeroize; - self.buffer.zeroize(); - self.bufpos.zeroize(); - self.chain_length.zeroize(); - // final_tshk and chain_tshk zeroized by their Drop impl + impl digest::zeroize::ZeroizeOnDrop for $name<'_> {} + + #[doc = "Core"] + #[doc = $alg_name] + #[doc = "reader state."] + #[derive(Clone)] + pub struct $reader_name { + tshk: $ts_reader_name, } - } -} -#[cfg(feature = "zeroize")] -impl digest::zeroize::ZeroizeOnDrop for KangarooTwelveCore<'_> {} + impl XofReaderCore for $reader_name { + #[inline] + fn read_block(&mut self) -> Block { + let mut block = Block::::default(); + self.tshk.read(&mut block); + block + } + } -/// Core [`KangarooTwelve`] reader state. -#[derive(Clone)] -pub struct KangarooTwelveReaderCore { - tshk: TurboShake128Reader, + // `Sha3ReaderCore` and the wrapper are zeroized by their Drop impls + #[cfg(feature = "zeroize")] + impl digest::zeroize::ZeroizeOnDrop for $reader_name {} + }; } -impl BlockSizeUser for KangarooTwelveReaderCore { +impl_k12_core!( + Kt128Core, + Kt128ReaderCore, + TurboShake128, + TurboShake128Reader, + 32, + "KT128", +); +impl_k12_core!( + Kt256Core, + Kt256ReaderCore, + TurboShake256, + TurboShake256Reader, + 64, + "KT256", +); + +impl BlockSizeUser for Kt128ReaderCore { type BlockSize = U168; // TurboSHAKE128 block size } -impl XofReaderCore for KangarooTwelveReaderCore { - #[inline] - fn read_block(&mut self) -> Block { - let mut block = Block::::default(); - self.tshk.read(&mut block); - block - } +impl BlockSizeUser for Kt256ReaderCore { + type BlockSize = U136; // TurboSHAKE256 block size } -// `TurboShake128ReaderCore` and the wrapper are zeroized by their Drop impls -#[cfg(feature = "zeroize")] -impl digest::zeroize::ZeroizeOnDrop for KangarooTwelveReaderCore {} +/// Core KT128 hasher state. +#[deprecated(since = "0.4.0-pre", note = "use `Kt128Core` instead")] +pub type KangarooTwelveCore<'cs> = Kt128Core<'cs>; + +/// Core KT128 reader state. +#[deprecated(since = "0.4.0-pre", note = "use `Kt128ReaderCore` instead")] +pub type KangarooTwelveReaderCore = Kt128ReaderCore; fn length_encode(mut length: usize, buffer: &mut [u8; LENGTH_ENCODE_SIZE]) -> &mut [u8] { let mut bufpos = 0usize; diff --git a/k12/src/lib.rs b/k12/src/lib.rs index fd85905ef..9b3f8bac1 100644 --- a/k12/src/lib.rs +++ b/k12/src/lib.rs @@ -18,97 +18,138 @@ use digest::{ CollisionResistance, ExtendableOutput, HashMarker, Reset, Update, XofReader, block_api::{AlgorithmName, BlockSizeUser, ExtendableOutputCore, UpdateCore, XofReaderCore}, block_buffer::{BlockBuffer, Eager, ReadBuffer}, - consts::{U16, U128, U168}, + consts::{U16, U32, U128, U136, U168}, }; -/// `KangarooTwelve` hasher. -#[derive(Default, Clone)] -pub struct KangarooTwelve<'cs> { - core: block_api::KangarooTwelveCore<'cs>, - buffer: BlockBuffer, -} +macro_rules! impl_k12 { + ( + $name:ident, $reader_name:ident, $core_name:ident, $reader_core_name:ident, $rate:ty, + $alg_name:literal, + ) => { + #[doc = $alg_name] + #[doc = "hasher."] + #[derive(Default, Clone)] + pub struct $name<'cs> { + core: block_api::$core_name<'cs>, + buffer: BlockBuffer, + } -impl<'cs> KangarooTwelve<'cs> { - /// Creates a new KangarooTwelve instance with the given customization. - pub fn new(customization: &'cs [u8]) -> Self { - Self { - core: block_api::KangarooTwelveCore::new(customization), - buffer: Default::default(), + impl<'cs> $name<'cs> { + #[doc = "Creates a new"] + #[doc = $alg_name] + #[doc = "instance with the given customization."] + pub fn new(customization: &'cs [u8]) -> Self { + Self { + core: block_api::$core_name::new(customization), + buffer: Default::default(), + } + } } - } -} -impl fmt::Debug for KangarooTwelve<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - f.write_str("KangarooTwelve { .. }") - } -} + impl fmt::Debug for $name<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.write_str(concat!(stringify!($name), " { .. }")) + } + } -impl AlgorithmName for KangarooTwelve<'_> { - fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("KangarooTwelve") - } -} + impl AlgorithmName for $name<'_> { + fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str($alg_name) + } + } -impl HashMarker for KangarooTwelve<'_> {} + impl HashMarker for $name<'_> {} -impl BlockSizeUser for KangarooTwelve<'_> { - type BlockSize = U128; -} + impl BlockSizeUser for $name<'_> { + type BlockSize = U128; + } -impl Update for KangarooTwelve<'_> { - fn update(&mut self, data: &[u8]) { - let Self { core, buffer } = self; - buffer.digest_blocks(data, |blocks| core.update_blocks(blocks)); - } -} + impl Update for $name<'_> { + fn update(&mut self, data: &[u8]) { + let Self { core, buffer } = self; + buffer.digest_blocks(data, |blocks| core.update_blocks(blocks)); + } + } -impl Reset for KangarooTwelve<'_> { - fn reset(&mut self) { - self.core.reset(); - self.buffer.reset(); - } -} + impl Reset for $name<'_> { + fn reset(&mut self) { + self.core.reset(); + self.buffer.reset(); + } + } -impl ExtendableOutput for KangarooTwelve<'_> { - type Reader = KangarooTwelveReader; + impl ExtendableOutput for $name<'_> { + type Reader = $reader_name; - #[inline] - fn finalize_xof(mut self) -> Self::Reader { - Self::Reader { - core: self.core.finalize_xof_core(&mut self.buffer), - buffer: Default::default(), + #[inline] + fn finalize_xof(mut self) -> Self::Reader { + Self::Reader { + core: self.core.finalize_xof_core(&mut self.buffer), + buffer: Default::default(), + } + } } - } -} -impl CollisionResistance for KangarooTwelve<'_> { - // https://www.ietf.org/archive/id/draft-irtf-cfrg-kangarootwelve-17.html#section-7-7 - type CollisionResistance = U16; -} + #[cfg(feature = "zeroize")] + impl digest::zeroize::ZeroizeOnDrop for $name<'_> {} -#[cfg(feature = "zeroize")] -impl digest::zeroize::ZeroizeOnDrop for KangarooTwelve<'_> {} + #[doc = $alg_name] + #[doc = "XOF reader."] + pub struct $reader_name { + core: block_api::$reader_core_name, + buffer: ReadBuffer<$rate>, + } -/// `KangarooTwelve` XOF reader. -pub struct KangarooTwelveReader { - core: block_api::KangarooTwelveReaderCore, - buffer: ReadBuffer, + impl fmt::Debug for $reader_name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.write_str(concat!(stringify!($reader_name), " { .. }")) + } + } + + impl XofReader for $reader_name { + #[inline] + fn read(&mut self, buffer: &mut [u8]) { + let Self { core, buffer: buf } = self; + buf.read(buffer, |block| *block = core.read_block()); + } + } + + #[cfg(feature = "zeroize")] + impl digest::zeroize::ZeroizeOnDrop for $reader_name {} + }; } -impl fmt::Debug for KangarooTwelveReader { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - f.write_str("KangarooTwelveReader { .. }") - } +impl_k12!( + Kt128, + Kt128Reader, + Kt128Core, + Kt128ReaderCore, + U168, + "KT128", +); +impl_k12!( + Kt256, + Kt256Reader, + Kt256Core, + Kt256ReaderCore, + U136, + "KT256", +); + +impl CollisionResistance for Kt128<'_> { + // https://www.rfc-editor.org/rfc/rfc9861.html#section-7-7 + type CollisionResistance = U16; } -impl XofReader for KangarooTwelveReader { - #[inline] - fn read(&mut self, buffer: &mut [u8]) { - let Self { core, buffer: buf } = self; - buf.read(buffer, |block| *block = core.read_block()); - } +impl CollisionResistance for Kt256<'_> { + // https://www.rfc-editor.org/rfc/rfc9861.html#section-7-8 + type CollisionResistance = U32; } -#[cfg(feature = "zeroize")] -impl digest::zeroize::ZeroizeOnDrop for KangarooTwelveReader {} +/// KT128 hasher. +#[deprecated(since = "0.4.0-pre", note = "use `Kt128` instead")] +pub type KangarooTwelve<'cs> = Kt128<'cs>; + +/// KT128 XOF reader. +#[deprecated(since = "0.4.0-pre", note = "use `Kt128Reader` instead")] +pub type KangarooTwelveReader = Kt128Reader; diff --git a/k12/tests/mod.rs b/k12/tests/mod.rs index a4fa6133b..0f26a5da6 100644 --- a/k12/tests/mod.rs +++ b/k12/tests/mod.rs @@ -1,26 +1,34 @@ use core::iter; use hex_literal::hex; use k12::{ - KangarooTwelve, + Kt128, Kt256, digest::{ExtendableOutput, Update}, }; -fn digest_and_box(data: &[u8], n: usize) -> Box<[u8]> { - let mut h = KangarooTwelve::default(); - h.update(data); - h.finalize_boxed(n) +macro_rules! digest_and_box { + ($name:ident, $hasher:ty) => { + fn $name(data: &[u8], n: usize) -> Box<[u8]> { + let mut h = <$hasher>::default(); + h.update(data); + h.finalize_boxed(n) + } + }; } +digest_and_box!(kt128_digest_and_box, Kt128); +digest_and_box!(kt256_digest_and_box, Kt256); + +// Source: + #[test] -fn empty() { - // Source: reference paper +fn kt128_empty() { assert_eq!( - digest_and_box(b"", 32)[..], + kt128_digest_and_box(b"", 32)[..], hex!("1ac2d450fc3b4205d19da7bfca1b37513c0803577ac7167f06fe2ce1f0ef39e5")[..] ); assert_eq!( - digest_and_box(b"", 64)[..], + kt128_digest_and_box(b"", 64)[..], hex!( "1ac2d450fc3b4205d19da7bfca1b37513c0803577ac7167f06fe2ce1f0ef39e5" "4269c056b8c82e48276038b6d292966cc07a3d4645272e31ff38508139eb0a71" @@ -28,13 +36,42 @@ fn empty() { ); assert_eq!( - digest_and_box(b"", 10032)[10000..], + kt128_digest_and_box(b"", 10032)[10000..], hex!("e8dc563642f7228c84684c898405d3a834799158c079b12880277a1d28e2ff6d")[..] ); } #[test] -fn pat_m() { +fn kt256_empty() { + assert_eq!( + kt256_digest_and_box(b"", 64)[..], + hex!( + "b23d2e9cea9f4904e02bec06817fc10ce38ce8e93ef4c89e6537076af8646404" + "e3e8b68107b8833a5d30490aa33482353fd4adc7148ecb782855003aaebde4a9" + )[..], + ); + + assert_eq!( + kt256_digest_and_box(b"", 128)[..], + hex!( + "b23d2e9cea9f4904e02bec06817fc10ce38ce8e93ef4c89e6537076af8646404" + "e3e8b68107b8833a5d30490aa33482353fd4adc7148ecb782855003aaebde4a9" + "b0925319d8ea1e121a609821ec19efea89e6d08daee1662b69c840289f188ba8" + "60f55760b61f82114c030c97e5178449608ccd2cd2d919fc7829ff69931ac4d0" + )[..], + ); + + assert_eq!( + kt256_digest_and_box(b"", 10064)[10000..], + hex!( + "ad4a1d718cf950506709a4c33396139b4449041fc79a05d68da35f1e453522e0" + "56c64fe94958e7085f2964888259b9932752f3ccd855288efee5fcbb8b563069" + )[..], + ); +} + +#[test] +fn kt128_pat_m() { let expected = [ hex!("2bda92450e8b147f8a7cb629e784a058efca7cf7d8218e02d345dfaa65244a1f"), hex!("6bf75fa2239198db4772e36478f8e19b0f371205f6a9a93a273f51df37122888"), @@ -49,13 +86,55 @@ fn pat_m() { { let len = 17usize.pow(i); let m: Vec = (0..len).map(|j| (j % 251) as u8).collect(); - let result = digest_and_box(&m, 32); + let result = kt128_digest_and_box(&m, 32); + assert_eq!(result[..], expected[i as usize][..]); + } +} + +#[test] +fn kt256_pat_m() { + let expected = [ + hex!( + "0d005a194085360217128cf17f91e1f71314efa5564539d444912e3437efa17f" + "82db6f6ffe76e781eaa068bce01f2bbf81eacb983d7230f2fb02834a21b1ddd0" + ), + hex!( + "1ba3c02b1fc514474f06c8979978a9056c8483f4a1b63d0dccefe3a28a2f323e" + "1cdcca40ebf006ac76ef0397152346837b1277d3e7faa9c9653b19075098527b" + ), + hex!( + "de8ccbc63e0f133ebb4416814d4c66f691bbf8b6a61ec0a7700f836b086cb029" + "d54f12ac7159472c72db118c35b4e6aa213c6562caaa9dcc518959e69b10f3ba" + ), + hex!( + "647efb49fe9d717500171b41e7f11bd491544443209997ce1c2530d15eb1ffbb" + "598935ef954528ffc152b1e4d731ee2683680674365cd191d562bae753b84aa5" + ), + hex!( + "b06275d284cd1cf205bcbe57dccd3ec1ff6686e3ed15776383e1f2fa3c6ac8f0" + "8bf8a162829db1a44b2a43ff83dd89c3cf1ceb61ede659766d5ccf817a62ba8d" + ), + hex!( + "9473831d76a4c7bf77ace45b59f1458b1673d64bcd877a7c66b2664aa6dd149e" + "60eab71b5c2bab858c074ded81ddce2b4022b5215935c0d4d19bf511aeeb0772" + ), + hex!( + "0652b740d78c5e1f7c8dcc1777097382768b7ff38f9a7a20f29f413bb1b3045b" + "31a5578f568f911e09cf44746da84224a5266e96a4a535e871324e4f9c7004da" + ), + ]; + for i in 0..5 + /*NOTE: can be up to 7 but is slow*/ + { + let len = 17usize.pow(i); + let m: Vec = (0..len).map(|j| (j % 251) as u8).collect(); + let result = kt256_digest_and_box(&m, 64); assert_eq!(result[..], expected[i as usize][..]); } } #[test] -fn pat_c() { +fn kt128_pat_c() { let expected = [ hex!("fab658db63e94a246188bf7af69a133045f46ee984c56e3c3328caaf1aa1a583"), hex!("d848c5068ced736f4462159b9867fd4c20b808acc3d5bc48e0b06ba0a3762ec4"), @@ -66,7 +145,7 @@ fn pat_c() { let m: Vec = iter::repeat_n(0xFF, 2usize.pow(i) - 1).collect(); let len = 41usize.pow(i); let c: Vec = (0..len).map(|j| (j % 251) as u8).collect(); - let mut h = KangarooTwelve::new(&c); + let mut h = Kt128::new(&c); h.update(&m); let result = h.finalize_boxed(32); assert_eq!(result[..], expected[i as usize][..]); @@ -74,7 +153,38 @@ fn pat_c() { } #[test] -fn input_multiple_of_chunk_size_minus_one() { +fn kt256_pat_c() { + let expected = [ + hex!( + "9280f5cc39b54a5a594ec63de0bb99371e4609d44bf845c2f5b8c316d72b1598" + "11f748f23e3fabbe5c3226ec96c62186df2d33e9df74c5069ceecbb4dd10eff6" + ), + hex!( + "47ef96dd616f200937aa7847e34ec2feae8087e3761dc0f8c1a154f51dc9ccf8" + "45d7adbce57ff64b639722c6a1672e3bf5372d87e00aff89be97240756998853" + ), + hex!( + "3b48667a5051c5966c53c5d42b95de451e05584e7806e2fb765eda959074172c" + "b438a9e91dde337c98e9c41bed94c4e0aef431d0b64ef2324f7932caa6f54969" + ), + hex!( + "e0911cc00025e1540831e266d94add9b98712142b80d2629e643aac4efaf5a3a" + "30a88cbf4ac2a91a2432743054fbcc9897670e86ba8cec2fc2ace9c966369724" + ), + ]; + for i in 0..4 { + let m: Vec = iter::repeat_n(0xFF, 2usize.pow(i) - 1).collect(); + let len = 41usize.pow(i); + let c: Vec = (0..len).map(|j| (j % 251) as u8).collect(); + let mut h = Kt256::new(&c); + h.update(&m); + let result = h.finalize_boxed(64); + assert_eq!(result[..], expected[i as usize][..]); + } +} + +#[test] +fn kt128_input_multiple_of_chunk_size_minus_one() { // generated with reference python implementation let expected = [ hex!("1b577636f723643e990cc7d6a659837436fd6a103626600eb8301cd1dbe553d6"), @@ -85,13 +195,13 @@ fn input_multiple_of_chunk_size_minus_one() { for (i, exp_res) in expected.iter().enumerate() { let len = 8192 * (i + 1) - 1; let m: Vec = (0..len).map(|j| (j % 251) as u8).collect(); - let result = digest_and_box(&m, 32); + let result = kt128_digest_and_box(&m, 32); assert_eq!(result[..], exp_res[..]); } } #[test] -fn input_multiple_of_chunk_size() { +fn kt128_input_multiple_of_chunk_size() { // generated with reference python implementation let expected = [ hex!("48f256f6772f9edfb6a8b661ec92dc93b95ebd05a08a17b39ae3490870c926c3"), @@ -102,7 +212,7 @@ fn input_multiple_of_chunk_size() { for (i, exp_res) in expected.iter().enumerate() { let len = 8192 * (i + 1); let m: Vec = (0..len).map(|j| (j % 251) as u8).collect(); - let result = digest_and_box(&m, 32); + let result = kt128_digest_and_box(&m, 32); assert_eq!(result[..], exp_res[..]); } }