Skip to main content

k12/custom/
owned.rs

1extern crate alloc;
2
3use alloc::vec::Vec;
4use core::fmt;
5use digest::{
6    CollisionResistance, CustomizedInit, ExtendableOutput, ExtendableOutputReset, HashMarker,
7    Reset, Update,
8    common::AlgorithmName,
9    consts::{U16, U32},
10};
11
12use crate::{Kt, KtReader, utils::length_encode};
13
14/// Customized KangarooTwelve hasher generic over rate with owned customization string.
15#[derive(Clone)]
16pub struct CustomKt<const RATE: usize> {
17    customization: Vec<u8>,
18    inner: Kt<RATE>,
19}
20
21impl<const RATE: usize> CustomizedInit for CustomKt<RATE> {
22    #[inline]
23    fn new_customized(customization: &[u8]) -> Self {
24        let len = u64::try_from(customization.len()).expect("length should always fit into `u64`");
25        let mut buf = Vec::new();
26        length_encode(len, |enc_len| {
27            buf = Vec::with_capacity(customization.len() + enc_len.len());
28            buf.extend_from_slice(customization);
29            buf.extend_from_slice(enc_len);
30        });
31
32        Self {
33            customization: buf,
34            inner: Default::default(),
35        }
36    }
37}
38
39impl<const RATE: usize> Default for CustomKt<RATE> {
40    #[inline]
41    fn default() -> Self {
42        Self::new_customized(&[])
43    }
44}
45
46impl<const RATE: usize> fmt::Debug for CustomKt<RATE> {
47    #[inline]
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
49        write!(f, "CustomKt{} {{ ... }}", 4 * (200 - RATE))
50    }
51}
52
53impl<const RATE: usize> AlgorithmName for CustomKt<RATE> {
54    #[inline]
55    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        Kt::<RATE>::write_alg_name(f)
57    }
58}
59
60impl<const RATE: usize> HashMarker for CustomKt<RATE> {}
61
62impl<const RATE: usize> Update for CustomKt<RATE> {
63    #[inline]
64    fn update(&mut self, data: &[u8]) {
65        self.inner.update(data);
66    }
67}
68
69impl<const RATE: usize> Reset for CustomKt<RATE> {
70    #[inline]
71    fn reset(&mut self) {
72        self.inner.reset();
73    }
74}
75
76impl<const RATE: usize> ExtendableOutput for CustomKt<RATE> {
77    type Reader = KtReader<RATE>;
78
79    #[inline]
80    fn finalize_xof(mut self) -> Self::Reader {
81        self.inner.update(&self.customization);
82        self.inner.raw_finalize()
83    }
84}
85
86impl<const RATE: usize> ExtendableOutputReset for CustomKt<RATE> {
87    #[inline]
88    fn finalize_xof_reset(&mut self) -> Self::Reader {
89        self.inner.update(&self.customization);
90        let reader = self.inner.raw_finalize();
91        self.inner.reset();
92        reader
93    }
94}
95
96impl<const RATE: usize> Drop for CustomKt<RATE> {
97    #[inline]
98    fn drop(&mut self) {
99        #[cfg(feature = "zeroize")]
100        {
101            use digest::zeroize::Zeroize;
102            self.customization.zeroize();
103            // `inner` is zeroized by `Drop`
104        }
105    }
106}
107
108#[cfg(feature = "zeroize")]
109impl<const RATE: usize> digest::zeroize::ZeroizeOnDrop for CustomKt<RATE> {}
110
111/// Customized KT128 hasher with owned customization string.
112pub type CustomKt128 = CustomKt<168>;
113/// Customized KT256 hasher with owned customization string.
114pub type CustomKt256 = CustomKt<136>;
115
116impl CollisionResistance for CustomKt128 {
117    // https://www.rfc-editor.org/rfc/rfc9861.html#section-7-7
118    type CollisionResistance = U16;
119}
120
121impl CollisionResistance for CustomKt256 {
122    // https://www.rfc-editor.org/rfc/rfc9861.html#section-7-8
123    type CollisionResistance = U32;
124}