Skip to main content

k12/custom/
borrow.rs

1use core::fmt;
2use digest::{
3    CollisionResistance, ExtendableOutput, ExtendableOutputReset, HashMarker, Reset, Update,
4    common::AlgorithmName,
5    consts::{U16, U32},
6};
7
8use crate::{Kt, KtReader, utils::length_encode};
9
10/// Customized KangarooTwelve hasher generic over rate with borrrowed customization string.
11#[derive(Clone)]
12pub struct CustomRefKt<'a, const RATE: usize> {
13    customization: &'a [u8],
14    inner: Kt<RATE>,
15}
16
17impl<'a, const RATE: usize> CustomRefKt<'a, RATE> {
18    /// Create new customized KangarooTwelve hasher with borrrowed customization string.
19    ///
20    /// Note that this is an inherent method and `CustomRefKt` does not implement
21    /// the [`CustomizedInit`][digest::CustomizedInit] trait.
22    #[inline]
23    #[must_use]
24    pub fn new_customized(customization: &'a [u8]) -> Self {
25        Self {
26            customization,
27            inner: Default::default(),
28        }
29    }
30}
31
32impl<const RATE: usize> Default for CustomRefKt<'static, RATE> {
33    #[inline]
34    fn default() -> Self {
35        Self::new_customized(&[])
36    }
37}
38
39impl<const RATE: usize> fmt::Debug for CustomRefKt<'_, RATE> {
40    #[inline]
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
42        write!(f, "CustomKt{} {{ ... }}", 4 * (200 - RATE))
43    }
44}
45
46impl<const RATE: usize> AlgorithmName for CustomRefKt<'_, RATE> {
47    #[inline]
48    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        Kt::<RATE>::write_alg_name(f)
50    }
51}
52
53impl<const RATE: usize> HashMarker for CustomRefKt<'_, RATE> {}
54
55impl<const RATE: usize> Update for CustomRefKt<'_, RATE> {
56    #[inline]
57    fn update(&mut self, data: &[u8]) {
58        self.inner.update(data);
59    }
60}
61
62impl<const RATE: usize> Reset for CustomRefKt<'_, RATE> {
63    #[inline]
64    fn reset(&mut self) {
65        self.inner.reset();
66    }
67}
68
69impl<const RATE: usize> CustomRefKt<'_, RATE> {
70    fn absorb_customization(&mut self) {
71        self.inner.update(self.customization);
72        let len = u64::try_from(self.customization.len()).expect("length always fits into `u64`");
73        length_encode(len, |enc_len| self.inner.update(enc_len));
74    }
75}
76
77impl<const RATE: usize> ExtendableOutput for CustomRefKt<'_, RATE> {
78    type Reader = KtReader<RATE>;
79
80    #[inline]
81    fn finalize_xof(mut self) -> Self::Reader {
82        self.absorb_customization();
83        self.inner.raw_finalize()
84    }
85}
86
87impl<const RATE: usize> ExtendableOutputReset for CustomRefKt<'_, RATE> {
88    #[inline]
89    fn finalize_xof_reset(&mut self) -> Self::Reader {
90        self.absorb_customization();
91        let reader = self.inner.raw_finalize();
92        self.inner.reset();
93        reader
94    }
95}
96
97// `inner` is zeroized by `Drop` and `customization` can not be zeroized
98#[cfg(feature = "zeroize")]
99impl<const RATE: usize> digest::zeroize::ZeroizeOnDrop for CustomRefKt<'_, RATE> {}
100
101/// Customized KT128 hasher with borrowed customization string.
102pub type CustomRefKt128<'a> = CustomRefKt<'a, 168>;
103/// Customized KT256 hasher with borrowed customization string.
104pub type CustomRefKt256<'a> = CustomRefKt<'a, 136>;
105
106impl CollisionResistance for CustomRefKt128<'_> {
107    type CollisionResistance = U16;
108}
109
110impl CollisionResistance for CustomRefKt256<'_> {
111    type CollisionResistance = U32;
112}