darkfi/blockchain/monero/
keccak.rs1use std::io::{Cursor, Read, Result, Write};
20
21#[allow(unused_imports)]
22use tiny_keccak::{Hasher, Keccak};
23
24#[repr(C)]
25#[allow(unused)]
26enum Mode {
27 Absorbing,
28 Squeezing,
29}
30
31#[repr(C)]
32struct KeccakState {
34 buffer: [u8; 200],
35 offset: usize,
36 rate: usize,
37 delim: u8,
38 mode: Mode,
39}
40
41unsafe fn serialize_keccak<W: Write>(keccak: &Keccak, writer: &mut W) -> Result<()> {
42 let keccak_ptr = keccak as *const Keccak as *const KeccakState;
43 let keccak_state = &*keccak_ptr;
44
45 writer.write_all(&keccak_state.buffer)?;
46 writer.write_all(&(keccak_state.offset as u64).to_le_bytes())?;
47 writer.write_all(&(keccak_state.rate as u64).to_le_bytes())?;
48 writer.write_all(&[keccak_state.delim])?;
49
50 Ok(())
51}
52
53unsafe fn deserialize_keccak<R: Read>(reader: &mut R) -> Result<Keccak> {
54 let mut keccak = Keccak::v256();
55
56 let keccak_ptr = &mut keccak as *mut Keccak as *mut KeccakState;
57 let keccak_state = &mut *keccak_ptr;
58
59 reader.read_exact(&mut keccak_state.buffer)?;
60
61 let mut offset_bytes = [0u8; 8];
62 reader.read_exact(&mut offset_bytes)?;
63 keccak_state.offset = u64::from_le_bytes(offset_bytes) as usize;
64
65 let mut rate_bytes = [0u8; 8];
66 reader.read_exact(&mut rate_bytes)?;
67 keccak_state.rate = u64::from_le_bytes(rate_bytes) as usize;
68
69 let mut delim_byte = [0u8; 1];
70 reader.read_exact(&mut delim_byte)?;
71 keccak_state.delim = delim_byte[0];
72
73 keccak_state.mode = Mode::Absorbing;
74
75 Ok(keccak)
76}
77
78pub fn keccak_to_bytes(keccak: &Keccak) -> Vec<u8> {
79 let mut bytes = vec![];
80 unsafe { serialize_keccak(keccak, &mut bytes).unwrap() }
81 bytes
82}
83
84pub fn keccak_from_bytes(bytes: &[u8]) -> Keccak {
85 let mut cursor = Cursor::new(bytes);
86 unsafe { deserialize_keccak(&mut cursor).unwrap() }
87}
88
89#[test]
90fn test_keccak_serde() {
91 let mut keccak = Keccak::v256();
92 keccak.update(b"foobar");
93
94 let ser = keccak_to_bytes(&keccak);
95
96 let mut digest1 = [0u8; 32];
97 keccak.finalize(&mut digest1);
98
99 let de = keccak_from_bytes(&ser);
100 let mut digest2 = [0u8; 32];
101 de.finalize(&mut digest2);
102
103 println!("{digest1:?}");
104 println!("{digest2:?}");
105
106 assert_eq!(digest1, digest2);
107}