diff --git a/common/nym-compact-ecash/src/proofs/mod.rs b/common/nym-compact-ecash/src/proofs/mod.rs index 5da7a85e5d..1efe6199ec 100644 --- a/common/nym-compact-ecash/src/proofs/mod.rs +++ b/common/nym-compact-ecash/src/proofs/mod.rs @@ -3,8 +3,8 @@ use std::convert::TryFrom; use std::convert::TryInto; use bls12_381::{G1Affine, G1Projective, Scalar}; -use digest::Digest; use digest::generic_array::typenum::Unsigned; +use digest::Digest; use group::GroupEncoding; use itertools::izip; use sha2::Sha256; @@ -18,10 +18,10 @@ type ChallengeDigest = Sha256; /// Generates a Scalar [or Fp] challenge by hashing a number of elliptic curve points. fn compute_challenge(iter: I) -> Scalar - where - D: Digest, - I: Iterator, - B: AsRef<[u8]>, +where + D: Digest, + I: Iterator, + B: AsRef<[u8]>, { let mut h = D::new(); for point_representation in iter { @@ -49,8 +49,8 @@ fn produce_response(witness_replacement: &Scalar, challenge: &Scalar, secret: &S // note: it's caller's responsibility to ensure witnesses.len() = secrets.len() fn produce_responses(witnesses: &[Scalar], challenge: &Scalar, secrets: &[S]) -> Vec - where - S: Borrow, +where + S: Borrow, { debug_assert_eq!(witnesses.len(), secrets.len()); @@ -91,16 +91,12 @@ impl TryFrom<&[u8]> for WithdrawalReqInstance { let com_bytes: [u8; 48] = bytes[..48].try_into().unwrap(); let com = try_deserialize_g1_projective( &com_bytes, - CompactEcashError::Deserialization( - "Failed to deserialize com".to_string(), - ), + CompactEcashError::Deserialization("Failed to deserialize com".to_string()), )?; let h_bytes: [u8; 48] = bytes[48..96].try_into().unwrap(); let h = try_deserialize_g1_projective( &h_bytes, - CompactEcashError::Deserialization( - "Failed to deserialize h".to_string(), - ), + CompactEcashError::Deserialization("Failed to deserialize h".to_string()), )?; let pc_coms_len = u64::from_le_bytes(bytes[96..104].try_into().unwrap()); let actual_pc_coms_len = (bytes.len() - 152) / 48; @@ -191,10 +187,10 @@ impl WithdrawalReqProof { // compute zkp commitments for each instance let zkcm_com = params.gen1() * r_com_opening + r_attributes - .iter() - .zip(params.gammas().iter()) - .map(|(rm_i, gamma_i)| gamma_i * rm_i) - .sum::(); + .iter() + .zip(params.gammas().iter()) + .map(|(rm_i, gamma_i)| gamma_i * rm_i) + .sum::(); let zkcm_pedcom = r_pedcom_openings .iter() @@ -216,7 +212,6 @@ impl WithdrawalReqProof { .map(|cm| cm.to_bytes()) .collect::>(); - println!("Zk commitments to com {:?}", zkcm_com.to_bytes()); // compute zkp challenge using g1, gammas, c, h, c1, c2, c3, zk commitments let challenge = compute_challenge::( std::iter::once(params.gen1().to_bytes().as_ref()) @@ -228,11 +223,7 @@ impl WithdrawalReqProof { ); // compute response - let response_opening = produce_response( - &r_com_opening, - &challenge, - &witness.com_opening, - ); + let response_opening = produce_response(&r_com_opening, &challenge, &witness.com_opening); let response_openings = produce_responses( &r_pedcom_openings, &challenge, @@ -257,20 +248,24 @@ impl WithdrawalReqProof { let zkcm_com = instance.com * self.challenge + params.gen1() * self.response_opening + self - .response_attributes - .iter() - .zip(params.gammas().iter()) - .map(|(m_i, gamma_i)| gamma_i * m_i) - .sum::(); + .response_attributes + .iter() + .zip(params.gammas().iter()) + .map(|(m_i, gamma_i)| gamma_i * m_i) + .sum::(); let zkcm_pedcom = izip!( instance.pc_coms.iter(), self.response_openings.iter(), - self.response_attributes.iter()) - .map(|(cm_j, resp_o_j, resp_m_j)| cm_j * self.challenge + params.gen1() * resp_o_j + instance.h * resp_m_j) - .collect::>(); + self.response_attributes.iter() + ) + .map(|(cm_j, resp_o_j, resp_m_j)| { + cm_j * self.challenge + params.gen1() * resp_o_j + instance.h * resp_m_j + }) + .collect::>(); - let zk_commitment_user_sk = instance.pk_user.pk * self.challenge + params.gen1() * self.response_attributes[0]; + let zk_commitment_user_sk = + instance.pk_user.pk * self.challenge + params.gen1() * self.response_attributes[0]; // covert to bytes let gammas_bytes = params @@ -284,8 +279,6 @@ impl WithdrawalReqProof { .map(|cm| cm.to_bytes()) .collect::>(); - println!("Zk commitments to com Vfy {:?}", zkcm_com.to_bytes()); - // recompute zkp challenge let challenge = compute_challenge::( std::iter::once(params.gen1().to_bytes().as_ref()) @@ -296,8 +289,6 @@ impl WithdrawalReqProof { .chain(std::iter::once(zk_commitment_user_sk.to_bytes().as_ref())), ); - println!("Original challenge: {:?}", self.challenge); - println!("Recomputed challenge: {:?}", challenge); challenge == self.challenge } } @@ -318,8 +309,14 @@ mod tests { let instance = WithdrawalReqInstance { com: G1Projective::random(&mut rng), h: G1Projective::random(&mut rng), - pc_coms: vec![G1Projective::random(&mut rng), G1Projective::random(&mut rng), G1Projective::random(&mut rng)], - pk_user: PublicKeyUser { pk: params.gen1() * params.random_scalar() }, + pc_coms: vec![ + G1Projective::random(&mut rng), + G1Projective::random(&mut rng), + G1Projective::random(&mut rng), + ], + pk_user: PublicKeyUser { + pk: params.gen1() * params.random_scalar(), + }, }; let instance_bytes = instance.to_bytes(); @@ -332,17 +329,20 @@ mod tests { let mut rng = thread_rng(); let params = Parameters::new().unwrap(); let sk = params.random_scalar(); - let pk_user = PublicKeyUser { pk: params.gen1() * sk }; + let pk_user = PublicKeyUser { + pk: params.gen1() * sk, + }; let v = params.random_scalar(); let t = params.random_scalar(); let attr = vec![sk, v, t]; let com_opening = params.random_scalar(); - let com = params.gen1() * com_opening + attr - .iter() - .zip(params.gammas()) - .map(|(&m, gamma)| gamma * m) - .sum::(); + let com = params.gen1() * com_opening + + attr + .iter() + .zip(params.gammas()) + .map(|(&m, gamma)| gamma * m) + .sum::(); let h = hash_g1(com.to_bytes()); let pc_openings = params.n_random_scalars(attr.len()); @@ -367,4 +367,4 @@ mod tests { let zk_proof = WithdrawalReqProof::construct(¶ms, &instance, &witness); assert!(zk_proof.verify(¶ms, &instance)) } -} \ No newline at end of file +} diff --git a/common/nym-compact-ecash/src/scheme/keygen.rs b/common/nym-compact-ecash/src/scheme/keygen.rs index 267f4cc16f..e23b65ad61 100644 --- a/common/nym-compact-ecash/src/scheme/keygen.rs +++ b/common/nym-compact-ecash/src/scheme/keygen.rs @@ -6,11 +6,11 @@ use bls12_381::{G1Projective, G2Projective, Scalar}; use crate::error::{CompactEcashError, Result}; use crate::scheme::setup::Parameters; use crate::scheme::SignerIndex; +use crate::utils::Polynomial; use crate::utils::{ try_deserialize_g1_projective, try_deserialize_g2_projective, try_deserialize_scalar, try_deserialize_scalar_vec, }; -use crate::utils::Polynomial; #[derive(Debug, PartialEq, Clone)] pub struct SecretKeyAuth { @@ -203,7 +203,9 @@ impl KeyPairAuth { self.secret_key.clone() } - pub fn verification_key(&self) -> VerificationKeyAuth { self.verification_key.clone() } + pub fn verification_key(&self) -> VerificationKeyAuth { + self.verification_key.clone() + } } pub struct KeyPairUser { @@ -291,4 +293,4 @@ pub fn ttp_keygen( .collect(); Ok(keypairs) -} \ No newline at end of file +} diff --git a/common/nym-compact-ecash/src/scheme/mod.rs b/common/nym-compact-ecash/src/scheme/mod.rs index bc2705d4d9..60d7b99528 100644 --- a/common/nym-compact-ecash/src/scheme/mod.rs +++ b/common/nym-compact-ecash/src/scheme/mod.rs @@ -20,4 +20,4 @@ pub struct Wallet { sig: Signature, v: Scalar, idx: Option, -} \ No newline at end of file +} diff --git a/common/nym-compact-ecash/src/scheme/setup.rs b/common/nym-compact-ecash/src/scheme/setup.rs index 667f77b65d..d9219e6c40 100644 --- a/common/nym-compact-ecash/src/scheme/setup.rs +++ b/common/nym-compact-ecash/src/scheme/setup.rs @@ -1,4 +1,4 @@ -use bls12_381::{G1Affine, G2Affine, G2Prepared, Scalar}; +use bls12_381::{G1Affine, G1Projective, G2Affine, G2Prepared, Scalar}; use ff::Field; use group::{Curve, GroupEncoding}; use rand::thread_rng; @@ -47,7 +47,6 @@ impl Parameters { pub(crate) fn gammas(&self) -> &Vec { &self.gammas } - pub fn random_scalar(&self) -> Scalar { // lazily-initialized thread-local random number generator, seeded by the system diff --git a/common/nym-compact-ecash/src/scheme/withdrawal.rs b/common/nym-compact-ecash/src/scheme/withdrawal.rs index a4f0fa1786..214578b4ee 100644 --- a/common/nym-compact-ecash/src/scheme/withdrawal.rs +++ b/common/nym-compact-ecash/src/scheme/withdrawal.rs @@ -24,7 +24,6 @@ pub struct RequestInfo { t: Scalar, } - pub fn withdrawal_request( params: &Parameters, sk_user: &SecretKeyUser, @@ -35,7 +34,8 @@ pub fn withdrawal_request( let attributes = vec![sk_user.sk, v, t]; let gammas = params.gammas(); let com_opening = params.random_scalar(); - let com = params.gen1() * com_opening + attributes + let com = params.gen1() * com_opening + + attributes .iter() .zip(gammas) .map(|(&m, gamma)| gamma * m) @@ -58,7 +58,9 @@ pub fn withdrawal_request( com, h: com_hash, pc_coms: pc_coms.clone(), - pk_user: PublicKeyUser { pk: params.gen1() * sk_user.sk }, + pk_user: PublicKeyUser { + pk: params.gen1() * sk_user.sk, + }, }; let witness = WithdrawalReqWitness { @@ -124,20 +126,25 @@ pub fn issue_wallet( Ok(BlindedSignature(h, sig)) } - -pub fn issue_verify(params: &Parameters, vk_auth: &VerificationKeyAuth, sk_user: &SecretKeyUser, blind_signature: &BlindedSignature, req_info: &RequestInfo) -> Result { +pub fn issue_verify( + params: &Parameters, + vk_auth: &VerificationKeyAuth, + sk_user: &SecretKeyUser, + blind_signature: &BlindedSignature, + req_info: &RequestInfo, +) -> Result { // Parse the blinded signature let h = blind_signature.0; let c = blind_signature.1; - // Verify the integrity of the reponse from the authority + // Verify the integrity of the response from the authority if !(req_info.com_hash == h) { return Err(CompactEcashError::IssuanceVfy( - "Failed to verify the proof of knowledge".to_string(), + "Integrity verification failed".to_string(), )); } - // Unblind the blinded signature + // Unblind the blinded signature on the partial wallet let blinding_removers = vk_auth .beta_g1 .iter() @@ -148,7 +155,7 @@ pub fn issue_verify(params: &Parameters, vk_auth: &VerificationKeyAuth, sk_user: let unblinded_c = c - blinding_removers; // Verify the signature correctness on the wallet share - let attr = vec![sk_user.sk, req_info.v]; + let attr = vec![sk_user.sk, req_info.v, req_info.t]; let signed_attributes = attr .iter() @@ -167,10 +174,8 @@ pub fn issue_verify(params: &Parameters, vk_auth: &VerificationKeyAuth, sk_user: )); } - Ok(Wallet { - sig: Signature(h, - unblinded_c), + sig: Signature(h, unblinded_c), v: req_info.v, idx: None, }) diff --git a/common/nym-compact-ecash/src/tests/e2e.rs b/common/nym-compact-ecash/src/tests/e2e.rs index 9cf31de50b..3e83442d86 100644 --- a/common/nym-compact-ecash/src/tests/e2e.rs +++ b/common/nym-compact-ecash/src/tests/e2e.rs @@ -1,10 +1,12 @@ use itertools::izip; use crate::error::CompactEcashError; -use crate::scheme::keygen::{generate_keypair_user, PublicKeyUser, SecretKeyUser, ttp_keygen, VerificationKeyAuth}; +use crate::scheme::keygen::{ + generate_keypair_user, ttp_keygen, PublicKeyUser, SecretKeyUser, VerificationKeyAuth, +}; use crate::scheme::setup::Parameters; -use crate::scheme::Wallet; use crate::scheme::withdrawal::{issue_verify, issue_wallet, withdrawal_request}; +use crate::scheme::Wallet; use crate::VerificationKey; #[test] @@ -22,21 +24,21 @@ fn main() -> Result<(), CompactEcashError> { let mut wallet_blinded_signatures = Vec::new(); for auth_keypair in authorities_keypairs { - let blind_signature = issue_wallet(¶ms, auth_keypair.secret_key(), user_keypair.public_key(), &req); + let blind_signature = issue_wallet( + ¶ms, + auth_keypair.secret_key(), + user_keypair.public_key(), + &req, + ); wallet_blinded_signatures.push(blind_signature.unwrap()); } - // let unblinded_wallet_shares: Vec = - // izip!(wallet_blinded_signatures.iter(), verification_keys_auth.iter()) - // .map(|(w, vk)| { - // issue_verify(¶ms, - // vk, - // &user_keypair.secret_key(), - // w, - // &req_info) - // .unwrap() - // }) - // .collect(); + let unblinded_wallet_shares: Vec = izip!( + wallet_blinded_signatures.iter(), + verification_keys_auth.iter() + ) + .map(|(w, vk)| issue_verify(¶ms, vk, &user_keypair.secret_key(), w, &req_info).unwrap()) + .collect(); Ok(()) } diff --git a/common/nym-compact-ecash/src/utils.rs b/common/nym-compact-ecash/src/utils.rs index 93640c4fa8..e9b9cb35ce 100644 --- a/common/nym-compact-ecash/src/utils.rs +++ b/common/nym-compact-ecash/src/utils.rs @@ -6,8 +6,10 @@ use core::ops::Mul; use std::convert::TryInto; use std::ops::Neg; -use bls12_381::{G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, multi_miller_loop, Scalar}; use bls12_381::hash_to_curve::{ExpandMsgXmd, HashToCurve, HashToField}; +use bls12_381::{ + multi_miller_loop, G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, Scalar, +}; use ff::Field; use group::Group; @@ -83,9 +85,9 @@ pub(crate) fn perform_lagrangian_interpolation_at_origin( points: &[SignerIndex], values: &[T], ) -> Result - where - T: Sum, - for<'a> &'a T: Mul, +where + T: Sum, + for<'a> &'a T: Mul, { if points.is_empty() || values.is_empty() { return Err(CompactEcashError::Interpolation( @@ -165,13 +167,19 @@ pub fn try_deserialize_scalar(bytes: &[u8; 32], err: CompactEcashError) -> Resul Into::>::into(Scalar::from_bytes(bytes)).ok_or(err) } -pub fn try_deserialize_g1_projective(bytes: &[u8; 48], err: CompactEcashError) -> Result { +pub fn try_deserialize_g1_projective( + bytes: &[u8; 48], + err: CompactEcashError, +) -> Result { Into::>::into(G1Affine::from_compressed(bytes)) .ok_or(err) .map(G1Projective::from) } -pub fn try_deserialize_g2_projective(bytes: &[u8; 96], err: CompactEcashError) -> Result { +pub fn try_deserialize_g2_projective( + bytes: &[u8; 96], + err: CompactEcashError, +) -> Result { Into::>::into(G2Affine::from_compressed(bytes)) .ok_or(err) .map(G2Projective::from)