1use core::{
2 convert::TryFrom,
3 fmt::Debug,
4 ops::{Deref, DerefMut},
5};
6use digest::{FixedOutput, Update};
7use tinyvec::ArrayVec;
8
9use crate::constants::{winternitz_chain::*, MAX_HASH_SIZE};
10
11pub mod sha256;
12pub mod shake256;
13
14pub struct HashChainData {
15 data: ArrayVec<[u8; ITER_MAX_LEN]>,
16}
17
18impl Deref for HashChainData {
19 type Target = ArrayVec<[u8; ITER_MAX_LEN]>;
20
21 fn deref(&self) -> &Self::Target {
22 &self.data
23 }
24}
25
26impl DerefMut for HashChainData {
27 fn deref_mut(&mut self) -> &mut Self::Target {
28 &mut self.data
29 }
30}
31
32pub trait HashChain:
43 Debug + Default + Clone + PartialEq + Send + Sync + FixedOutput + Update
44{
45 const OUTPUT_SIZE: u16;
46 const BLOCK_SIZE: u16;
47
48 fn finalize(self) -> ArrayVec<[u8; MAX_HASH_SIZE]>;
49 fn finalize_reset(&mut self) -> ArrayVec<[u8; MAX_HASH_SIZE]>;
50
51 fn prepare_hash_chain_data(
52 lms_tree_identifier: &[u8],
53 lms_leaf_identifier: &[u8],
54 ) -> HashChainData {
55 let mut hc_data = HashChainData {
56 data: ArrayVec::from_array_len(
57 [0u8; ITER_MAX_LEN],
58 iter_len(Self::OUTPUT_SIZE as usize),
59 ),
60 };
61 hc_data[ITER_I..ITER_Q].copy_from_slice(lms_tree_identifier);
62 hc_data[ITER_Q..ITER_K].copy_from_slice(lms_leaf_identifier);
63 hc_data
64 }
65
66 fn do_hash_chain(
67 &mut self,
68 hc_data: &mut HashChainData,
69 hash_chain_id: u16,
70 initial_value: &[u8],
71 from: usize,
72 to: usize,
73 ) -> ArrayVec<[u8; MAX_HASH_SIZE]> {
74 hc_data[ITER_K..ITER_J].copy_from_slice(&hash_chain_id.to_be_bytes());
75 hc_data[ITER_PREV..].copy_from_slice(initial_value);
76
77 self.do_actual_hash_chain(hc_data, from, to);
78
79 ArrayVec::try_from(&hc_data[ITER_PREV..]).unwrap()
80 }
81
82 fn do_actual_hash_chain(&mut self, hc_data: &mut HashChainData, from: usize, to: usize) {
83 for j in from..to {
84 hc_data[ITER_J] = j as u8;
85 self.update(&hc_data.data);
87 let temp_hash = self.finalize_reset();
88 hc_data[ITER_PREV..].copy_from_slice(temp_hash.as_slice());
89 }
90 }
91}