1use std::fmt;
2use std::io;
3
4use crate::encoding::{bytes_to_rate_block, hash_to_bytes};
5use crate::field::Goldilocks;
6use crate::params::{self, OUTPUT_BYTES, OUTPUT_BYTES_PER_ELEMENT, OUTPUT_ELEMENTS, RATE, RATE_BYTES, WIDTH};
7
8const DOMAIN_HASH: u64 = 0x00;
10const DOMAIN_KEYED: u64 = 0x01;
11const DOMAIN_DERIVE_KEY_CONTEXT: u64 = 0x02;
12const DOMAIN_DERIVE_KEY_MATERIAL: u64 = 0x03;
13
14const CAPACITY_START: usize = RATE; #[derive(Clone, Copy, PartialEq, Eq, Hash)]
19pub struct Hash([u8; OUTPUT_BYTES]);
20
21impl Hash {
22 pub const fn from_bytes(bytes: [u8; OUTPUT_BYTES]) -> Self {
24 Self(bytes)
25 }
26
27 pub fn as_bytes(&self) -> &[u8; OUTPUT_BYTES] {
29 &self.0
30 }
31
32 pub fn to_hex(&self) -> String {
34 let mut s = String::with_capacity(OUTPUT_BYTES * 2);
35 for byte in &self.0 {
36 use fmt::Write;
37 write!(s, "{byte:02x}").unwrap();
38 }
39 s
40 }
41}
42
43impl From<[u8; OUTPUT_BYTES]> for Hash {
44 fn from(bytes: [u8; OUTPUT_BYTES]) -> Self {
45 Self(bytes)
46 }
47}
48
49#[cfg(feature = "serde")]
50impl serde::Serialize for Hash {
51 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
52 use serde::ser::SerializeTuple;
53 let mut seq = serializer.serialize_tuple(OUTPUT_BYTES)?;
54 for byte in &self.0 {
55 seq.serialize_element(byte)?;
56 }
57 seq.end()
58 }
59}
60
61#[cfg(feature = "serde")]
62impl<'de> serde::Deserialize<'de> for Hash {
63 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
64 struct HashVisitor;
65 impl<'de> serde::de::Visitor<'de> for HashVisitor {
66 type Value = Hash;
67
68 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
69 write!(formatter, "a byte array of length {OUTPUT_BYTES}")
70 }
71
72 fn visit_seq<A: serde::de::SeqAccess<'de>>(
73 self,
74 mut seq: A,
75 ) -> Result<Hash, A::Error> {
76 let mut bytes = [0u8; OUTPUT_BYTES];
77 for (i, byte) in bytes.iter_mut().enumerate() {
78 *byte = seq
79 .next_element()?
80 .ok_or_else(|| serde::de::Error::invalid_length(i, &self))?;
81 }
82 Ok(Hash(bytes))
83 }
84 }
85 deserializer.deserialize_tuple(OUTPUT_BYTES, HashVisitor)
86 }
87}
88
89impl AsRef<[u8]> for Hash {
90 fn as_ref(&self) -> &[u8] {
91 &self.0
92 }
93}
94
95impl fmt::Display for Hash {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 for byte in &self.0 {
98 write!(f, "{byte:02x}")?;
99 }
100 Ok(())
101 }
102}
103
104impl fmt::Debug for Hash {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 write!(f, "Hash({self})")
107 }
108}
109
110#[derive(Clone)]
119pub struct Hasher {
120 state: [Goldilocks; WIDTH],
121 buf: Vec<u8>,
122 absorbed: u64,
123}
124
125impl Hasher {
126 pub fn new() -> Self {
128 let mut state = [Goldilocks::new(0); WIDTH];
129 state[CAPACITY_START + 3] = Goldilocks::new(DOMAIN_HASH);
130 Self {
131 state,
132 buf: Vec::new(),
133 absorbed: 0,
134 }
135 }
136
137 pub fn new_keyed(key: &[u8; OUTPUT_BYTES]) -> Self {
141 let mut state = [Goldilocks::new(0); WIDTH];
142 state[CAPACITY_START + 3] = Goldilocks::new(DOMAIN_KEYED);
143
144 let mut hasher = Self {
146 state,
147 buf: Vec::new(),
148 absorbed: 0,
149 };
150 hasher.update(key.as_slice());
151 hasher
152 }
153
154 pub(crate) fn new_derive_key_context(context: &str) -> Self {
159 let mut state = [Goldilocks::new(0); WIDTH];
160 state[CAPACITY_START + 3] = Goldilocks::new(DOMAIN_DERIVE_KEY_CONTEXT);
161 let mut hasher = Self {
162 state,
163 buf: Vec::new(),
164 absorbed: 0,
165 };
166 hasher.update(context.as_bytes());
167 hasher
168 }
169
170 pub(crate) fn new_derive_key_material(context_hash: &Hash) -> Self {
172 let mut state = [Goldilocks::new(0); WIDTH];
173 state[CAPACITY_START + 3] = Goldilocks::new(DOMAIN_DERIVE_KEY_MATERIAL);
174
175 for (i, chunk) in context_hash.0.chunks(OUTPUT_BYTES_PER_ELEMENT).enumerate() {
177 let val = u64::from_le_bytes(chunk.try_into().unwrap());
178 state[i] = Goldilocks::new(val);
179 }
180 params::permute(&mut state);
181
182 Self {
183 state,
184 buf: Vec::new(),
185 absorbed: 0,
186 }
187 }
188
189 pub fn update(&mut self, data: &[u8]) -> &mut Self {
191 self.buf.extend_from_slice(data);
192 self.absorbed += data.len() as u64;
193
194 while self.buf.len() >= RATE_BYTES {
196 let block_bytes: Vec<u8> = self.buf.drain(..RATE_BYTES).collect();
197 let mut rate_block = [Goldilocks::new(0); RATE];
198 bytes_to_rate_block(&block_bytes, &mut rate_block);
199 self.absorb_block(&rate_block);
200 }
201
202 self
203 }
204
205 fn absorb_block(&mut self, block: &[Goldilocks; RATE]) {
207 for (i, block_elem) in block.iter().enumerate() {
208 self.state[i] = self.state[i] + *block_elem;
209 }
210 params::permute(&mut self.state);
211 }
212
213 fn finalize_state(&self) -> [Goldilocks; WIDTH] {
221 let mut state = self.state;
222 let mut padded = self.buf.clone();
223
224 padded.push(0x01);
226
227 padded.resize(RATE_BYTES, 0x00);
229
230 let mut rate_block = [Goldilocks::new(0); RATE];
232 bytes_to_rate_block(&padded, &mut rate_block);
233 for i in 0..RATE {
234 state[i] = state[i] + rate_block[i];
235 }
236
237 state[CAPACITY_START + 2] = Goldilocks::new(self.absorbed);
239
240 params::permute(&mut state);
241 state
242 }
243
244 pub fn finalize(&self) -> Hash {
246 let state = self.finalize_state();
247 let output: [Goldilocks; OUTPUT_ELEMENTS] = state[..OUTPUT_ELEMENTS]
248 .try_into()
249 .unwrap();
250 Hash(hash_to_bytes(&output))
251 }
252
253 pub fn finalize_xof(&self) -> OutputReader {
255 let state = self.finalize_state();
256 OutputReader {
257 state,
258 buffer: [0u8; OUTPUT_BYTES],
259 buffer_pos: OUTPUT_BYTES, }
261 }
262}
263
264impl Default for Hasher {
265 fn default() -> Self {
266 Self::new()
267 }
268}
269
270impl fmt::Debug for Hasher {
271 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
272 f.debug_struct("Hasher")
273 .field("absorbed", &self.absorbed)
274 .field("buffered", &self.buf.len())
275 .finish()
276 }
277}
278
279pub struct OutputReader {
284 state: [Goldilocks; WIDTH],
285 buffer: [u8; OUTPUT_BYTES],
286 buffer_pos: usize,
287}
288
289impl OutputReader {
290 pub fn fill(&mut self, output: &mut [u8]) {
292 let mut written = 0;
293 while written < output.len() {
294 if self.buffer_pos >= OUTPUT_BYTES {
295 self.squeeze();
296 }
297 let available = OUTPUT_BYTES - self.buffer_pos;
298 let needed = output.len() - written;
299 let n = available.min(needed);
300 output[written..written + n]
301 .copy_from_slice(&self.buffer[self.buffer_pos..self.buffer_pos + n]);
302 self.buffer_pos += n;
303 written += n;
304 }
305 }
306
307 fn squeeze(&mut self) {
309 let output_elems: [Goldilocks; OUTPUT_ELEMENTS] = self.state[..OUTPUT_ELEMENTS]
310 .try_into()
311 .unwrap();
312 self.buffer = hash_to_bytes(&output_elems);
313 self.buffer_pos = 0;
314 params::permute(&mut self.state);
315 }
316}
317
318impl io::Read for OutputReader {
319 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
320 self.fill(buf);
321 Ok(buf.len())
322 }
323}
324
325impl fmt::Debug for OutputReader {
326 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
327 f.debug_struct("OutputReader").finish_non_exhaustive()
328 }
329}
330
331#[cfg(test)]
332mod tests {
333 use super::*;
334
335 #[test]
336 fn hash_display_is_hex() {
337 let h = Hash([0xAB; OUTPUT_BYTES]);
338 let s = format!("{h}");
339 assert_eq!(s.len(), OUTPUT_BYTES * 2);
340 assert!(s.chars().all(|c| c.is_ascii_hexdigit()));
341 }
342
343 #[test]
344 fn empty_hash_is_not_zero() {
345 let h = Hasher::new().finalize();
346 assert_ne!(h.0, [0u8; OUTPUT_BYTES]);
347 }
348
349 #[test]
350 fn different_inputs_different_hashes() {
351 let h1 = Hasher::new().update(b"a").finalize();
352 let h2 = Hasher::new().update(b"b").finalize();
353 assert_ne!(h1, h2);
354 }
355
356 #[test]
357 fn streaming_consistency() {
358 let data = b"hello world, this is a test of streaming consistency!";
359 let one_shot = {
360 let mut h = Hasher::new();
361 h.update(data);
362 h.finalize()
363 };
364 let streamed = {
365 let mut h = Hasher::new();
366 h.update(&data[..5]);
367 h.update(&data[5..20]);
368 h.update(&data[20..]);
369 h.finalize()
370 };
371 assert_eq!(one_shot, streamed);
372 }
373
374 #[test]
375 fn streaming_across_rate_boundary() {
376 let data = vec![0x42u8; 100];
378 let one_shot = {
379 let mut h = Hasher::new();
380 h.update(&data);
381 h.finalize()
382 };
383 let byte_at_a_time = {
384 let mut h = Hasher::new();
385 for b in &data {
386 h.update(std::slice::from_ref(b));
387 }
388 h.finalize()
389 };
390 assert_eq!(one_shot, byte_at_a_time);
391 }
392
393 #[test]
394 fn domain_separation_hash_vs_keyed() {
395 let data = b"test data";
396 let plain = Hasher::new().update(data).finalize();
397 let keyed = Hasher::new_keyed(&[0u8; OUTPUT_BYTES]).update(data).finalize();
398 assert_ne!(plain, keyed);
399 }
400
401 #[test]
402 fn domain_separation_hash_vs_derive_key() {
403 let data = b"test material";
404 let plain = Hasher::new().update(data).finalize();
405 let ctx_hasher = Hasher::new_derive_key_context("test context");
406 let ctx_hash = ctx_hasher.finalize();
407 let derived = Hasher::new_derive_key_material(&ctx_hash)
408 .update(data)
409 .finalize();
410 assert_ne!(plain, derived);
411 }
412
413 #[test]
414 fn xof_first_32_match_finalize() {
415 let data = b"xof test";
416 let hash = Hasher::new().update(data).finalize();
417 let mut xof = Hasher::new().update(data).finalize_xof();
418 let mut xof_bytes = [0u8; OUTPUT_BYTES];
419 xof.fill(&mut xof_bytes);
420 assert_eq!(hash.as_bytes(), &xof_bytes);
421 }
422
423 #[test]
424 fn xof_produces_more_than_32_bytes() {
425 let mut xof = Hasher::new().update(b"xof").finalize_xof();
426 let mut out = [0u8; 128];
427 xof.fill(&mut out);
428 assert_ne!(out, [0u8; 128]);
430 assert_ne!(out[..OUTPUT_BYTES], out[OUTPUT_BYTES..OUTPUT_BYTES * 2]);
432 }
433
434 #[test]
435 fn xof_read_trait() {
436 use std::io::Read;
437 let mut xof = Hasher::new().update(b"read trait").finalize_xof();
438 let mut buf = [0u8; 64];
439 let n = xof.read(&mut buf).unwrap();
440 assert_eq!(n, 64);
441 }
442
443 #[test]
444 fn keyed_hash_different_keys() {
445 let data = b"same data";
446 let h1 = Hasher::new_keyed(&[0u8; OUTPUT_BYTES]).update(data).finalize();
447 let h2 = Hasher::new_keyed(&[1u8; OUTPUT_BYTES]).update(data).finalize();
448 assert_ne!(h1, h2);
449 }
450
451 #[test]
454 fn exact_rate_block_input() {
455 let data = vec![0x42u8; RATE_BYTES];
457 let h = Hasher::new().update(&data).finalize();
458 assert_ne!(h.0, [0u8; OUTPUT_BYTES]);
459 let h2 = {
461 let mut hasher = Hasher::new();
462 hasher.update(&data[..28]);
463 hasher.update(&data[28..]);
464 hasher.finalize()
465 };
466 assert_eq!(h, h2);
467 }
468
469 #[test]
470 fn exact_two_rate_blocks_input() {
471 let data = vec![0x42u8; RATE_BYTES * 2];
473 let h = Hasher::new().update(&data).finalize();
474 let h_streamed = {
475 let mut hasher = Hasher::new();
476 for chunk in data.chunks(17) { hasher.update(chunk);
478 }
479 hasher.finalize()
480 };
481 assert_eq!(h, h_streamed);
482 }
483
484 #[test]
485 fn one_less_than_rate_block() {
486 let data = vec![0x42u8; RATE_BYTES - 1];
488 let h = Hasher::new().update(&data).finalize();
489 assert_ne!(h.0, [0u8; OUTPUT_BYTES]);
490 }
491
492 #[test]
493 fn one_more_than_rate_block() {
494 let data = vec![0x42u8; RATE_BYTES + 1];
496 let h = Hasher::new().update(&data).finalize();
497 assert_ne!(h.0, [0u8; OUTPUT_BYTES]);
498 }
499
500 #[test]
503 fn hasher_clone_produces_same_hash() {
504 let mut h1 = Hasher::new();
505 h1.update(b"some data");
506 let h2 = h1.clone();
507 h1.update(b" more");
508 let mut h3 = h1.clone();
509 h3.update(b"");
510 assert_eq!(h1.finalize(), h3.finalize());
511 assert_ne!(h1.finalize(), h2.finalize());
513 }
514
515 #[test]
516 fn hasher_clone_mid_block() {
517 let mut h = Hasher::new();
518 h.update(&[0xAB; 30]); let cloned = h.clone();
520 h.update(&[0xCD; 30]);
521 let mut cloned2 = cloned.clone();
522 cloned2.update(&[0xCD; 30]);
523 assert_eq!(h.finalize(), cloned2.finalize());
524 }
525
526 #[test]
529 fn xof_incremental_reads_match_bulk() {
530 let mut xof1 = Hasher::new().update(b"xof incremental").finalize_xof();
531 let mut xof2 = Hasher::new().update(b"xof incremental").finalize_xof();
532
533 let mut bulk = [0u8; 200];
535 xof1.fill(&mut bulk);
536
537 let mut incremental = Vec::new();
539 for size in [1, 3, 7, 13, 64, 50, 62] {
540 let mut buf = vec![0u8; size];
541 xof2.fill(&mut buf);
542 incremental.extend_from_slice(&buf);
543 }
544
545 assert_eq!(&bulk[..], &incremental[..]);
546 }
547
548 #[test]
549 fn xof_deterministic() {
550 let mut xof1 = Hasher::new().update(b"deterministic").finalize_xof();
551 let mut xof2 = Hasher::new().update(b"deterministic").finalize_xof();
552 let mut out1 = [0u8; 256];
553 let mut out2 = [0u8; 256];
554 xof1.fill(&mut out1);
555 xof2.fill(&mut out2);
556 assert_eq!(out1, out2);
557 }
558
559 #[test]
560 fn xof_different_inputs_different_streams() {
561 let mut xof1 = Hasher::new().update(b"input A").finalize_xof();
562 let mut xof2 = Hasher::new().update(b"input B").finalize_xof();
563 let mut out1 = [0u8; 128];
564 let mut out2 = [0u8; 128];
565 xof1.fill(&mut out1);
566 xof2.fill(&mut out2);
567 assert_ne!(out1, out2);
568 }
569
570 #[test]
571 fn xof_zero_length_fill() {
572 let mut xof = Hasher::new().update(b"zero").finalize_xof();
573 let mut empty = [];
574 xof.fill(&mut empty); let mut out = [0u8; 64];
578 xof.fill(&mut out);
579 assert_ne!(out, [0u8; 64]);
580 }
581
582 #[test]
585 fn hash_from_bytes_roundtrip() {
586 let bytes = [0xAB; OUTPUT_BYTES];
587 let h = Hash::from_bytes(bytes);
588 assert_eq!(h.as_bytes(), &bytes);
589 }
590
591 #[test]
592 fn hash_to_hex_length() {
593 let h = Hash::from_bytes([0x00; OUTPUT_BYTES]);
594 assert_eq!(h.to_hex().len(), OUTPUT_BYTES * 2);
595 assert_eq!(h.to_hex(), "0".repeat(OUTPUT_BYTES * 2));
596 }
597
598 #[test]
599 fn hash_debug_format() {
600 let h = Hash::from_bytes([0x00; OUTPUT_BYTES]);
601 let debug = format!("{h:?}");
602 assert!(debug.starts_with("Hash("));
603 assert!(debug.ends_with(')'));
604 }
605
606 #[test]
607 fn hash_as_ref() {
608 let h = Hash::from_bytes([0x42; OUTPUT_BYTES]);
609 let slice: &[u8] = h.as_ref();
610 assert_eq!(slice.len(), OUTPUT_BYTES);
611 assert!(slice.iter().all(|&b| b == 0x42));
612 }
613
614 #[test]
615 fn hash_eq_and_hash_trait() {
616 use std::collections::HashSet;
617 let h1 = Hash::from_bytes([1; OUTPUT_BYTES]);
618 let h2 = Hash::from_bytes([1; OUTPUT_BYTES]);
619 let h3 = Hash::from_bytes([2; OUTPUT_BYTES]);
620 assert_eq!(h1, h2);
621 assert_ne!(h1, h3);
622
623 let mut set = HashSet::new();
624 set.insert(h1);
625 set.insert(h2);
626 set.insert(h3);
627 assert_eq!(set.len(), 2);
628 }
629
630 #[test]
633 fn hasher_default_matches_new() {
634 let h1 = Hasher::new().update(b"test").finalize();
635 let h2 = Hasher::default().update(b"test").finalize();
636 assert_eq!(h1, h2);
637 }
638
639 #[test]
642 fn all_four_domains_produce_different_outputs() {
643 let data = b"domain test data";
644
645 let plain = Hasher::new().update(data).finalize();
646
647 let keyed = Hasher::new_keyed(&[0u8; OUTPUT_BYTES])
648 .update(data)
649 .finalize();
650
651 let ctx = Hasher::new_derive_key_context("ctx");
652 let ctx_hash = ctx.finalize();
653 let derived = Hasher::new_derive_key_material(&ctx_hash)
654 .update(data)
655 .finalize();
656
657 let context_only = Hasher::new_derive_key_context(
658 std::str::from_utf8(data).unwrap()
659 ).finalize();
660
661 let hashes = [plain, keyed, derived, context_only];
663 for i in 0..hashes.len() {
664 for j in (i + 1)..hashes.len() {
665 assert_ne!(hashes[i], hashes[j], "domains {i} and {j} collide");
666 }
667 }
668 }
669
670 #[test]
673 fn keyed_hash_empty_data() {
674 let h = Hasher::new_keyed(&[0u8; OUTPUT_BYTES]).finalize();
675 assert_ne!(h.0, [0u8; OUTPUT_BYTES]);
676 }
677
678 #[test]
681 fn derive_key_empty_material() {
682 let key = crate::derive_key("context", b"");
683 assert_ne!(key, [0u8; OUTPUT_BYTES]);
684 }
685
686 #[test]
687 fn derive_key_empty_context() {
688 let key = crate::derive_key("", b"material");
689 assert_ne!(key, [0u8; OUTPUT_BYTES]);
690 }
691
692 #[test]
695 fn hasher_debug_shows_absorbed() {
696 let mut h = Hasher::new();
697 h.update(b"hello");
698 let debug = format!("{h:?}");
699 assert!(debug.contains("absorbed"));
700 assert!(debug.contains("5")); }
702
703 #[test]
708 fn pinned_empty_hash() {
709 let h1 = Hasher::new().finalize();
710 let h2 = Hasher::new().finalize();
711 assert_eq!(h1, h2);
712 let hex = h1.to_hex();
714 assert_eq!(hex.len(), 128); }
716
717 #[test]
719 fn pinned_hemera_hash() {
720 let h1 = crate::hash(b"hemera");
721 let h2 = crate::hash(b"hemera");
722 assert_eq!(h1, h2);
723 }
724
725 #[cfg(feature = "serde")]
726 #[test]
727 fn serde_roundtrip() {
728 let h = crate::hash(b"serde test");
729 let json = serde_json::to_string(&h).unwrap();
730 let recovered: Hash = serde_json::from_str(&json).unwrap();
731 assert_eq!(h, recovered);
732 }
733
734 #[cfg(feature = "serde")]
735 #[test]
736 fn serde_roundtrip_zero_hash() {
737 let h = Hash::from_bytes([0u8; OUTPUT_BYTES]);
738 let json = serde_json::to_string(&h).unwrap();
739 let recovered: Hash = serde_json::from_str(&json).unwrap();
740 assert_eq!(h, recovered);
741 }
742}