From 5bdbee6dae9397d798ad183e551b0d143d4b8ca7 Mon Sep 17 00:00:00 2001 From: aniampio Date: Thu, 30 Jun 2022 18:14:59 +0100 Subject: [PATCH] Fix in the identify function --- .../src/scheme/identification.rs | 114 ++++++++++++++---- .../src/scheme/setup.rs | 29 +++-- 2 files changed, 106 insertions(+), 37 deletions(-) diff --git a/common/nym_offline_divisible_ecash/src/scheme/identification.rs b/common/nym_offline_divisible_ecash/src/scheme/identification.rs index 3bc6b07447..e3dc32783a 100644 --- a/common/nym_offline_divisible_ecash/src/scheme/identification.rs +++ b/common/nym_offline_divisible_ecash/src/scheme/identification.rs @@ -35,20 +35,9 @@ pub fn identify( // compute the serial numbers for k1 in [0, V1-1] let mut serial_numbers = HashMap::new(); - println!("Let's see, where is the difference"); - println!("Payment1 Phi1 {:?}", payment1.phi.1); - println!("Payment2 Phi1 {:?}", payment2.phi.1); - - println!("Payment1 Phi0 {:?}", payment1.phi.0); - println!("Payment2 Phi0 {:?}", payment2.phi.0); - - println!("Payment1 vv {:?}", payment1.vv); - println!("Payment2 vv {:?}", payment2.vv); - - for k1 in 0..payment1.vv { let sn = pairing(&payment1.phi.1.to_affine(), ¶ms_a.get_ith_delta(k1 as usize).to_affine()) - + pairing(&payment1.phi.0.to_affine(), ¶ms_a.get_ith_eta(k1 as usize).to_affine()); + + pairing(&payment1.phi.0.to_affine(), ¶ms_a.get_etas_ith_jth_elem(payment1.vv as usize, k1 as usize).to_affine()); serial_numbers.insert(sn, k1); } @@ -56,7 +45,7 @@ pub fn identify( let mut duplicate_serial_numbers: Vec<(Gt, u64, u64)> = Default::default(); for k2 in 0..payment2.vv { let sn = pairing(&payment2.phi.1.to_affine(), ¶ms_a.get_ith_delta(k2 as usize).to_affine()) - + pairing(&payment2.phi.0.to_affine(), ¶ms_a.get_ith_eta(k2 as usize).to_affine()); + + pairing(&payment2.phi.0.to_affine(), ¶ms_a.get_etas_ith_jth_elem(payment2.vv as usize, k2 as usize).to_affine()); if !serial_numbers.contains_key(&sn) { serial_numbers.insert(sn, k2); } else { @@ -65,7 +54,6 @@ pub fn identify( } } - println!("HOw many duplicates: {:?}", duplicate_serial_numbers.len()); if duplicate_serial_numbers.is_empty() { Ok(IdentifyResult::NotADuplicatePayment) } else { @@ -78,14 +66,14 @@ pub fn identify( let delta_k1 = params_a.get_ith_delta(k1 as usize); let delta_k2 = params_a.get_ith_delta(k2 as usize); let tt1 = pairing(&payment1.varphi.1.to_affine(), &delta_k1.to_affine()) - + pairing(&payment1.varphi.0.to_affine(), ¶ms_a.get_ith_eta(k1 as usize).to_affine()); + + pairing(&payment1.varphi.0.to_affine(), ¶ms_a.get_etas_ith_jth_elem(payment1.vv as usize, k1 as usize).to_affine()); let tt2 = pairing(&payment2.varphi.1.to_affine(), &delta_k2.to_affine()) - + pairing(&payment2.varphi.0.to_affine(), ¶ms_a.get_ith_eta(k2 as usize).to_affine()); + + pairing(&payment2.varphi.0.to_affine(), ¶ms_a.get_etas_ith_jth_elem(payment2.vv as usize, k2 as usize).to_affine()); for pk_u in public_keys_u.iter() { - let pg_pku_deltas = pairing(&pk_u.pk.to_affine(), &(delta_k1 * payment1.rr.neg() + delta_k2 * payment2.rr.neg()).to_affine()); - if tt1 + tt2 * Scalar::from(1).neg() == pg_pku_deltas { + let pg_pku_deltas = pairing(&pk_u.pk.to_affine(), &(delta_k1 * payment1.rr + delta_k2 * payment2.rr.neg()).to_affine()); + if tt1 - tt2 == pg_pku_deltas { return Ok(IdentifyResult::DoubleSpendingPublicKeys(pk_u.clone())); } } @@ -101,6 +89,8 @@ pub fn identify( mod tests { use std::collections::HashSet; + use bls12_381::pairing; + use group::Curve; use rand::thread_rng; use crate::scheme::{PayInfo, Payment}; @@ -204,12 +194,12 @@ mod tests { // GENERATE KEYS FOR OTHER USERS let mut pk_all_users: Vec = Default::default(); - // for i in 0..50 { - // let sk = grp.random_scalar(); - // let sk_user = SecretKeyUser { sk }; - // let pk_user = sk_user.public_key(&grp); - // pk_all_users.push(pk_user); - // } + for i in 0..50 { + let sk = grp.random_scalar(); + let sk_user = SecretKeyUser { sk }; + let pk_user = sk_user.public_key(&grp); + pk_all_users.push(pk_user); + } pk_all_users.push(pk_user1.clone()); pk_all_users.push(pk_user2.clone()); @@ -235,10 +225,82 @@ mod tests { let pay_info1 = PayInfo { info: [67u8; 32] }; let (payment1, new_wallet1) = wallet1.spend(¶ms, &verification_key, &sk_user1, &pay_info1, 10).unwrap(); + // let's reverse the spending counter in the wallet to create a double spending payment + let current_l = wallet1.l.get(); + wallet1.l.set(current_l - 1); + + let pay_info2 = PayInfo { info: [52u8; 32] }; + let (payment2, wallet1) = wallet1.spend(¶ms, &verification_key, &sk_user1, &pay_info2, 10).unwrap(); + + + let identify_result = identify(¶ms, &verification_key, &pk_all_users, payment1, payment2, pay_info1, pay_info2).unwrap(); + + assert_eq!(identify_result, IdentifyResult::DoubleSpendingPublicKeys(pk_user1)); + } + + #[test] + fn two_payments_with_multiple_repeating_serial_number_but_different_pay_info() { + let rng = thread_rng(); + let grp = GroupParameters::new().unwrap(); + let params = Parameters::new(grp.clone()); + let params_u = params.get_params_u(); + let params_a = params.get_params_a(); + + // KEY GENERATION FOR THE AUTHORITIES + let authorities_keypairs = ttp_keygen_authorities(¶ms, 2, 3).unwrap(); + let verification_keys_auth: Vec = authorities_keypairs + .iter() + .map(|keypair| keypair.verification_key()) + .collect(); + + let verification_key = + aggregate_verification_keys(&verification_keys_auth, Some(&[1, 2, 3])).unwrap(); + + // KEY GENERATION FOR THE USER1 + let sk1 = grp.random_scalar(); + let sk_user1 = SecretKeyUser { sk: sk1 }; + let pk_user1 = SecretKeyUser::public_key(&sk_user1, &grp); + + // KEY GENERATION FOR THE USER2 + let sk_user2 = sk_user1.clone(); + let pk_user2 = pk_user1.clone(); + + // GENERATE KEYS FOR OTHER USERS + let mut pk_all_users: Vec = Default::default(); + for i in 0..50 { + let sk = grp.random_scalar(); + let sk_user = SecretKeyUser { sk }; + let pk_user = sk_user.public_key(&grp); + pk_all_users.push(pk_user); + } + pk_all_users.push(pk_user1.clone()); + pk_all_users.push(pk_user2.clone()); + + // WITHDRAWAL REQUEST FOR USER1 + let (withdrawal_req1, req_info1) = withdrawal_request(¶ms, &sk_user1).unwrap(); + + // ISSUE PARTIAL WALLETS for USER1 + let mut partial_wallets1 = Vec::new(); + for auth_keypair in authorities_keypairs.clone() { + let blind_signature = issue( + ¶ms, + &withdrawal_req1, + pk_user1.clone(), + &auth_keypair.secret_key(), + ).unwrap(); + let partial_wallet1 = issue_verify(&grp, &auth_keypair.verification_key(), &sk_user1, &blind_signature, &req_info1).unwrap(); + partial_wallets1.push(partial_wallet1); + } + + // AGGREGATE WALLET FOR USER1 + let mut wallet1 = aggregate_wallets(&grp, &verification_key, &sk_user1, &partial_wallets1).unwrap(); + + let pay_info1 = PayInfo { info: [67u8; 32] }; + let (payment1, new_wallet1) = wallet1.spend(¶ms, &verification_key, &sk_user1, &pay_info1, 10).unwrap(); // let's reverse the spending counter in the wallet to create a double spending payment - // let current_l = wallet1.l.get(); - // wallet1.l.set(current_l - 1); + let current_l = wallet1.l.get(); + wallet1.l.set(current_l - 7); let pay_info2 = PayInfo { info: [52u8; 32] }; let (payment2, wallet1) = wallet1.spend(¶ms, &verification_key, &sk_user1, &pay_info2, 10).unwrap(); diff --git a/common/nym_offline_divisible_ecash/src/scheme/setup.rs b/common/nym_offline_divisible_ecash/src/scheme/setup.rs index cb6e6557c0..15f1ce94e6 100644 --- a/common/nym_offline_divisible_ecash/src/scheme/setup.rs +++ b/common/nym_offline_divisible_ecash/src/scheme/setup.rs @@ -1,7 +1,7 @@ use std::convert::TryFrom; use std::net::ToSocketAddrs; -use bls12_381::{G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, Scalar}; +use bls12_381::{G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, pairing, Scalar}; use ff::Field; use group::Curve; use rand::thread_rng; @@ -59,6 +59,8 @@ pub struct Parameters { grp: GroupParameters, params_u: ParametersUser, params_a: ParametersAuthority, + tmp_sigma: G1Projective, + pub y: Scalar, } impl Parameters { @@ -77,7 +79,6 @@ impl Parameters { let gamma1 = hash_g1("gamma1"); let gamma2 = hash_g1("gamma2"); let eta = hash_g1("eta"); - let omega = hash_g1("omega"); let z = grp.random_scalar(); let y = grp.random_scalar(); @@ -101,11 +102,13 @@ impl Parameters { let etas_u: Vec = vec_a.iter().map(|x| g1 * x).collect(); - let mut etas_a: Vec = Default::default(); + let mut etas_a: Vec> = Default::default(); for l in 1..=L { + let mut etas_a_l: Vec = Default::default(); for k in 0..=l - 1 { - etas_a.push(g2 * (vec_a[l as usize - 1].neg() * (y.pow(&[k as u64, 0, 0, 0])))); + etas_a_l.push(g2 * (vec_a[l as usize - 1].neg() * (y.pow(&[k as u64, 0, 0, 0])))); } + etas_a.push(etas_a_l); } let sps_keypair = SPSKeyPair::new(grp.clone(), 2, 0); @@ -123,7 +126,6 @@ impl Parameters { psi_g1, psi_g2, eta, - omega, etas: etas_u, sigmas: sigmas_u, thetas: thetas_u, @@ -140,17 +142,22 @@ impl Parameters { grp, params_u, params_a, + tmp_sigma: sigma, + y, }; } } +impl Parameters { + pub(crate) fn get_sigma(&self) -> &G1Projective { &self.tmp_sigma } +} + #[derive(Debug, Clone)] pub struct ParametersUser { gammas: Vec, psi_g1: G1Projective, psi_g2: G2Projective, eta: G1Projective, - omega: G1Projective, etas: Vec, sigmas: Vec, thetas: Vec, @@ -167,8 +174,6 @@ impl ParametersUser { pub(crate) fn get_eta(&self) -> &G1Projective { &self.eta } - pub(crate) fn get_omega(&self) -> &G1Projective { &self.omega } - pub(crate) fn get_etas(&self) -> &[G1Projective] { &self.etas } pub(crate) fn get_ith_eta(&self, idx: usize) -> &G1Projective { self.etas.get(idx - 1).unwrap() } @@ -191,7 +196,7 @@ impl ParametersUser { #[derive(Debug, Clone)] pub struct ParametersAuthority { deltas: Vec, - etas: Vec, + etas: Vec>, } impl ParametersAuthority { @@ -199,7 +204,9 @@ impl ParametersAuthority { pub(crate) fn get_ith_delta(&self, idx: usize) -> &G2Projective { self.deltas.get(idx).unwrap() } - pub(crate) fn get_etas(&self) -> &[G2Projective] { &self.etas } + pub(crate) fn get_etas(&self) -> &Vec> { &self.etas } - pub(crate) fn get_ith_eta(&self, idx: usize) -> &G2Projective { self.etas.get(idx).unwrap() } + pub(crate) fn get_eta_ith_row(&self, idx: usize) -> &[G2Projective] { self.etas.get(idx).unwrap() } + + pub(crate) fn get_etas_ith_jth_elem(&self, row: usize, column: usize) -> &G2Projective { self.etas.get(row - 1).unwrap().get(column).unwrap() } }