rs_keccak_nbits/
n_bit_keccak_hasher.rs

1use crate::NBitKeccakState;
2use core::hash::Hasher;
3use core::ops::{BitAnd, BitAndAssign, BitOr, BitXor, BitXorAssign, Not, Sub};
4use rs_hasher_ctx::{ByteArrayWrapper, GenericHasher, HasherContext};
5use rs_internal_hasher::HashAlgorithm;
6use rs_internal_state::ExtendedOutputFunction;
7use rs_n_bit_words::{LittleEndianBytes, NBitWord, Rotate, TSize};
8
9/// `NBitKeccakHasher` is a type that provides the Keccak-nBits hashing algorithm in RustyShield.
10///
11/// A "Hasher" in the context of cryptographic hashing refers to the object that manages the process of converting input
12/// data into a fixed-size sequence of bytes. The Hasher is responsible for maintaining the internal state of the
13/// hashing process and providing methods to add more data and retrieve the resulting hash.
14///
15/// The `NBitKeccakHasher` struct adheres to Rust's `Hasher` trait, enabling you to use it interchangeably with other
16/// hashers in Rust. It can be used anywhere a type implementing `Hasher` is required.
17///
18/// ## Examples
19///
20/// The following examples demonstrate using `NBitKeccakHasher` with both `Hash` and `Hasher`, and from where the
21/// difference comes from:
22///
23///```rust
24/// # use std::hash::{BuildHasher, Hash, Hasher};
25/// # use rs_keccak_nbits::NBitKeccakHasher;
26/// let data = b"hello";
27///
28/// // Using Hash
29/// let mut keccakhasher = NBitKeccakHasher::<u8, 4, 20>::default();
30/// data.hash(&mut keccakhasher);
31/// let result_via_hash = keccakhasher.finish();
32///
33/// // Using Hasher
34/// let mut keccakhasher = NBitKeccakHasher::<u8, 4, 20>::default();
35/// keccakhasher.write(data);
36/// let result_via_hasher = keccakhasher.finish();
37///
38/// // Simulating the Hash inners
39/// let mut keccakhasher = NBitKeccakHasher::<u8, 4, 20>::default();
40/// keccakhasher.write_usize(data.len());
41/// keccakhasher.write(data);
42/// let simulated_hash_result = keccakhasher.finish();
43///
44/// assert_ne!(result_via_hash, result_via_hasher);
45/// assert_eq!(result_via_hash, simulated_hash_result);
46///```
47#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
48pub struct NBitKeccakHasher<T, const RATE: usize, const OUTPUT_SIZE: usize>(
49    GenericHasher<NBitKeccakState<T, RATE, OUTPUT_SIZE>, OUTPUT_SIZE>,
50)
51where
52    T: BitAnd
53        + BitAndAssign
54        + BitOr<NBitWord<T>, Output = NBitWord<T>>
55        + BitXor<Output = T>
56        + BitXorAssign
57        + Copy
58        + Default
59        + Not<Output = T>,
60    NBitWord<T>: From<u64> + LittleEndianBytes + Not<Output = NBitWord<T>> + Rotate + TSize<T>,
61    u32: Sub<NBitWord<T>, Output = NBitWord<T>>;
62
63impl<T, const RATE: usize, const OUTPUT_SIZE: usize> From<NBitKeccakHasher<T, RATE, OUTPUT_SIZE>>
64    for NBitKeccakState<T, RATE, OUTPUT_SIZE>
65where
66    T: Copy
67        + Default
68        + BitAnd
69        + BitAndAssign
70        + BitOr<NBitWord<T>, Output = NBitWord<T>>
71        + BitXor<Output = T>
72        + BitXorAssign
73        + Not<Output = T>,
74    NBitWord<T>: From<u64> + LittleEndianBytes + Not<Output = NBitWord<T>> + Rotate + TSize<T>,
75    u32: Sub<NBitWord<T>, Output = NBitWord<T>>,
76{
77    fn from(value: NBitKeccakHasher<T, RATE, OUTPUT_SIZE>) -> Self {
78        value.0.state
79    }
80}
81
82impl<T, const RATE: usize, const OUTPUT_SIZE: usize> From<NBitKeccakState<T, RATE, OUTPUT_SIZE>>
83    for NBitKeccakHasher<T, RATE, OUTPUT_SIZE>
84    where
85        T: Copy
86        + Default
87        + BitAnd
88        + BitAndAssign
89        + BitOr<NBitWord<T>, Output = NBitWord<T>>
90        + BitXor<Output = T>
91        + BitXorAssign
92        + Not<Output = T>,
93        NBitWord<T>: From<u64> + LittleEndianBytes + Not<Output = NBitWord<T>> + Rotate + TSize<T>,
94        u32: Sub<NBitWord<T>, Output = NBitWord<T>>,
95{
96    fn from(value: NBitKeccakState<T, RATE, OUTPUT_SIZE>) -> Self {
97        Self(GenericHasher {
98            padding: <NBitKeccakState<T, RATE, OUTPUT_SIZE> as HashAlgorithm>::Padding::default(),
99            state: value,
100        })
101    }
102}
103
104impl<T, const RATE: usize, const OUTPUT_SIZE: usize> Hasher for NBitKeccakHasher<T, RATE, OUTPUT_SIZE>
105where
106    T: BitAnd
107        + BitAndAssign
108        + BitOr<NBitWord<T>, Output = NBitWord<T>>
109        + BitXor<Output = T>
110        + BitXorAssign
111        + Copy
112        + Default
113        + Not<Output = T>,
114    NBitWord<T>: From<u64> + LittleEndianBytes + Not<Output = NBitWord<T>> + Rotate + TSize<T>,
115    u32: Sub<NBitWord<T>, Output = NBitWord<T>>,
116{
117    fn finish(&self) -> u64 {
118        Hasher::finish(&self.0)
119    }
120
121    fn write(&mut self, bytes: &[u8]) {
122        self.0.write(bytes)
123    }
124}
125
126impl<T, const RATE: usize, const OUTPUT_SIZE: usize> HasherContext<OUTPUT_SIZE>
127    for NBitKeccakHasher<T, RATE, OUTPUT_SIZE>
128where
129    T: BitAnd
130        + BitAndAssign
131        + BitOr<NBitWord<T>, Output = NBitWord<T>>
132        + BitXor<Output = T>
133        + BitXorAssign
134        + Copy
135        + Default
136        + Not<Output = T>,
137    NBitWord<T>: From<u64> + LittleEndianBytes + Not<Output = NBitWord<T>> + Rotate + TSize<T>,
138    u32: Sub<NBitWord<T>, Output = NBitWord<T>>,
139{
140    type Output = ByteArrayWrapper<OUTPUT_SIZE>;
141
142    fn finish(&mut self) -> Self::Output {
143        HasherContext::finish(&mut self.0).squeeze().into()
144    }
145}