From f1d8a6aaf26be8e93a2f83f0a09e51e66514bb62 Mon Sep 17 00:00:00 2001 From: Denis Varlakov Date: Sat, 12 Dec 2020 16:04:06 +0700 Subject: [PATCH 1/2] SecretShare updated --- Cargo.toml | 10 +++++++- src/lib.rs | 4 ++-- src/wallet.rs | 64 +++++++++++++++++++++++++++------------------------ 3 files changed, 45 insertions(+), 33 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e8a5380..a6ae6e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ authors = [ crate-type = ["lib"] [dependencies] -curv = { git = "https://github.com/KZen-networks/curv", tag = "v0.3.4"} +curv = { git = "https://github.com/survived/curv.git", branch = "expose-testing-macro"} bulletproof = {git = "https://github.com/KZen-networks/bulletproofs", tag = "v1.1.2"} serde_derive = "1.0" serde = "1.0" @@ -19,6 +19,14 @@ rayon = "1.0.3" [dev-dependencies] criterion = "0.2" +[dev-dependencies.curv] +git = "https://github.com/survived/curv.git" +branch = "expose-testing-macro" +features = ["testing-utils"] + +[patch."https://github.com/survived/curv.git"] +curv = { path = "../curv" } + [[bench]] name = "v_backup" path = "benches/v_backup.rs" diff --git a/src/lib.rs b/src/lib.rs index 08c45f7..1976dcb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,8 +14,8 @@ version 3 of the License, or (at your option) any later version. @license GPL-3.0+ */ -pub mod grad_release; -pub mod juggling; +// pub mod grad_release; +// pub mod juggling; pub mod wallet; extern crate bulletproof; extern crate curv; diff --git a/src/wallet.rs b/src/wallet.rs index f00fa65..0a2fbd4 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -15,56 +15,60 @@ version 3 of the License, or (at your option) any later version. @license GPL-3.0+ */ -use curv::arithmetic::traits::{Converter, Modulo}; +use curv::arithmetic::traits::Converter; use curv::cryptographic_primitives::hashing::hash_sha256::HSha256; use curv::cryptographic_primitives::hashing::traits::*; -use curv::elliptic::curves::secp256_k1::FE; -use curv::elliptic::curves::secp256_k1::GE; use curv::elliptic::curves::traits::*; use curv::BigInt; -pub struct SecretShare { - pub secret: FE, - pub pubkey: GE, + +pub struct SecretShare { + pub secret: P::Scalar, + pub pubkey: P, } -impl SecretShare { - pub fn generate() -> SecretShare { - let base_point: GE = ECPoint::generator(); - let secret: FE = ECScalar::new_random(); +impl

SecretShare

+where + P: ECPoint, + P::Scalar: Clone, +{ + pub fn generate() -> SecretShare

{ + let base_point: P = ECPoint::generator(); + let secret: P::Scalar = ECScalar::new_random(); - let pubkey = base_point * &secret; + let pubkey = base_point * secret.clone(); return SecretShare { secret, pubkey }; } //based on VRF construction from ellitpic curve: https://eprint.iacr.org/2017/099.pdf //TODO: consider to output in str format pub fn generate_randomness(&self, label: &BigInt) -> BigInt { - let h = generate_random_point(&Converter::to_vec(label)); - let gamma = h * &self.secret; - let beta = HSha256::create_hash_from_ge(&[&gamma]); + let h: P = derive_point(&Converter::to_vec(label)); + let gamma = h * self.secret.clone(); + let beta = HSha256::create_hash_from_ge::

(&[&gamma]); beta.to_big_int() } } -pub fn generate_random_point(bytes: &[u8]) -> GE { - let result: Result = ECPoint::from_bytes(&bytes); - if result.is_ok() { - return result.unwrap(); - } else { - let two = BigInt::from(2); - let bn = BigInt::from(bytes); - let bn_times_two = BigInt::mod_mul(&bn, &two, &FE::q()); - let bytes = BigInt::to_vec(&bn_times_two); - return generate_random_point(&bytes); - } +// TODO: Copy-paste from https://github.com/survived/bulletproofs/blob/1e856b17aefd37e2085144097df69c26832bb2b6/src/proofs/utils.rs#L6 +pub fn derive_point(source: &[u8]) -> P { + let bn = BigInt::from(source); + let scalar = ::from(&bn); + P::generator() * scalar } #[cfg(test)] mod tests { - use curv::BigInt; - use wallet::SecretShare; - #[test] - fn test_randomness() { - let x = SecretShare::generate(); + use curv::elliptic::curves::traits::*; + use curv::{test_for_all_curves, BigInt}; + + use super::SecretShare; + + test_for_all_curves!(test_randomness); + fn test_randomness

() + where + P: ECPoint, + P::Scalar: Clone, + { + let x = SecretShare::

::generate(); let bitcoin_label = String::from("Bitcoin1").into_bytes(); let ethereum_label = String::from("Ethereum1").into_bytes(); let label_btc = BigInt::from(&bitcoin_label[..]); From 2cb7a53071f6ecfadf5e13460d21fad735c948d4 Mon Sep 17 00:00:00 2001 From: Denis Varlakov Date: Sun, 13 Dec 2020 22:19:39 +0700 Subject: [PATCH 2/2] Introduce generic curve in all the algorithms --- Cargo.toml | 6 +- src/grad_release/mod.rs | 116 +++++++++++++---------- src/juggling/proof_system.rs | 177 +++++++++++++++++++---------------- src/juggling/segmentation.rs | 117 +++++++++++++---------- src/lib.rs | 5 +- 5 files changed, 239 insertions(+), 182 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a6ae6e2..94c4715 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,10 +11,11 @@ crate-type = ["lib"] [dependencies] curv = { git = "https://github.com/survived/curv.git", branch = "expose-testing-macro"} -bulletproof = {git = "https://github.com/KZen-networks/bulletproofs", tag = "v1.1.2"} +bulletproof = {git = "https://github.com/survived/bulletproofs", branch = "generic-curv"} serde_derive = "1.0" serde = "1.0" rayon = "1.0.3" +zeroize = "0.10" [dev-dependencies] criterion = "0.2" @@ -24,9 +25,6 @@ git = "https://github.com/survived/curv.git" branch = "expose-testing-macro" features = ["testing-utils"] -[patch."https://github.com/survived/curv.git"] -curv = { path = "../curv" } - [[bench]] name = "v_backup" path = "benches/v_backup.rs" diff --git a/src/grad_release/mod.rs b/src/grad_release/mod.rs index 64912f1..961a765 100644 --- a/src/grad_release/mod.rs +++ b/src/grad_release/mod.rs @@ -9,44 +9,56 @@ use juggling::proof_system::Helgamalsegmented; use juggling::proof_system::Proof; use juggling::proof_system::Witness; use juggling::segmentation::Msegmentation; +use serde::{Deserialize, Serialize}; +use zeroize::Zeroize; use Errors; use Errors::ErrorSegmentNum; -type GE = curv::elliptic::curves::secp256_k1::GE; -type FE = curv::elliptic::curves::secp256_k1::FE; const SECRET_BIT_LENGTH: usize = 256; #[derive(Serialize, Deserialize)] -pub struct VEShare { - pub secret: FE, - pub segments: Witness, - pub encryptions: Helgamalsegmented, - pub proof: Proof, +pub struct VEShare { + pub secret: P::Scalar, + pub segments: Witness, + pub encryptions: Helgamalsegmented

, + pub proof: Proof

, } #[derive(Serialize, Deserialize)] -pub struct FirstMessage { +#[serde(bound(serialize = "P: Serialize, P::Scalar: Serialize"))] +#[serde(bound(deserialize = "P: Deserialize<'de>, P::Scalar: Deserialize<'de>"))] +pub struct FirstMessage { pub segment_size: usize, - pub D_vec: Vec, - pub range_proof: RangeProof, - pub Q: GE, - pub E: GE, - pub dlog_proof: HomoELGamalDlogProof, + pub D_vec: Vec

, + pub range_proof: RangeProof

, + pub Q: P, + pub E: P, + pub dlog_proof: HomoELGamalDlogProof

, } #[derive(Serialize, Deserialize)] -pub struct SegmentProof { +#[serde(bound(serialize = "P: Serialize, P::Scalar: Serialize"))] +#[serde(bound(deserialize = "P: Deserialize<'de>, P::Scalar: Deserialize<'de>"))] +pub struct SegmentProof { pub k: usize, - pub E_k: GE, - pub correct_enc_proof: HomoELGamalProof, + pub E_k: P, + pub correct_enc_proof: HomoELGamalProof

