curv/cryptographic_primitives/commitments/
hash_commitment.rs1use std::marker::PhantomData;
9
10use digest::Digest;
11
12use crate::arithmetic::traits::*;
13use crate::BigInt;
14
15use super::traits::Commitment;
16use super::SECURITY_BITS;
17
18pub struct HashCommitment<H: Digest + Clone>(PhantomData<H>);
22
23impl<H: Digest + Clone> Commitment<BigInt> for HashCommitment<H> {
25 fn create_commitment_with_user_defined_randomness(
26 message: &BigInt,
27 blinding_factor: &BigInt,
28 ) -> BigInt {
29 let digest_result = H::new()
30 .chain(message.to_bytes())
31 .chain(blinding_factor.to_bytes())
32 .finalize();
33 BigInt::from_bytes(digest_result.as_ref())
34 }
35
36 fn create_commitment(message: &BigInt) -> (BigInt, BigInt) {
37 let blinding_factor = BigInt::sample(SECURITY_BITS);
38 let com = Self::create_commitment_with_user_defined_randomness(message, &blinding_factor);
39 (com, blinding_factor)
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::Commitment;
46 use super::HashCommitment;
47 use super::SECURITY_BITS;
48 use crate::arithmetic::traits::*;
49 use crate::{test_for_all_hashes, BigInt};
50 use digest::Digest;
51
52 test_for_all_hashes!(test_bit_length_create_commitment);
53 fn test_bit_length_create_commitment<H: Digest + Clone>() {
54 let hex_len = H::output_size() * 8;
55 let mut ctr_commit_len = 0;
56 let mut ctr_blind_len = 0;
57 let sample_size = 10_000;
58 for _ in 1..sample_size {
59 let message = BigInt::sample(hex_len);
60 let (commitment, blind_factor) = HashCommitment::<H>::create_commitment(&message);
61 if commitment.bit_length() == hex_len {
62 ctr_commit_len += 1;
63 }
64 if blind_factor.bit_length() == SECURITY_BITS {
66 ctr_blind_len += 1;
67 }
68 }
69 let ctr_commit_len = ctr_commit_len as f32;
72 let ctr_blind_len = ctr_blind_len as f32;
73 let sample_size = sample_size as f32;
74 assert!(ctr_commit_len / sample_size > 0.3);
75 assert!(ctr_blind_len / sample_size > 0.3);
76 }
77
78 test_for_all_hashes!(test_bit_length_create_commitment_with_user_defined_randomness);
79 fn test_bit_length_create_commitment_with_user_defined_randomness<H: Digest + Clone>() {
80 let sec_bits = H::output_size() * 8;
81 let message = BigInt::sample(sec_bits);
82 let (_commitment, blind_factor) = HashCommitment::<H>::create_commitment(&message);
83 let commitment2 = HashCommitment::<H>::create_commitment_with_user_defined_randomness(
84 &message,
85 &blind_factor,
86 );
87 assert!(commitment2.to_hex().len() / 2 <= sec_bits / 8);
88 }
89
90 test_for_all_hashes!(test_random_num_generation_create_commitment_with_user_defined_randomness);
91 fn test_random_num_generation_create_commitment_with_user_defined_randomness<
92 H: Digest + Clone,
93 >() {
94 let message = BigInt::sample(SECURITY_BITS);
95 let (commitment, blind_factor) = HashCommitment::<H>::create_commitment(&message);
96 let commitment2 = HashCommitment::<H>::create_commitment_with_user_defined_randomness(
97 &message,
98 &blind_factor,
99 );
100 assert_eq!(commitment, commitment2);
101 }
102
103 test_for_all_hashes!(test_hashing_create_commitment_with_user_defined_randomness);
104 fn test_hashing_create_commitment_with_user_defined_randomness<H: Digest + Clone>() {
105 let mut digest = H::new();
106 let message = BigInt::one();
107 let commitment = HashCommitment::<H>::create_commitment_with_user_defined_randomness(
108 &message,
109 &BigInt::zero(),
110 );
111 let message2 = message.to_bytes();
112 digest.update(&message2);
113 let bytes_blinding_factor = &BigInt::zero().to_bytes();
114 digest.update(&bytes_blinding_factor);
115 let hash_result = BigInt::from_bytes(digest.finalize().as_ref());
116 assert_eq!(&commitment, &hash_result);
117 }
118}