-
Notifications
You must be signed in to change notification settings - Fork 112
/
Copy pathhash_commitment.rs
118 lines (106 loc) · 4.68 KB
/
hash_commitment.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
This file is part of Curv library
Copyright 2018 by Kzen Networks
(https://github.com/KZen-networks/curv)
License MIT: https://github.com/KZen-networks/curv/blob/master/LICENSE
*/
use std::marker::PhantomData;
use digest::Digest;
use crate::arithmetic::traits::*;
use crate::BigInt;
use super::traits::Commitment;
use super::SECURITY_BITS;
//TODO: (open issue) use this struct to represent the commitment HashCommitment{comm: BigInt, r: BigInt, m: BigInt}
/// calculate commitment c = H(m,r) using SHA3 CRHF.
/// r is 256bit blinding factor, m is the commited value
pub struct HashCommitment<H: Digest + Clone>(PhantomData<H>);
//TODO: using the function with BigInt's as input instead of string's makes it impossible to commit to empty message or use empty randomness
impl<H: Digest + Clone> Commitment<BigInt> for HashCommitment<H> {
fn create_commitment_with_user_defined_randomness(
message: &BigInt,
blinding_factor: &BigInt,
) -> BigInt {
let digest_result = H::new()
.chain(message.to_bytes())
.chain(blinding_factor.to_bytes())
.finalize();
BigInt::from_bytes(digest_result.as_ref())
}
fn create_commitment(message: &BigInt) -> (BigInt, BigInt) {
let blinding_factor = BigInt::sample(SECURITY_BITS);
let com = Self::create_commitment_with_user_defined_randomness(message, &blinding_factor);
(com, blinding_factor)
}
}
#[cfg(test)]
mod tests {
use super::Commitment;
use super::HashCommitment;
use super::SECURITY_BITS;
use crate::arithmetic::traits::*;
use crate::{test_for_all_hashes, BigInt};
use digest::Digest;
test_for_all_hashes!(test_bit_length_create_commitment);
fn test_bit_length_create_commitment<H: Digest + Clone>() {
let hex_len = H::output_size() * 8;
let mut ctr_commit_len = 0;
let mut ctr_blind_len = 0;
let sample_size = 10_000;
for _ in 1..sample_size {
let message = BigInt::sample(hex_len);
let (commitment, blind_factor) = HashCommitment::<H>::create_commitment(&message);
if commitment.bit_length() == hex_len {
ctr_commit_len += 1;
}
// the blinding factor bit length is not related to the hash function.
if blind_factor.bit_length() == SECURITY_BITS {
ctr_blind_len += 1;
}
}
//test commitment length - works because SHA256 output length the same as sec_bits
// we test that the probability distribution is according to what is expected. ideally = 0.5
let ctr_commit_len = ctr_commit_len as f32;
let ctr_blind_len = ctr_blind_len as f32;
let sample_size = sample_size as f32;
assert!(ctr_commit_len / sample_size > 0.3);
assert!(ctr_blind_len / sample_size > 0.3);
}
test_for_all_hashes!(test_bit_length_create_commitment_with_user_defined_randomness);
fn test_bit_length_create_commitment_with_user_defined_randomness<H: Digest + Clone>() {
let sec_bits = H::output_size() * 8;
let message = BigInt::sample(sec_bits);
let (_commitment, blind_factor) = HashCommitment::<H>::create_commitment(&message);
let commitment2 = HashCommitment::<H>::create_commitment_with_user_defined_randomness(
&message,
&blind_factor,
);
assert!(commitment2.to_hex().len() / 2 <= sec_bits / 8);
}
test_for_all_hashes!(test_random_num_generation_create_commitment_with_user_defined_randomness);
fn test_random_num_generation_create_commitment_with_user_defined_randomness<
H: Digest + Clone,
>() {
let message = BigInt::sample(SECURITY_BITS);
let (commitment, blind_factor) = HashCommitment::<H>::create_commitment(&message);
let commitment2 = HashCommitment::<H>::create_commitment_with_user_defined_randomness(
&message,
&blind_factor,
);
assert_eq!(commitment, commitment2);
}
test_for_all_hashes!(test_hashing_create_commitment_with_user_defined_randomness);
fn test_hashing_create_commitment_with_user_defined_randomness<H: Digest + Clone>() {
let mut digest = H::new();
let message = BigInt::one();
let commitment = HashCommitment::<H>::create_commitment_with_user_defined_randomness(
&message,
&BigInt::zero(),
);
let message2 = message.to_bytes();
digest.update(&message2);
let bytes_blinding_factor = &BigInt::zero().to_bytes();
digest.update(&bytes_blinding_factor);
let hash_result = BigInt::from_bytes(digest.finalize().as_ref());
assert_eq!(&commitment, &hash_result);
}
}