k12: add Kt256; rename KangarooTwelve to Kt128 (#756)

This implement KT256 as specified in RFC 9861:

https://www.rfc-editor.org/rfc/rfc9861.html

Also, rename existing types `KangarooTwelve*` to `Kt128*` (e.g.
`KangarooTwelveReader` to `Kt128Reader`). This is because the
KangarooTwelve instance is specified as the KT128 instance in RFC
9861.[1]

NOTE:  For compatibility reasons, the existing types are defined as
deprecated aliases for `Kt128*`.

[1]: https://www.rfc-editor.org/rfc/rfc9861.html#section-1-3
This commit is contained in:
Shun Sakai
2026-01-13 00:17:43 +09:00
committed by GitHub
parent ed7a207819
commit 3fb4aa5c7a
4 changed files with 473 additions and 270 deletions

View File

@@ -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;
);

View File

@@ -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,
}
}
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();
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,
}
self.chain_length += 1;
self.buffer = [0u8; CHUNK_SIZE];
self.bufpos = 0;
}
impl<'cs> $name<'cs> {
const CHAINING_VALUE_SIZE: usize = $cv_size;
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; 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 BlockSizeUser for KangarooTwelveCore<'_> {
type BlockSize = U128;
}
impl BufferKindUser for KangarooTwelveCore<'_> {
type BufferKind = Eager;
}
impl UpdateCore for KangarooTwelveCore<'_> {
#[inline]
fn update_blocks(&mut self, blocks: &[Block<Self>]) {
for block in blocks {
if self.bufpos == CHUNK_SIZE {
self.process_chunk();
#[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.buffer[self.bufpos..self.bufpos + 128].clone_from_slice(block);
self.bufpos += 128;
}
}
}
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 ExtendableOutputCore for KangarooTwelveCore<'_> {
type ReaderCore = KangarooTwelveReaderCore;
self.chain_length += 1;
self.buffer = [0u8; CHUNK_SIZE];
self.bufpos = 0;
}
#[inline]
fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
let mut lenbuf = [0u8; LENGTH_ENCODE_SIZE];
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]);
}
// 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();
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);
}
}
// 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();
impl HashMarker for $name<'_> {}
// 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 BlockSizeUser for $name<'_> {
type BlockSize = U128;
}
// 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 BufferKindUser for $name<'_> {
type BufferKind = Eager;
}
}
}
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 UpdateCore for $name<'_> {
#[inline]
fn update_blocks(&mut self, blocks: &[Block<Self>]) {
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;
}
}
}
}
}
impl Reset for KangarooTwelveCore<'_> {
#[inline]
fn reset(&mut self) {
*self = Self::new(self.customization);
}
}
impl ExtendableOutputCore for $name<'_> {
type ReaderCore = $reader_name;
impl AlgorithmName for KangarooTwelveCore<'_> {
fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(stringify!(KangarooTwelve))
}
}
#[inline]
fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
let mut lenbuf = [0u8; LENGTH_ENCODE_SIZE];
impl fmt::Debug for KangarooTwelveCore<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(concat!(stringify!(KangarooTwelveCore), " { ... }"))
}
}
// 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(),
}
}
}
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,
}
}
}
impl Reset for $name<'_> {
#[inline]
fn reset(&mut self) {
*self = Self::new(self.customization);
}
}
impl AlgorithmName for $name<'_> {
fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str($alg_name)
}
}
impl fmt::Debug for $name<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(concat!(stringify!($name), " { ... }"))
}
}
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,
}
}
impl XofReaderCore for $reader_name {
#[inline]
fn read_block(&mut self) -> Block<Self> {
let mut block = Block::<Self>::default();
self.tshk.read(&mut block);
block
}
}
// `Sha3ReaderCore` and the wrapper are zeroized by their Drop impls
#[cfg(feature = "zeroize")]
impl digest::zeroize::ZeroizeOnDrop for $reader_name {}
};
}
#[cfg(feature = "zeroize")]
impl digest::zeroize::ZeroizeOnDrop for KangarooTwelveCore<'_> {}
impl_k12_core!(
Kt128Core,
Kt128ReaderCore,
TurboShake128,
TurboShake128Reader,
32,
"KT128",
);
impl_k12_core!(
Kt256Core,
Kt256ReaderCore,
TurboShake256,
TurboShake256Reader,
64,
"KT256",
);
/// Core [`KangarooTwelve`] reader state.
#[derive(Clone)]
pub struct KangarooTwelveReaderCore {
tshk: TurboShake128Reader,
}
impl BlockSizeUser for KangarooTwelveReaderCore {
impl BlockSizeUser for Kt128ReaderCore {
type BlockSize = U168; // TurboSHAKE128 block size
}
impl XofReaderCore for KangarooTwelveReaderCore {
#[inline]
fn read_block(&mut self) -> Block<Self> {
let mut block = Block::<Self>::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;

View File

@@ -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<U128, Eager>,
}
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(),
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<U128, Eager>,
}
}
}
impl fmt::Debug for KangarooTwelve<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.write_str("KangarooTwelve { .. }")
}
}
impl AlgorithmName for KangarooTwelve<'_> {
fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("KangarooTwelve")
}
}
impl HashMarker for KangarooTwelve<'_> {}
impl BlockSizeUser for KangarooTwelve<'_> {
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 Reset for KangarooTwelve<'_> {
fn reset(&mut self) {
self.core.reset();
self.buffer.reset();
}
}
impl ExtendableOutput for KangarooTwelve<'_> {
type Reader = KangarooTwelveReader;
#[inline]
fn finalize_xof(mut self) -> Self::Reader {
Self::Reader {
core: self.core.finalize_xof_core(&mut self.buffer),
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 $name<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.write_str(concat!(stringify!($name), " { .. }"))
}
}
impl AlgorithmName for $name<'_> {
fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str($alg_name)
}
}
impl HashMarker for $name<'_> {}
impl BlockSizeUser for $name<'_> {
type BlockSize = U128;
}
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 $name<'_> {
fn reset(&mut self) {
self.core.reset();
self.buffer.reset();
}
}
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(),
}
}
}
#[cfg(feature = "zeroize")]
impl digest::zeroize::ZeroizeOnDrop for $name<'_> {}
#[doc = $alg_name]
#[doc = "XOF reader."]
pub struct $reader_name {
core: block_api::$reader_core_name,
buffer: ReadBuffer<$rate>,
}
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 CollisionResistance for KangarooTwelve<'_> {
// https://www.ietf.org/archive/id/draft-irtf-cfrg-kangarootwelve-17.html#section-7-7
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;
}
#[cfg(feature = "zeroize")]
impl digest::zeroize::ZeroizeOnDrop for KangarooTwelve<'_> {}
/// `KangarooTwelve` XOF reader.
pub struct KangarooTwelveReader {
core: block_api::KangarooTwelveReaderCore,
buffer: ReadBuffer<U168>,
impl CollisionResistance for Kt256<'_> {
// https://www.rfc-editor.org/rfc/rfc9861.html#section-7-8
type CollisionResistance = U32;
}
impl fmt::Debug for KangarooTwelveReader {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.write_str("KangarooTwelveReader { .. }")
}
}
/// KT128 hasher.
#[deprecated(since = "0.4.0-pre", note = "use `Kt128` instead")]
pub type KangarooTwelve<'cs> = Kt128<'cs>;
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());
}
}
#[cfg(feature = "zeroize")]
impl digest::zeroize::ZeroizeOnDrop for KangarooTwelveReader {}
/// KT128 XOF reader.
#[deprecated(since = "0.4.0-pre", note = "use `Kt128Reader` instead")]
pub type KangarooTwelveReader = Kt128Reader;

View File

@@ -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: <https://www.rfc-editor.org/rfc/rfc9861.html#section-5>
#[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<u8> = (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 pat_c() {
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<u8> = (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 kt128_pat_c() {
let expected = [
hex!("fab658db63e94a246188bf7af69a133045f46ee984c56e3c3328caaf1aa1a583"),
hex!("d848c5068ced736f4462159b9867fd4c20b808acc3d5bc48e0b06ba0a3762ec4"),
@@ -66,7 +145,7 @@ fn pat_c() {
let m: Vec<u8> = iter::repeat_n(0xFF, 2usize.pow(i) - 1).collect();
let len = 41usize.pow(i);
let c: Vec<u8> = (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<u8> = iter::repeat_n(0xFF, 2usize.pow(i) - 1).collect();
let len = 41usize.pow(i);
let c: Vec<u8> = (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<u8> = (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<u8> = (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[..]);
}
}