primitives/commitments/
hashbased.rs1use hybrid_array::Array;
2use subtle::ConstantTimeEq;
3
4use super::CommitmentScheme;
5use crate::{
6 constants::CollisionResistanceBytes,
7 errors::PrimitiveError,
8 hashing::{hash, Digest},
9 random::CryptoRngCore,
10 types::SessionId,
11};
12
13pub type Commitment = Digest;
14pub type Witness = Array<u8, CollisionResistanceBytes>;
15
16#[derive(Default, Copy, Clone, Debug)]
17pub struct HashBasedCommitment {
18 session_id: Option<SessionId>,
19}
20
21impl HashBasedCommitment {
22 pub fn new() -> Self {
23 Self { session_id: None }
24 }
25 pub fn new_with_session_id(session_id: SessionId) -> Self {
26 Self {
27 session_id: Some(session_id),
28 }
29 }
30}
31
32impl<T> CommitmentScheme<T> for HashBasedCommitment
33where
34 T: AsRef<[u8]>,
35{
36 type Commitment = Commitment;
37 type Witness = Witness;
38
39 fn commit<R: CryptoRngCore>(&self, input: &T, mut rng: R) -> (Self::Commitment, Self::Witness) {
40 let mut w = Witness::default();
42 rng.fill_bytes(&mut w);
43
44 let c = match self.session_id {
46 Some(session_id) => hash(&[w.as_ref(), input.as_ref(), session_id.as_ref()]),
47 None => hash(&[w.as_ref(), input.as_ref()]),
48 };
49
50 (c, w)
51 }
52
53 fn open(
54 &self,
55 c: &Self::Commitment,
56 w: &Self::Witness,
57 input: &T,
58 ) -> Result<(), PrimitiveError> {
59 let c_prime = match self.session_id {
61 Some(session_id) => hash(&[w.as_ref(), input.as_ref(), session_id.as_ref()]),
62 None => hash(&[w.as_ref(), input.as_ref()]),
63 };
64 bool::from(c.ct_eq(&c_prime))
66 .then_some(())
67 .ok_or_else(|| PrimitiveError::WrongOpening(format!("{c:?}"), format!("{c_prime:?}")))
68 }
69}