Skip to content

Commit

Permalink
Make the commitments generic over the hash function and remove deprec…
Browse files Browse the repository at this point in the history
…ated hashing traits (#129)

* Delete deprecated hashing traits and structures
* Make cryptographic commitments generic over the hash function
* Add a macro to test against a bunch of hash functions and move test macros to a new module
* Make the tests iterate over a bunch of hash functions
* Make merkle_tree::MT256 Send/Sync even if E isn't
* Update LdeiProof
  • Loading branch information
elichai authored Sep 9, 2021
1 parent fce3eab commit 1569c91
Show file tree
Hide file tree
Showing 20 changed files with 430 additions and 311 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ name = "curv"
crate-type = ["lib"]

[dependencies]
blake2b_simd = "0.5.7"
cryptoxide = "0.1.2"
curve25519-dalek = "3"
digest = "0.9"
Expand Down Expand Up @@ -57,6 +56,7 @@ serde_test = "1.0"
paste = "1.0.2"
proptest = "0.10"
proptest-derive = "0.2"
blake2 = "0.9"

[features]
default = ["rust-gmp-kzen"]
Expand Down
3 changes: 2 additions & 1 deletion examples/proof_of_knowledge_of_dlog.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use curv::elliptic::curves::*;
use sha2::Sha256;

/// Sigma protocol for proof of knowledge of discrete log
/// TO RUN:
Expand All @@ -13,7 +14,7 @@ pub fn dlog_proof<E: Curve>() {
use curv::cryptographic_primitives::proofs::sigma_dlog::*;

let witness = Scalar::random();
let dlog_proof = DLogProof::<E>::prove(&witness);
let dlog_proof = DLogProof::<E, Sha256>::prove(&witness);
assert!(DLogProof::verify(&dlog_proof).is_ok());
}

Expand Down
94 changes: 51 additions & 43 deletions src/cryptographic_primitives/commitments/hash_commitment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,37 @@
License MIT: https://github.com/KZen-networks/curv/blob/master/LICENSE
*/

//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;
use std::marker::PhantomData;

use digest::Digest;

use crate::arithmetic::traits::*;
use crate::BigInt;

use super::traits::Commitment;
use super::SECURITY_BITS;
use crate::arithmetic::traits::*;
use sha3::{Digest, Sha3_256};

//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 Commitment<BigInt> for HashCommitment {
impl<H: Digest + Clone> Commitment<BigInt> for HashCommitment<H> {
fn create_commitment_with_user_defined_randomness(
message: &BigInt,
blinding_factor: &BigInt,
) -> BigInt {
let mut digest = Sha3_256::new();
let bytes_message = message.to_bytes();
digest.update(&bytes_message);
let bytes_blinding_factor = blinding_factor.to_bytes();
digest.update(&bytes_blinding_factor);
BigInt::from_bytes(digest.finalize().as_ref())
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 = HashCommitment::create_commitment_with_user_defined_randomness(
message,
&blinding_factor,
);
let com = Self::create_commitment_with_user_defined_randomness(message, &blinding_factor);
(com, blinding_factor)
}
}
Expand All @@ -46,57 +46,65 @@ mod tests {
use super::HashCommitment;
use super::SECURITY_BITS;
use crate::arithmetic::traits::*;
use crate::BigInt;
use sha3::{Digest, Sha3_256};
use crate::{test_for_all_hashes, BigInt};
use digest::Digest;

#[test]
fn test_bit_length_create_commitment() {
let hex_len = SECURITY_BITS;
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 = 1000;
let sample_size = 10_000;
for _ in 1..sample_size {
let message = BigInt::sample(SECURITY_BITS);
let (commitment, blind_factor) = HashCommitment::create_commitment(&message);
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;
}
if blind_factor.bit_length() == hex_len {
// 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 distribuition is according to what is expected. ideally = 0.5
// 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]
fn test_bit_length_create_commitment_with_user_defined_randomness() {
let message = BigInt::sample(SECURITY_BITS);
let (_commitment, blind_factor) = HashCommitment::create_commitment(&message);
let commitment2 =
HashCommitment::create_commitment_with_user_defined_randomness(&message, &blind_factor);
assert!(commitment2.to_hex().len() / 2 <= SECURITY_BITS / 8);
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]
fn test_random_num_generation_create_commitment_with_user_defined_randomness() {
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::create_commitment(&message);
let commitment2 =
HashCommitment::create_commitment_with_user_defined_randomness(&message, &blind_factor);
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]
fn test_hashing_create_commitment_with_user_defined_randomness() {
let mut digest = Sha3_256::new();
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::create_commitment_with_user_defined_randomness(
let commitment = HashCommitment::<H>::create_commitment_with_user_defined_randomness(
&message,
&BigInt::zero(),
);
Expand Down
53 changes: 20 additions & 33 deletions src/cryptographic_primitives/hashing/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ where

#[cfg(test)]
mod test {
use digest::generic_array::ArrayLength;
use digest::{BlockInput, FixedOutput, Reset, Update};
use hmac::Hmac;
use sha2::{Sha256, Sha512};

use super::*;
Expand Down Expand Up @@ -268,73 +271,57 @@ mod test {
);
}

crate::test_for_all_curves!(create_sha512_from_ge_test);
fn create_sha256_from_ge_test<E: Curve>() {
crate::test_for_all_curves_and_hashes!(create_hash_from_ge_test);
fn create_hash_from_ge_test<E: Curve, H: Digest + Clone>() {
let generator = Point::<E>::generator();
let base_point2 = Point::<E>::base_point2();
let result1 = Sha256::new()
let result1 = H::new()
.chain_point(&generator)
.chain_point(base_point2)
.result_scalar::<E>();
assert!(result1.to_bigint().bit_length() > 240);
let result2 = Sha256::new()
let result2 = H::new()
.chain_point(base_point2)
.chain_point(&generator)
.result_scalar::<E>();
assert_ne!(result1, result2);
let result3 = Sha256::new()
let result3 = H::new()
.chain_point(base_point2)
.chain_point(&generator)
.result_scalar::<E>();
assert_eq!(result2, result3);
}

crate::test_for_all_curves!(create_sha256_from_ge_test);
fn create_sha512_from_ge_test<E: Curve>() {
let generator = Point::<E>::generator();
let base_point2 = Point::<E>::base_point2();
let result1 = Sha512::new()
.chain_point(&generator)
.chain_point(base_point2)
.result_scalar::<E>();
assert!(result1.to_bigint().bit_length() > 240);
let result2 = Sha512::new()
.chain_point(base_point2)
.chain_point(&generator)
.result_scalar::<E>();
assert_ne!(result1, result2);
let result3 = Sha512::new()
.chain_point(base_point2)
.chain_point(&generator)
.result_scalar::<E>();
assert_eq!(result2, result3);
}

#[test]
fn create_hmac_test() {
crate::test_for_all_hashes!(create_hmac_test);
fn create_hmac_test<H>()
where
H: Update + BlockInput + FixedOutput + Reset + Default + Clone,
H::BlockSize: ArrayLength<u8>,
H::OutputSize: ArrayLength<u8>,
{
let key = BigInt::sample(512);
let result1 = Hmac::<Sha512>::new_bigint(&key)
let result1 = Hmac::<H>::new_bigint(&key)
.chain_bigint(&BigInt::from(10))
.result_bigint();
assert!(Hmac::<Sha512>::new_bigint(&key)
assert!(Hmac::<H>::new_bigint(&key)
.chain_bigint(&BigInt::from(10))
.verify_bigint(&result1)
.is_ok());

let key2 = BigInt::sample(512);
// same data , different key
let result2 = Hmac::<Sha512>::new_bigint(&key2)
let result2 = Hmac::<H>::new_bigint(&key2)
.chain_bigint(&BigInt::from(10))
.result_bigint();
assert_ne!(result1, result2);
// same key , different data
let result3 = Hmac::<Sha512>::new_bigint(&key)
let result3 = Hmac::<H>::new_bigint(&key)
.chain_bigint(&BigInt::from(10))
.chain_bigint(&BigInt::from(11))
.result_bigint();
assert_ne!(result1, result3);
// same key, same data
let result4 = Hmac::<Sha512>::new_bigint(&key)
let result4 = Hmac::<H>::new_bigint(&key)
.chain_bigint(&BigInt::from(10))
.result_bigint();
assert_eq!(result1, result4)
Expand Down
2 changes: 1 addition & 1 deletion src/cryptographic_primitives/hashing/merkle_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct MT256<'a> {
*/
pub struct MT256<E: Curve> {
tree: MerkleTree<[u8; 32]>,
_ph: PhantomData<E>,
_ph: PhantomData<fn(E)>,
}

//impl <'a> MT256<'a>{
Expand Down
7 changes: 1 addition & 6 deletions src/cryptographic_primitives/hashing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,8 @@
(https://github.com/KZen-networks/curv)
License MIT: https://github.com/KZen-networks/curv/blob/master/LICENSE
*/
pub mod blake2b512;
pub mod hash_sha256;
pub mod hash_sha512;
pub mod hmac_sha512;
mod ext;
pub mod merkle_tree;
pub mod traits;

mod ext;
pub use digest::Digest;
pub use ext::*;
23 changes: 0 additions & 23 deletions src/cryptographic_primitives/hashing/traits.rs

This file was deleted.

Loading

0 comments on commit 1569c91

Please sign in to comment.