, } -impl VEShare { - pub fn create(secret: &FE, encryption_key: &GE, segment_size: &usize) -> (FirstMessage, Self) { - let G: GE = GE::generator(); +impl

VEShare

+where + P: ECPoint + Clone + Zeroize + Sync + Send, + P::Scalar: Clone + PartialEq + Zeroize + Sync + Send, +{ + pub fn create( + secret: &P::Scalar, + encryption_key: &P, + segment_size: &usize, + ) -> (FirstMessage

, Self) { + let G: P = ECPoint::generator(); let num_segments = SECRET_BIT_LENGTH / *segment_size; //TODO: asserty divisible or add segment - let (segments, encryptions) = Msegmentation::to_encrypted_segments( + let (segments, encryptions) = Msegmentation::to_encrypted_segments::

( secret, &segment_size, num_segments, @@ -56,11 +68,11 @@ impl VEShare { let proof = Proof::prove(&segments, &encryptions, &G, &encryption_key, &segment_size); // first message: - let Q = GE::generator() * secret; - let D_vec: Vec = (0..num_segments) + let Q = P::generator() * secret.clone(); + let D_vec: Vec

= (0..num_segments) .map(|i| encryptions.DE[i].D.clone()) .collect(); - let E_vec: Vec = (0..num_segments) + let E_vec: Vec

= (0..num_segments) .map(|i| encryptions.DE[i].E.clone()) .collect(); let E = Msegmentation::assemble_ge(&E_vec, segment_size); @@ -77,7 +89,7 @@ impl VEShare { dlog_proof: proof.elgamal_enc_dlog.clone(), }, VEShare { - secret: *secret, + secret: secret.clone(), segments, encryptions, proof, @@ -85,48 +97,48 @@ impl VEShare { ) } - pub fn segment_k_proof(&self, segment_k: &usize) -> SegmentProof { + pub fn segment_k_proof(&self, segment_k: &usize) -> SegmentProof

{ SegmentProof { k: segment_k.clone(), - E_k: self.encryptions.DE[*segment_k].E, + E_k: self.encryptions.DE[*segment_k].E.clone(), correct_enc_proof: self.proof.elgamal_enc[*segment_k].clone(), } } - pub fn start_verify(first_message: &FirstMessage, encryption_key: &GE) -> Result<(), Errors> { + pub fn start_verify(first_message: &FirstMessage

, encryption_key: &P) -> Result<(), Errors> { Proof::verify_first_message(first_message, encryption_key) } pub fn verify_segment( - first_message: &FirstMessage, - segment: &SegmentProof, - encryption_key: &GE, + first_message: &FirstMessage

, + segment: &SegmentProof

, + encryption_key: &P, ) -> Result<(), Errors> { Proof::verify_segment(first_message, segment, encryption_key) } pub fn extract_secret( - first_message: &FirstMessage, - segment_proof_vec: &[SegmentProof], - decryption_key: &FE, - ) -> Result { + first_message: &FirstMessage

, + segment_proof_vec: &[SegmentProof

], + decryption_key: &P::Scalar, + ) -> Result { let len = segment_proof_vec.len(); if len != first_message.D_vec.len() { return Err(ErrorSegmentNum); } let elgamal_enc_vec = (0..len) .map(|i| Helgamal { - D: first_message.D_vec[i], - E: segment_proof_vec[i].E_k, + D: first_message.D_vec[i].clone(), + E: segment_proof_vec[i].E_k.clone(), }) - .collect::>(); + .collect::>>(); let encryptions = Helgamalsegmented { DE: elgamal_enc_vec, }; let secret_decrypted = Msegmentation::decrypt( &encryptions, - &GE::generator(), + &P::generator(), &decryption_key, &first_message.segment_size, ); @@ -136,34 +148,38 @@ impl VEShare { #[cfg(test)] mod tests { - type GE = curv::elliptic::curves::secp256_k1::GE; - use curv::elliptic::curves::traits::*; + use curv::test_for_all_curves; use grad_release::VEShare; use grad_release::SECRET_BIT_LENGTH; + use zeroize::Zeroize; // simple usage example. two parties wish to exchange secrets in ~fair manner - #[test] - fn test_secret_exchange() { + test_for_all_curves!(test_secret_exchange); + fn test_secret_exchange() + where + P: ECPoint + Clone + Zeroize + Sync + Send, + P::Scalar: Clone + PartialEq + Zeroize + Sync + Send + std::fmt::Debug, + { let segment_size = 8; // secret generation - let secret_p1 = ECScalar::new_random(); - let secret_p2 = ECScalar::new_random(); + let secret_p1: P::Scalar = ECScalar::new_random(); + let secret_p2: P::Scalar = ECScalar::new_random(); // enc/dec key pairs generation - let p1_dec_key = ECScalar::new_random(); - let p1_enc_key = GE::generator() * p1_dec_key; - let p2_dec_key = ECScalar::new_random(); - let p2_enc_key = GE::generator() * p2_dec_key; + let p1_dec_key: P::Scalar = ECScalar::new_random(); + let p1_enc_key: P = P::generator() * p1_dec_key.clone(); + let p2_dec_key: P::Scalar = ECScalar::new_random(); + let p2_enc_key: P = P::generator() * p2_dec_key.clone(); // p1 sends first message to p2 let (p1_first_message, p1_ve_share) = - VEShare::create(&secret_p1, &p2_enc_key, &segment_size); + VEShare::

::create(&secret_p1, &p2_enc_key, &segment_size); // p2 verify first message assert!(VEShare::start_verify(&p1_first_message, &p2_enc_key).is_ok()); // p2 sends first message to p1 let (p2_first_message, p2_ve_share) = - VEShare::create(&secret_p2, &p1_enc_key, &segment_size); + VEShare::

::create(&secret_p2, &p1_enc_key, &segment_size); // p1 verify first message assert!(VEShare::start_verify(&p2_first_message, &p1_enc_key).is_ok()); diff --git a/src/juggling/proof_system.rs b/src/juggling/proof_system.rs index 134bcee..a1e0023 100644 --- a/src/juggling/proof_system.rs +++ b/src/juggling/proof_system.rs @@ -15,54 +15,61 @@ version 3 of the License, or (at your option) any later version. @license GPL-3.0+ */ use curv::BigInt; -use curv::elliptic::curves::secp256_k1::GE; -use curv::elliptic::curves::secp256_k1::FE; use curv::cryptographic_primitives::proofs::sigma_correct_homomorphic_elgamal_encryption_of_dlog::{HomoELGamalDlogProof,HomoElGamalDlogWitness,HomoElGamalDlogStatement}; use curv::cryptographic_primitives::proofs::sigma_correct_homomorphic_elgamal_enc::{HomoELGamalProof,HomoElGamalWitness,HomoElGamalStatement}; use curv::cryptographic_primitives::hashing::hash_sha512::HSha512; use curv::cryptographic_primitives::hashing::traits::*; use curv::arithmetic::traits::Converter; -use bulletproof::proofs::range_proof::{RangeProof,generate_random_point}; +use bulletproof::proofs::range_proof::{RangeProof}; +use bulletproof::proofs::utils::derive_point; use juggling::segmentation::Msegmentation; use Errors::{self, ErrorProving}; use grad_release::FirstMessage; use ::Errors::ErrorFirstMessage; use grad_release::SegmentProof; use ::Errors::ErrorSegmentProof; -use curv::elliptic::curves::traits::ECPoint; +use curv::elliptic::curves::traits::*; +use serde::{Serialize, Deserialize}; +use zeroize::Zeroize; #[derive(Serialize, Deserialize)] -pub struct Helgamal { - pub D: GE, - pub E: GE, +pub struct Helgamal { + pub D: P, + pub E: P, } #[derive(Serialize, Deserialize)] -pub struct Helgamalsegmented { - pub DE: Vec, +pub struct Helgamalsegmented { + pub DE: Vec>, } #[derive(Serialize, Deserialize)] -pub struct Witness { - pub x_vec: Vec, - pub r_vec: Vec, +pub struct Witness { + pub x_vec: Vec, + pub r_vec: Vec, } #[derive(Serialize, Deserialize)] -pub struct Proof { - pub bulletproof: RangeProof, - pub elgamal_enc: Vec>, - pub elgamal_enc_dlog: HomoELGamalDlogProof, +#[serde(bound(serialize = "P: Serialize, P::Scalar: Serialize"))] +#[serde(bound(deserialize = "P: Deserialize<'de>, P::Scalar: Deserialize<'de>"))] +pub struct Proof { + pub bulletproof: RangeProof

, + pub elgamal_enc: Vec>, + pub elgamal_enc_dlog: HomoELGamalDlogProof

, } -impl Proof { +impl

Proof

+where + P: ECPoint + Clone + Zeroize, + P::Scalar: Clone + PartialEq + Zeroize, +{ pub fn prove( - w: &Witness, - c: &Helgamalsegmented, - G: &curv::elliptic::curves::secp256_k1::GE, - Y: &curv::elliptic::curves::secp256_k1::GE, + w: &Witness, + c: &Helgamalsegmented

, + G: &P, + Y: &P, segment_size: &usize, - ) -> Proof { + ) -> Proof

{ // bulletproofs: let num_segments = w.x_vec.len(); // bit range @@ -78,7 +85,7 @@ impl Proof { .map(|i| { let kzen_label_i = BigInt::from(i as u32) + &kzen_label; let hash_i = HSha512::create_hash(&[&kzen_label_i]); - generate_random_point(&Converter::to_vec(&hash_i)) + derive_point(&Converter::to_vec(&hash_i)) }) .collect::>(); @@ -87,7 +94,7 @@ impl Proof { .map(|i| { let kzen_label_j = BigInt::from(n as u32) + BigInt::from(i as u32) + &kzen_label; let hash_j = HSha512::create_hash(&[&kzen_label_j]); - generate_random_point(&Converter::to_vec(&hash_j)) + derive_point(&Converter::to_vec(&hash_j)) }) .collect::>(); @@ -109,18 +116,18 @@ impl Proof { D: c.DE[i].D.clone(), E: c.DE[i].E.clone(), }; - HomoELGamalProof::prove(&w, &delta) + HomoELGamalProof::

::prove(&w, &delta) }) - .collect::>>(); + .collect::>>(); // proof of correct ElGamal DLog - let D_vec: Vec = (0..num_segments).map(|i| c.DE[i].D.clone()).collect(); - let E_vec: Vec = (0..num_segments).map(|i| c.DE[i].E.clone()).collect(); + let D_vec: Vec

= (0..num_segments).map(|i| c.DE[i].D.clone()).collect(); + let E_vec: Vec

= (0..num_segments).map(|i| c.DE[i].E.clone()).collect(); let sum_D = Msegmentation::assemble_ge(&D_vec, segment_size); let sum_E = Msegmentation::assemble_ge(&E_vec, segment_size); let sum_r = Msegmentation::assemble_fe(&w.r_vec, segment_size); let sum_x = Msegmentation::assemble_fe(&w.x_vec, segment_size); - let Q = G.clone() * &sum_x; + let Q = G.clone() * sum_x.clone(); let delta = HomoElGamalDlogStatement { G: G.clone(), Y: Y.clone(), @@ -140,10 +147,10 @@ impl Proof { pub fn verify( &self, - c: &Helgamalsegmented, - G: &GE, - Y: &GE, - Q: &GE, + c: &Helgamalsegmented

, + G: &P, + Y: &P, + Q: &P, segment_size: &usize, ) -> Result<(), Errors> { // bulletproofs: @@ -161,20 +168,20 @@ impl Proof { .map(|i| { let kzen_label_i = BigInt::from(i as u32) + &kzen_label; let hash_i = HSha512::create_hash(&[&kzen_label_i]); - generate_random_point(&Converter::to_vec(&hash_i)) + derive_point(&Converter::to_vec(&hash_i)) }) - .collect::>(); + .collect::>(); // can run in parallel to g_vec: let h_vec = (0..nm) .map(|i| { let kzen_label_j = BigInt::from(n as u32) + BigInt::from(i as u32) + &kzen_label; let hash_j = HSha512::create_hash(&[&kzen_label_j]); - generate_random_point(&Converter::to_vec(&hash_j)) + derive_point(&Converter::to_vec(&hash_j)) }) - .collect::>(); + .collect::>(); - let D_vec: Vec = (0..num_segments).map(|i| c.DE[i].D.clone()).collect(); + let D_vec: Vec

= (0..num_segments).map(|i| c.DE[i].D.clone()).collect(); let bp_ver = self .bulletproof .verify(&g_vec, &h_vec, G, Y, &D_vec, segment_size.clone()) @@ -193,7 +200,7 @@ impl Proof { }) .collect::>(); - let E_vec: Vec = (0..num_segments).map(|i| c.DE[i].E.clone()).collect(); + let E_vec: Vec

= (0..num_segments).map(|i| c.DE[i].E.clone()).collect(); let sum_D = Msegmentation::assemble_ge(&D_vec, segment_size); let sum_E = Msegmentation::assemble_ge(&E_vec, segment_size); @@ -214,8 +221,8 @@ impl Proof { } pub fn verify_first_message( - first_message: &FirstMessage, - encryption_key: &GE, + first_message: &FirstMessage

, + encryption_key: &P, ) -> Result<(), Errors> { // bulletproofs: let num_segments = first_message.D_vec.len(); @@ -232,27 +239,29 @@ impl Proof { .map(|i| { let kzen_label_i = BigInt::from(i as u32) + &kzen_label; let hash_i = HSha512::create_hash(&[&kzen_label_i]); - generate_random_point(&Converter::to_vec(&hash_i)) + derive_point(&Converter::to_vec(&hash_i)) }) - .collect::>(); + .collect::>(); - let Y = *encryption_key; + let Y = encryption_key.clone(); // can run in parallel to g_vec: let h_vec = (0..nm) .map(|i| { let kzen_label_j = BigInt::from(n as u32) + BigInt::from(i as u32) + &kzen_label; let hash_j = HSha512::create_hash(&[&kzen_label_j]); - generate_random_point(&Converter::to_vec(&hash_j)) + derive_point(&Converter::to_vec(&hash_j)) }) - .collect::>(); + .collect::>(); - let D_vec: Vec = (0..num_segments).map(|i| first_message.D_vec[i]).collect(); + let D_vec: Vec

= (0..num_segments) + .map(|i| first_message.D_vec[i].clone()) + .collect(); let bp_ver = first_message .range_proof .verify( &g_vec, &h_vec, - &GE::generator(), + &P::generator(), &Y, &first_message.D_vec, first_message.segment_size.clone(), @@ -260,12 +269,12 @@ impl Proof { .is_ok(); let sum_D = Msegmentation::assemble_ge(&D_vec, &first_message.segment_size); - let sum_E = first_message.E; + let sum_E = first_message.E.clone(); let delta = HomoElGamalDlogStatement { - G: GE::generator(), + G: P::generator(), Y, - Q: first_message.Q, + Q: first_message.Q.clone(), D: sum_D, E: sum_E, }; @@ -279,16 +288,16 @@ impl Proof { } pub fn verify_segment( - first_message: &FirstMessage, - segment: &SegmentProof, - encryption_key: &GE, + first_message: &FirstMessage

, + segment: &SegmentProof

, + encryption_key: &P, ) -> Result<(), Errors> { let delta = HomoElGamalStatement { - G: GE::generator(), - H: GE::generator(), - Y: *encryption_key, - D: first_message.D_vec[segment.k], - E: segment.E_k, + G: P::generator(), + H: P::generator(), + Y: encryption_key.clone(), + D: first_message.D_vec[segment.k].clone(), + E: segment.E_k.clone(), }; let elgamal_proof = segment.correct_enc_proof.verify(&delta).is_ok(); @@ -303,21 +312,25 @@ impl Proof { #[cfg(test)] mod tests { - use curv::elliptic::curves::secp256_k1::FE; - use curv::elliptic::curves::secp256_k1::GE; use curv::elliptic::curves::traits::*; + use curv::test_for_all_curves; use juggling::proof_system::*; use juggling::segmentation::Msegmentation; use wallet::SecretShare; - - #[test] - fn test_varifiable_encryption() { + use zeroize::Zeroize; + + test_for_all_curves!(test_verifiable_encryption); + fn test_verifiable_encryption

() + where + P: ECPoint + Clone + Zeroize + Sync + Send, + P::Scalar: Clone + PartialEq + Zeroize + Sync + Send + std::fmt::Debug, + { let segment_size = 8; - let y: FE = ECScalar::new_random(); - let G: GE = ECPoint::generator(); - let Y = G.clone() * &y; - let x = SecretShare::generate(); - let Q = G.clone() * &x.secret; + let y: P::Scalar = ECScalar::new_random(); + let G: P = ECPoint::generator(); + let Y = G.clone() * y.clone(); + let x = SecretShare::

::generate(); + let Q = G.clone() * x.secret.clone(); let (segments, encryptions) = Msegmentation::to_encrypted_segments(&x.secret, &segment_size, 32, &Y, &G); let secret_new = Msegmentation::assemble_fe(&segments.x_vec, &segment_size); @@ -331,23 +344,29 @@ mod tests { assert!(result.is_ok()); } - #[test] - #[should_panic] - fn test_varifiable_encryption_bad_Q() { + test_for_all_curves!( + #[should_panic] + test_verifiable_encryption_bad_Q + ); + fn test_verifiable_encryption_bad_Q() + where + P: ECPoint + Clone + Zeroize + Sync + Send, + P::Scalar: Clone + PartialEq + Zeroize + Sync + Send + std::fmt::Debug, + { let segment_size = 8; - let y: FE = ECScalar::new_random(); - let G: GE = ECPoint::generator(); - let Y = G.clone() * &y; - let x = SecretShare::generate(); - let Q = G.clone() * &x.secret + G.clone(); + let y: P::Scalar = ECScalar::new_random(); + let G: P = ECPoint::generator(); + let Y = G.clone() * y.clone(); + let x = SecretShare::

::generate(); + let Q = G.clone() * x.secret.clone() + G.clone(); let (segments, encryptions) = - Msegmentation::to_encrypted_segments(&x.secret, &segment_size, 32, &Y, &G); + Msegmentation::to_encrypted_segments::

(&x.secret, &segment_size, 32, &Y, &G); let secret_new = Msegmentation::assemble_fe(&segments.x_vec, &segment_size); let secret_decrypted = Msegmentation::decrypt(&encryptions, &G, &y, &segment_size); assert_eq!(x.secret, secret_new); assert_eq!(x.secret, secret_decrypted.unwrap()); - let proof = Proof::prove(&segments, &encryptions, &G, &Y, &segment_size); + let proof = Proof::

::prove(&segments, &encryptions, &G, &Y, &segment_size); let result = proof.verify(&encryptions, &G, &Y, &Q, &segment_size); assert!(result.is_ok()); } diff --git a/src/juggling/segmentation.rs b/src/juggling/segmentation.rs index f343186..34001a1 100644 --- a/src/juggling/segmentation.rs +++ b/src/juggling/segmentation.rs @@ -15,8 +15,6 @@ version 3 of the License, or (at your option) any later version. @license GPL-3.0+ */ const SECRETBITS: usize = 256; -use curv::elliptic::curves::secp256_k1::FE; -use curv::elliptic::curves::secp256_k1::GE; use curv::elliptic::curves::traits::*; use curv::BigInt; use juggling::proof_system::{Helgamal, Helgamalsegmented, Witness}; @@ -27,7 +25,10 @@ use Errors::{self, ErrorDecrypting}; pub struct Msegmentation; impl Msegmentation { - pub fn get_segment_k(secret: &FE, segment_size: &usize, k: u8) -> FE { + pub fn get_segment_k(secret: &S, segment_size: &usize, k: u8) -> S + where + S: ECScalar, + { let ss_bn = secret.to_big_int(); let segment_size_u32 = segment_size.clone() as u32; let msb = segment_size_u32 * (k as u32 + 1); @@ -47,29 +48,36 @@ impl Msegmentation { } } //returns r_k,{D_k,E_k} - pub fn encrypt_segment_k( - secret: &FE, - random: &FE, + pub fn encrypt_segment_k

( + secret: &P::Scalar, + random: &P::Scalar, segment_size: &usize, k: u8, - pub_ke_y: &GE, - G: &GE, - ) -> Helgamal { + pub_ke_y: &P, + G: &P, + ) -> Helgamal

+ where + P: ECPoint + Clone, + P::Scalar: Clone + PartialEq, + { let segment_k = Msegmentation::get_segment_k(secret, segment_size, k); - let E_k = G * random; - let r_kY = pub_ke_y * random; + let E_k = G.clone() * random.clone(); + let r_kY = pub_ke_y.clone() * random.clone(); if segment_k == ECScalar::zero() { let D_k = r_kY; Helgamal { D: D_k, E: E_k } } else { - let x_kG = G * &segment_k; + let x_kG = G.clone() * segment_k.clone(); let D_k = r_kY + x_kG; Helgamal { D: D_k, E: E_k } } } // TODO: find a way using generics to combine the following two fn's - pub fn assemble_fe(segments: &Vec, segment_size: &usize) -> FE { + pub fn assemble_fe(segments: &Vec, segment_size: &usize) -> S + where + S: ECScalar + Clone + PartialEq, + { let two = BigInt::from(2); let mut segments_2n = segments.clone(); let seg1 = segments_2n.remove(0); @@ -77,20 +85,23 @@ impl Msegmentation { .iter() .zip(0..segments_2n.len()) .fold(seg1, |acc, x| { - if x.0.clone() == FE::zero() { + if x.0.clone() == S::zero() { acc } else { let two_to_the_n = two.pow(segment_size.clone() as u32); let two_to_the_n_shifted = two_to_the_n.shl(x.1 * segment_size); - let two_to_the_n_shifted_fe: FE = ECScalar::from(&two_to_the_n_shifted); - let shifted_segment = x.0.clone() * two_to_the_n_shifted_fe; + let two_to_the_n_shifted_fe: S = ECScalar::from(&two_to_the_n_shifted); + let shifted_segment: S = x.0.clone() * two_to_the_n_shifted_fe; acc + shifted_segment } }); return seg_sum; } - pub fn assemble_ge(segments: &Vec, segment_size: &usize) -> GE { + pub fn assemble_ge

(segments: &Vec

, segment_size: &usize) -> P + where + P: ECPoint + Clone, + { let two = BigInt::from(2); let mut segments_2n = segments.clone(); let seg1 = segments_2n.remove(0); @@ -100,24 +111,28 @@ impl Msegmentation { .fold(seg1, |acc, x| { let two_to_the_n = two.pow(segment_size.clone() as u32); let two_to_the_n_shifted = two_to_the_n.shl(x.1 * segment_size); - let two_to_the_n_shifted_fe: FE = ECScalar::from(&two_to_the_n_shifted); + let two_to_the_n_shifted_fe: P::Scalar = ECScalar::from(&two_to_the_n_shifted); let shifted_segment = x.0.clone() * two_to_the_n_shifted_fe; acc + shifted_segment }); return seg_sum; } - pub fn to_encrypted_segments( - secret: &FE, + pub fn to_encrypted_segments

( + secret: &P::Scalar, segment_size: &usize, num_of_segments: usize, - pub_ke_y: &GE, - G: &GE, - ) -> (Witness, Helgamalsegmented) { + pub_ke_y: &P, + G: &P, + ) -> (Witness, Helgamalsegmented

) + where + P: ECPoint + Clone + Sync + Send, + P::Scalar: Clone + PartialEq + Sync, + { assert_eq!(*segment_size * num_of_segments, SECRETBITS); let r_vec = (0..num_of_segments) .map(|_| ECScalar::new_random()) - .collect::>(); + .collect::>(); let segmented_enc = (0..num_of_segments) .into_par_iter() .map(|i| { @@ -131,31 +146,35 @@ impl Msegmentation { G, ) }) - .collect::>(); + .collect::>>(); let x_vec = (0..num_of_segments) .map(|i| Msegmentation::get_segment_k(secret, segment_size, i as u8)) - .collect::>(); + .collect::>(); let w = Witness { x_vec, r_vec }; let heg_segmented = Helgamalsegmented { DE: segmented_enc }; (w, heg_segmented) } //TODO: implement a more advance algorithm for dlog - pub fn decrypt_segment( - DE: &Helgamal, - G: &GE, - private_key: &FE, + pub fn decrypt_segment

( + DE: &Helgamal

, + G: &P, + private_key: &P::Scalar, limit: &u32, - table: &[GE], - ) -> Result { + table: &[P], + ) -> Result + where + P: ECPoint + Clone, + P::Scalar: Clone, + { let mut result = None; let limit_plus_one = limit.clone() + 1u32; - let out_of_limit_fe: FE = ECScalar::from(&BigInt::from(limit_plus_one)); - let out_of_limit_ge: GE = G.clone() * &out_of_limit_fe; - let yE = DE.E.clone() * private_key; + let out_of_limit_fe: P::Scalar = ECScalar::from(&BigInt::from(limit_plus_one)); + let out_of_limit_ge: P = G.clone() * out_of_limit_fe.clone(); + let yE = DE.E.clone() * private_key.clone(); // handling 0 segment - let mut D_minus_yE: GE = out_of_limit_ge; + let mut D_minus_yE: P = out_of_limit_ge; if yE == DE.D.clone() { result = Some(()); } else { @@ -177,20 +196,24 @@ impl Msegmentation { } } - pub fn decrypt( - DE_vec: &Helgamalsegmented, - G: &GE, - private_key: &FE, + pub fn decrypt

( + DE_vec: &Helgamalsegmented

, + G: &P, + private_key: &P::Scalar, segment_size: &usize, - ) -> Result { + ) -> Result + where + P: ECPoint + Clone + Sync + Send, + P::Scalar: Clone + PartialEq + Sync + Send, + { let limit = 2u32.pow(segment_size.clone() as u32); let test_ge_table = (1..limit) .into_par_iter() .map(|i| { let test_fe = ECScalar::from(&BigInt::from(i)); - G * &test_fe + G.clone() * test_fe }) - .collect::>(); + .collect::>(); let vec_secret = (0..DE_vec.DE.len()) .into_par_iter() .map(|i| { @@ -204,19 +227,19 @@ impl Msegmentation { // .expect("error decrypting"); result }) - .collect::>>(); + .collect::>>(); let mut flag = true; let vec_secret_unwrap = (0..vec_secret.len()) .into_iter() .map(|i| { if vec_secret[i].is_err() { flag = false; - FE::zero() + ::zero() } else { - vec_secret[i].unwrap() + vec_secret[i].clone().unwrap() } }) - .collect::>(); + .collect::>(); match flag { false => Err(ErrorDecrypting), true => Ok(Msegmentation::assemble_fe( diff --git a/src/lib.rs b/src/lib.rs index 1976dcb..9dd65b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,12 +14,13 @@ version 3 of the License, or (at your option) any later version. @license GPL-3.0+ */ -// pub mod grad_release; -// pub mod juggling; +pub mod grad_release; +pub mod juggling; pub mod wallet; extern crate bulletproof; extern crate curv; extern crate rayon; +extern crate zeroize; #[macro_use] extern crate serde_derive;