diff --git a/CHANGELOG.md b/CHANGELOG.md index 9531e9d5..775d3c04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## v0.8.0-rc4 +* Implement Try and Increment when converting hash to scalar [#128] \ + Improves performance and security of conversion 🔥 +* Get rid of deprecated `rust-crypto` dependency [#137] + * Changed the crate providing merkle trees support: `merkle-sha3 v0.1` → `merkle-cbt v0.3` + * Merkle trees API has been slightly changed + * Merkle trees are generic over hash function (it used to work with keccak256 only) + * Merkle proofs built by previous versions of `curv` are incompatible with latest `curv` + +[#128]: https://github.com/ZenGo-X/curv/pull/128 +[#137]: https://github.com/ZenGo-X/curv/pull/137 + ## v0.8.0-rc3 * Fix point subtraction. Bug was introduced in `v0.8.0-rc1`. [#127] * Add `Polynomial::lagrange_basis` function [#130] diff --git a/Cargo.toml b/Cargo.toml index a06ee87b..e1f70abf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,14 +24,12 @@ ff-zeroize = "0.6.3" hex = { version = "0.4", features = ["serde"] } hmac = "0.11" thiserror = "1" -merkle-sha3 = "^0.1" lazy_static = "1.4" num-traits = "0.2" num-integer = "0.1" pairing-plus = "0.19" rand = "0.7" rand_legacy = { package = "rand", version = "0.6" } -rust-crypto = "^0.2" serde = { version = "1.0", features = ["derive"] } serde_bytes = "0.11" serde_derive = "1.0" @@ -39,6 +37,7 @@ sha2 = "0.9" sha3 = "0.9" old_sha2 = { package = "sha2", version = "0.8" } zeroize = "1" +merkle-cbt = "0.3" rust-gmp-kzen = { version = "0.5", features = ["serde_support"], optional = true } num-bigint = { version = "0.4", features = ["serde"], optional = true } @@ -62,4 +61,4 @@ blake2 = "0.9" default = ["rust-gmp-kzen"] [package.metadata.docs.rs] -rustdoc-args = [ "--html-in-header", "katex-header.html" ] +rustdoc-args = [ "--html-in-header", "katex-header.html", "--cfg", "docsrs" ] diff --git a/README.md b/README.md index f0b36055..f10063a6 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Latest version](https://img.shields.io/crates/v/curv-kzen.svg)](https://crates.io/crates/curv-kzen) [![Docs](https://docs.rs/curv-kzen/badge.svg)](https://docs.rs/curv-kzen) [![License](https://img.shields.io/crates/l/curv-kzen)](LICENSE) +[![dependency status](https://deps.rs/repo/github/ZenGo-X/curv/status.svg)](https://deps.rs/repo/github/ZenGo-X/curv) Curv ===================================== diff --git a/src/cryptographic_primitives/hashing/merkle_tree.rs b/src/cryptographic_primitives/hashing/merkle_tree.rs index 36f2d6c7..a83cced5 100644 --- a/src/cryptographic_primitives/hashing/merkle_tree.rs +++ b/src/cryptographic_primitives/hashing/merkle_tree.rs @@ -5,66 +5,90 @@ License MIT: https://github.com/KZen-networks/curv/blob/master/LICENSE */ -// enabled via feature since it uses rust-crypto. - use std::marker::PhantomData; -use crypto::sha3::Sha3; -use merkle::{MerkleTree, Proof}; +use digest::{Digest, Output}; +use merkle_cbt::merkle_tree::{Merge, MerkleProof, MerkleTree, CBMT}; +use serde::{Deserialize, Serialize}; +use crate::cryptographic_primitives::hashing::DigestExt; +use crate::cryptographic_primitives::proofs::ProofError; use crate::elliptic::curves::{Curve, Point}; -/* -pub struct MT256<'a> { - tree: MerkleTree, - root: & 'a Vec, -} -*/ -pub struct MT256 { - tree: MerkleTree<[u8; 32]>, - _ph: PhantomData, + +pub struct MT256 { + tree: MerkleTree, MergeDigest>, + leaves: Vec>, } -//impl <'a> MT256<'a>{ -impl MT256 { - pub fn create_tree(vec: &[Point]) -> MT256 { - let digest = Sha3::keccak256(); - let vec_bytes = (0..vec.len()) - .map(|i| { - let mut array = [0u8; 32]; - let bytes = vec[i].to_bytes(false); - array.copy_from_slice(&bytes[0..32]); - array - }) - .collect::>(); - let tree = MerkleTree::from_vec::<[u8; 32]>(digest, vec_bytes); +impl MT256 { + pub fn create_tree(leaves: Vec>) -> Self { + let hashes = leaves + .iter() + .map(|leaf| H::new().chain_point(leaf).finalize()) + .collect::>(); MT256 { - tree, - _ph: PhantomData, + tree: CBMT::, MergeDigest>::build_merkle_tree(&hashes), + leaves, } } - pub fn gen_proof_for_ge(&self, value: &Point) -> Proof<[u8; 32]> { - let mut array = [0u8; 32]; - let pk_slice = value.to_bytes(false); - array.copy_from_slice(&pk_slice[0..32]); - MerkleTree::gen_proof::<[u8; 32]>(&self.tree, array).expect("not found in tree") + pub fn build_proof(&self, point: Point) -> Option> { + let index = (0u32..) + .zip(&self.leaves) + .find(|(_, leaf)| **leaf == point) + .map(|(i, _)| i)?; + let proof = self.tree.build_proof(&[index])?; + Some(Proof { + index: proof.indices()[0], + lemmas: proof.lemmas().to_vec(), + point, + }) } - pub fn get_root(&self) -> &Vec { - MerkleTree::root_hash(&self.tree) + pub fn get_root(&self) -> Output { + self.tree.root() } +} - #[allow(clippy::result_unit_err)] - pub fn validate_proof(proof: &Proof<[u8; 32]>, root: &[u8]) -> Result<(), ()> { - if Proof::validate::<[u8; 32]>(proof, root) { +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(bound( + serialize = "Output: Serialize", + deserialize = "Output: Deserialize<'de>" +))] +pub struct Proof { + pub index: u32, + pub lemmas: Vec>, + pub point: Point, +} + +impl Proof { + pub fn verify(&self, root: &Output) -> Result<(), ProofError> { + let leaf = H::new().chain_point(&self.point).finalize(); + let valid = + MerkleProof::, MergeDigest>::new(vec![self.index], self.lemmas.clone()) + .verify(root, &[leaf]); + if valid { Ok(()) } else { - Err(()) + Err(ProofError) } } } +struct MergeDigest(PhantomData); + +impl Merge for MergeDigest +where + D: Digest, +{ + type Item = Output; + + fn merge(left: &Self::Item, right: &Self::Item) -> Self::Item { + D::new().chain(left).chain(right).finalize() + } +} + #[cfg(test)] mod tests { use super::MT256; @@ -80,11 +104,10 @@ mod tests { let ge3: Point = &ge1 + &ge2; let ge4: Point = &ge1 + &ge3; let ge_vec = vec![ge1.clone(), ge2, ge3, ge4]; - let mt256 = MT256::create_tree(&ge_vec); - let proof1 = mt256.gen_proof_for_ge(&ge1); + let mt256 = MT256::<_, sha3::Keccak256>::create_tree(ge_vec); + let proof1 = mt256.build_proof(ge1).unwrap(); let root = mt256.get_root(); - let valid_proof = MT256::::validate_proof(&proof1, root).is_ok(); - assert!(valid_proof); + proof1.verify(&root).expect("proof is invalid"); } test_for_all_curves!(test_mt_functionality_three_leaves); @@ -95,9 +118,9 @@ mod tests { let ge3: Point = &ge1 + &ge2; let ge_vec = vec![ge1.clone(), ge2, ge3]; - let mt256 = MT256::create_tree(&ge_vec); - let proof1 = mt256.gen_proof_for_ge(&ge1); + let mt256 = MT256::<_, sha3::Keccak256>::create_tree(ge_vec); + let proof1 = mt256.build_proof(ge1).unwrap(); let root = mt256.get_root(); - assert!(MT256::::validate_proof(&proof1, root).is_ok()); + proof1.verify(&root).expect("proof is invalid"); } }