Update for compact e-cash - remove requirement for security tag

This commit is contained in:
aniampio
2022-08-03 15:46:15 +01:00
committed by durch
parent 3ffa367de1
commit fecb67ded7
10 changed files with 92 additions and 217 deletions
@@ -1,18 +1,10 @@
use std::borrow::Borrow;
use std::convert::TryFrom;
use std::convert::TryInto;
use bls12_381::{G1Affine, G1Projective, Scalar};
use digest::generic_array::typenum::Unsigned;
use bls12_381::Scalar;
use digest::Digest;
use group::GroupEncoding;
use digest::generic_array::typenum::Unsigned;
use sha2::Sha256;
use crate::error::{CompactEcashError, Result};
use crate::scheme::keygen::PublicKeyUser;
use crate::scheme::setup::GroupParameters;
use crate::utils::try_deserialize_g1_projective;
pub mod proof_spend;
pub mod proof_withdrawal;
@@ -20,10 +12,10 @@ type ChallengeDigest = Sha256;
/// Generates a Scalar [or Fp] challenge by hashing a number of elliptic curve points.
fn compute_challenge<D, I, B>(iter: I) -> Scalar
where
D: Digest,
I: Iterator<Item = B>,
B: AsRef<[u8]>,
where
D: Digest,
I: Iterator<Item=B>,
B: AsRef<[u8]>,
{
let mut h = D::new();
for point_representation in iter {
@@ -51,8 +43,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<S>(witnesses: &[Scalar], challenge: &Scalar, secrets: &[S]) -> Vec<Scalar>
where
S: Borrow<Scalar>,
where
S: Borrow<Scalar>,
{
debug_assert_eq!(witnesses.len(), secrets.len());
@@ -1,13 +1,12 @@
use std::convert::{TryFrom, TryInto};
use std::ops::Neg;
use bls12_381::{G1Projective, G2Projective, Scalar};
use group::{Curve, Group, GroupEncoding};
use group::{Curve, GroupEncoding};
use crate::error::{CompactEcashError, Result};
use crate::proofs::{ChallengeDigest, compute_challenge, produce_response, produce_responses};
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::scheme::keygen::VerificationKeyAuth;
use crate::scheme::setup::Parameters;
use crate::utils::{try_deserialize_g1_projective, try_deserialize_g2_projective};
#[derive(Debug)]
@@ -15,7 +14,6 @@ use crate::utils::{try_deserialize_g1_projective, try_deserialize_g2_projective}
pub struct SpendInstance {
pub kappa: G2Projective,
pub cc: G1Projective,
pub dd: G1Projective,
pub aa: Vec<G1Projective>,
pub ss: Vec<G1Projective>,
pub tt: Vec<G1Projective>,
@@ -78,13 +76,6 @@ impl TryFrom<&[u8]> for SpendInstance {
)?;
j += 48;
let dd_bytes = bytes[j..j + 48].try_into().unwrap();
let dd = try_deserialize_g1_projective(
&dd_bytes,
CompactEcashError::Deserialization("Failed to deserialize D".to_string()),
)?;
j += 48;
let s_len = u64::from_le_bytes(bytes[j..j + 8].try_into().unwrap());
j += 8;
if bytes[j..].len() < s_len as usize * 48 {
@@ -167,7 +158,6 @@ impl TryFrom<&[u8]> for SpendInstance {
kappa,
aa,
cc,
dd,
ss,
tt,
kappa_k,
@@ -186,7 +176,6 @@ impl SpendInstance {
}
bytes.extend_from_slice(self.cc.to_bytes().as_ref());
bytes.extend_from_slice(self.dd.to_bytes().as_ref());
bytes.extend_from_slice(&self.ss.len().to_le_bytes());
for s in &self.ss {
@@ -211,13 +200,10 @@ pub struct SpendWitness {
// signature randomizing element
pub r: Scalar,
pub o_c: Scalar,
pub o_d: Scalar,
pub lk: Vec<Scalar>,
pub o_a: Vec<Scalar>,
pub mu: Vec<Scalar>,
pub lambda: Vec<Scalar>,
pub o_mu: Vec<Scalar>,
pub o_lambda: Vec<Scalar>,
pub r_k: Vec<Scalar>,
}
@@ -229,11 +215,8 @@ pub struct SpendProof {
response_l: Vec<Scalar>,
response_o_a: Vec<Scalar>,
response_o_c: Scalar,
response_o_d: Scalar,
response_mu: Vec<Scalar>,
response_lambda: Vec<Scalar>,
response_o_mu: Vec<Scalar>,
response_o_lambda: Vec<Scalar>,
response_attributes: Vec<Scalar>,
}
@@ -250,18 +233,14 @@ impl SpendProof {
let r_attributes = grparams.n_random_scalars(witness.attributes.len());
let r_sk = r_attributes[0];
let r_v = r_attributes[1];
let r_t = r_attributes[2];
let r_r = grparams.random_scalar();
let r_o_c = grparams.random_scalar();
let r_o_d = grparams.random_scalar();
let r_r_lk = grparams.n_random_scalars(witness.r_k.len());
let r_lk = grparams.n_random_scalars(witness.lk.len());
let r_o_a = grparams.n_random_scalars(witness.o_a.len());
let r_mu = grparams.n_random_scalars(witness.mu.len());
let r_lambda = grparams.n_random_scalars(witness.lambda.len());
let r_o_mu = grparams.n_random_scalars(witness.o_mu.len());
let r_o_lambda = grparams.n_random_scalars(witness.o_lambda.len());
let g1 = *grparams.gen1();
let gamma1 = *grparams.gamma1();
@@ -281,7 +260,6 @@ impl SpendProof {
.sum::<G2Projective>();
let zkcm_cc = g1 * r_o_c + gamma1 * r_v;
let zkcm_dd = g1 * r_o_d + gamma1 * r_t;
let zkcm_aa: Vec<G1Projective> =
r_o_a
@@ -294,7 +272,7 @@ impl SpendProof {
.map(|x| x.to_bytes())
.collect::<Vec<_>>();
let zkcm_ss = r_mu.iter().map(|r_mu_k| g1 * r_mu_k).collect::<Vec<_>>();
let zkcm_ss = r_mu.iter().map(|r_mu_k| grparams.delta() * r_mu_k).collect::<Vec<_>>();
let zkcm_ss_bytes = zkcm_ss
.iter()
@@ -303,7 +281,7 @@ impl SpendProof {
let zkcm_tt = rr
.iter()
.zip(r_lambda.iter()).map(|(rr_k, r_lambda_k)| g1 * r_sk + (g1 * rr_k) * r_lambda_k).collect::<Vec<_>>();
.zip(r_mu.iter()).map(|(rr_k, r_mu_k)| g1 * r_sk + (g1 * rr_k) * r_mu_k).collect::<Vec<_>>();
let zkcm_tt_bytes = zkcm_tt
.iter()
@@ -322,21 +300,9 @@ impl SpendProof {
.map(|x| x.to_bytes())
.collect::<Vec<_>>();
let zkcm_gamma12 = instance.aa
.iter()
.zip(r_lambda.iter())
.zip(r_o_lambda.iter())
.map(|((aa_k, r_lambda_k), r_o_lambda_k)| (aa_k + instance.dd + gamma1) * r_lambda_k + g1 * r_o_lambda_k)
.collect::<Vec<_>>();
let zkcm_gamma12_bytes = zkcm_gamma12
.iter()
.map(|x| x.to_bytes())
.collect::<Vec<_>>();
let zkcm_kappa_k = r_lk.iter()
.zip(r_r_lk.iter())
.map(|(r_k, r_r_k)| params.pkRP().alpha + params.pkRP().beta * r_k + grparams.gen2() * r_r_k)
.map(|(r_k, r_r_k)| params.pk_rp().alpha + params.pk_rp().beta * r_k + grparams.gen2() * r_r_k)
.collect::<Vec<_>>();
let zkcm_kappa_k_bytes = zkcm_kappa_k
@@ -353,13 +319,11 @@ impl SpendProof {
.chain(std::iter::once(instance.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_kappa.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_cc.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_dd.to_bytes().as_ref()))
.chain(zkcm_aa_bytes.iter().map(|x| x.as_ref()))
.chain(zkcm_ss_bytes.iter().map(|x| x.as_ref()))
.chain(zkcm_kappa_k_bytes.iter().map(|x| x.as_ref()))
.chain(zkcm_tt_bytes.iter().map(|x| x.as_ref()))
.chain(zkcm_gamma11_bytes.iter().map(|x| x.as_ref()))
.chain(zkcm_gamma12_bytes.iter().map(|x| x.as_ref())),
);
// compute response for each witness
@@ -373,12 +337,9 @@ impl SpendProof {
let response_l = produce_responses(&r_lk, &challenge, &witness.lk);
let response_o_a = produce_responses(&r_o_a, &challenge, &witness.o_a);
let response_o_c = produce_response(&r_o_c, &challenge, &witness.o_c);
let response_o_d = produce_response(&r_o_d, &challenge, &witness.o_d);
let response_mu = produce_responses(&r_mu, &challenge, &witness.mu);
let response_lambda = produce_responses(&r_lambda, &challenge, &witness.lambda);
let response_o_mu = produce_responses(&r_o_mu, &challenge, &witness.o_mu);
let response_o_lambda = produce_responses(&r_o_lambda, &challenge, &witness.o_lambda);
SpendProof {
challenge,
@@ -387,11 +348,8 @@ impl SpendProof {
response_l,
response_o_a,
response_o_c,
response_o_d,
response_mu,
response_lambda,
response_o_mu,
response_o_lambda,
response_attributes,
}
}
@@ -438,14 +396,11 @@ impl SpendProof {
let zkcm_cc = g1 * self.response_o_c
+ gamma1 * self.response_attributes[1]
+ instance.cc * self.challenge;
let zkcm_dd = g1 * self.response_o_d
+ gamma1 * self.response_attributes[2]
+ instance.dd * self.challenge;
let zkcm_ss = self.response_mu
.iter()
.zip(instance.ss.iter())
.map(|(resp_mu_k, ss_k)| g1 * resp_mu_k + ss_k * self.challenge)
.map(|(resp_mu_k, ss_k)| grparams.delta() * resp_mu_k + ss_k * self.challenge)
.collect::<Vec<_>>();
let zkcm_ss_bytes = zkcm_ss
@@ -453,11 +408,11 @@ impl SpendProof {
.map(|x| x.to_bytes())
.collect::<Vec<_>>();
let zkcm_tt = self.response_lambda
let zkcm_tt = self.response_mu
.iter()
.zip(rr.iter())
.zip(instance.tt.iter())
.map(|((resp_lambda_k, rr_k), tt_k)| g1 * self.response_attributes[0] + (g1 * rr_k) * resp_lambda_k + tt_k * self.challenge)
.map(|((resp_mu_k, rr_k), tt_k)| g1 * self.response_attributes[0] + (g1 * rr_k) * resp_mu_k + tt_k * self.challenge)
.collect::<Vec<_>>();
let zkcm_tt_bytes = zkcm_tt
@@ -479,24 +434,11 @@ impl SpendProof {
.collect::<Vec<_>>();
let zkcm_gamma12 = instance.aa
.iter()
.zip(self.response_lambda.iter())
.zip(self.response_o_lambda.iter())
.map(|((aa_k, resp_lambda_k), resp_o_lambda_k)| (aa_k + instance.dd + gamma1) * resp_lambda_k
+ g1 * resp_o_lambda_k + gamma1 * self.challenge)
.collect::<Vec<_>>();
let zkcm_gamma12_bytes = zkcm_gamma12
.iter()
.map(|x| x.to_bytes())
.collect::<Vec<_>>();
let zkcm_kappa_k = instance.kappa_k
.iter()
.zip(self.response_r_l.iter())
.zip(self.response_l.iter())
.map(|((kappa_k, resp_r_k), resp_r_l_k)| kappa_k * self.challenge + grparams.gen2() * resp_r_k + params.pkRP().alpha * (Scalar::one() - self.challenge) + params.pkRP().beta * resp_r_l_k)
.map(|((kappa_k, resp_r_k), resp_r_l_k)| kappa_k * self.challenge + grparams.gen2() * resp_r_k + params.pk_rp().alpha * (Scalar::one() - self.challenge) + params.pk_rp().beta * resp_r_l_k)
.collect::<Vec<_>>();
let zkcm_kappa_k_bytes = zkcm_kappa_k
@@ -513,13 +455,11 @@ impl SpendProof {
.chain(std::iter::once(instance.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_kappa.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_cc.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_dd.to_bytes().as_ref()))
.chain(zkcm_aa_bytes.iter().map(|x| x.as_ref()))
.chain(zkcm_ss_bytes.iter().map(|x| x.as_ref()))
.chain(zkcm_kappa_k_bytes.iter().map(|x| x.as_ref()))
.chain(zkcm_tt_bytes.iter().map(|x| x.as_ref()))
.chain(zkcm_gamma11_bytes.iter().map(|x| x.as_ref()))
.chain(zkcm_gamma12_bytes.iter().map(|x| x.as_ref())),
);
challenge == self.challenge
@@ -528,26 +468,25 @@ impl SpendProof {
#[cfg(test)]
mod tests {
use bls12_381::{G1Projective, G2Projective, Scalar};
use group::Curve;
use rand::{Rng, thread_rng};
use bls12_381::{G2Projective, Scalar};
use rand::thread_rng;
use crate::proofs::proof_spend::{SpendInstance, SpendProof, SpendWitness};
use crate::scheme::{pseudorandom_fgt, pseudorandom_fgv};
use crate::scheme::{pseudorandom_f_delta_v, pseudorandom_f_g_v};
use crate::scheme::aggregation::aggregate_verification_keys;
use crate::scheme::keygen::{PublicKeyUser, ttp_keygen, VerificationKeyAuth};
use crate::scheme::PayInfo;
use crate::scheme::setup::{GroupParameters, setup};
use crate::scheme::setup::setup;
use crate::utils::hash_to_scalar;
#[test]
fn spend_proof_construct_and_verify() {
let rng = thread_rng();
let _rng = thread_rng();
let L = 32;
let params = setup(L);
let grparams = params.grp();
let sk = grparams.random_scalar();
let pk_user = PublicKeyUser {
let _pk_user = PublicKeyUser {
pk: grparams.gen1() * sk,
};
let authorities_keypairs = ttp_keygen(&grparams, 2, 3).unwrap();
@@ -578,40 +517,35 @@ mod tests {
let o_a = grparams.random_scalar();
let o_c = grparams.random_scalar();
let o_d = grparams.random_scalar();
// compute commitments A, C, D
let aa = g1 * o_a + gamma1 * Scalar::from(l);
let cc = g1 * o_c + gamma1 * v;
let dd = g1 * o_d + gamma1 * t;
// compute hash of the payment info
let pay_info = PayInfo { info: [37u8; 32] };
let rr = hash_to_scalar(pay_info.info);
// evaluate the pseudorandom functions
let ss = pseudorandom_fgv(&grparams, v, l);
let tt = g1 * sk + pseudorandom_fgt(&grparams, t, l) * rr;
let ss = pseudorandom_f_delta_v(&grparams, v, l);
let tt = g1 * sk + pseudorandom_f_g_v(&grparams, v, l) * rr;
// compute values mu, o_mu, lambda, o_lambda
let mu: Scalar = (v + Scalar::from(l) + Scalar::from(1)).invert().unwrap();
let o_mu = ((o_a + o_c) * mu).neg();
let lambda = (t + Scalar::from(l) + Scalar::from(1)).invert().unwrap();
let o_lambda = ((o_a + o_d) * lambda).neg();
// parse the signature associated with value l
let sign_l = params.get_sign_by_idx(l).unwrap();
// randomise the signature associated with value l
let (sign_l_prime, r_l) = sign_l.randomise(grparams);
let (_sign_l_prime, r_l) = sign_l.randomise(grparams);
// compute kappa_l
let kappa_k =
grparams.gen2() * r_l + params.pkRP().alpha + params.pkRP().beta * Scalar::from(l);
grparams.gen2() * r_l + params.pk_rp().alpha + params.pk_rp().beta * Scalar::from(l);
let instance = SpendInstance {
kappa,
aa: vec![aa],
cc,
dd,
ss: vec![ss],
tt: vec![tt],
kappa_k: vec![kappa_k],
@@ -621,13 +555,10 @@ mod tests {
attributes,
r,
o_c,
o_d,
lk: vec![Scalar::from(l)],
o_a: vec![o_a],
mu: vec![mu],
lambda: vec![lambda],
o_mu: vec![o_mu],
o_lambda: vec![o_lambda],
r_k: vec![r_l],
};
@@ -5,7 +5,7 @@ use group::GroupEncoding;
use itertools::izip;
use crate::error::{CompactEcashError, Result};
use crate::proofs::{compute_challenge, produce_response, produce_responses, ChallengeDigest};
use crate::proofs::{ChallengeDigest, compute_challenge, produce_response, produce_responses};
use crate::scheme::keygen::PublicKeyUser;
use crate::scheme::setup::GroupParameters;
use crate::utils::try_deserialize_g1_projective;
@@ -136,10 +136,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::<G1Projective>();
.iter()
.zip(params.gammas().iter())
.map(|(rm_i, gamma_i)| gamma_i * rm_i)
.sum::<G1Projective>();
let zkcm_pedcom = r_pedcom_openings
.iter()
@@ -201,21 +201,21 @@ 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::<G1Projective>();
.response_attributes
.iter()
.zip(params.gammas().iter())
.map(|(m_i, gamma_i)| gamma_i * m_i)
.sum::<G1Projective>();
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::<Vec<_>>();
.map(|(cm_j, resp_o_j, resp_m_j)| {
cm_j * self.challenge + params.gen1() * resp_o_j + instance.h * resp_m_j
})
.collect::<Vec<_>>();
let zk_commitment_user_sk =
instance.pk_user.pk * self.challenge + params.gen1() * self.response_attributes[0];
@@ -279,7 +279,7 @@ mod tests {
#[test]
fn withdrawal_proof_construct_and_verify() {
let rng = thread_rng();
let _rng = thread_rng();
let params = GroupParameters::new().unwrap();
let sk = params.random_scalar();
let pk_user = PublicKeyUser {
@@ -292,10 +292,10 @@ mod tests {
let com_opening = params.random_scalar();
let com = params.gen1() * com_opening
+ attr
.iter()
.zip(params.gammas())
.map(|(&m, gamma)| gamma * m)
.sum::<G1Projective>();
.iter()
.zip(params.gammas())
.map(|(&m, gamma)| gamma * m)
.sum::<G1Projective>();
let h = hash_g1(com.to_bytes());
let pc_openings = params.n_random_scalars(attr.len());
@@ -6,16 +6,16 @@ use bls12_381::{G2Prepared, G2Projective, Scalar};
use group::Curve;
use itertools::Itertools;
use crate::Attribute;
use crate::error::{CompactEcashError, Result};
use crate::scheme::{PartialWallet, Wallet};
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
use crate::scheme::setup::GroupParameters;
use crate::scheme::withdrawal::RequestInfo;
use crate::scheme::{PartialWallet, Wallet};
use crate::utils::{
check_bilinear_pairing, perform_lagrangian_interpolation_at_origin, PartialSignature,
check_bilinear_pairing, PartialSignature, perform_lagrangian_interpolation_at_origin,
Signature, SignatureShare, SignerIndex,
};
use crate::Attribute;
pub(crate) trait Aggregatable: Sized {
fn aggregate(aggregatable: &[Self], indices: Option<&[SignerIndex]>) -> Result<Self>;
@@ -27,10 +27,10 @@ pub(crate) trait Aggregatable: Sized {
}
impl<T> Aggregatable for T
where
T: Sum,
for<'a> T: Sum<&'a T>,
for<'a> &'a T: Mul<Scalar, Output = T>,
where
T: Sum,
for<'a> T: Sum<&'a T>,
for<'a> &'a T: Mul<Scalar, Output=T>,
{
fn aggregate(aggregatable: &[T], indices: Option<&[u64]>) -> Result<T> {
if aggregatable.is_empty() {
@@ -156,14 +156,13 @@ pub fn aggregate_wallets(
.map(|(idx, wallet)| SignatureShare::new(*wallet.signature(), (idx + 1) as u64))
.collect();
let attributes = vec![sk_user.sk, req_info.get_v(), req_info.get_t()];
let attributes = vec![sk_user.sk, req_info.get_v()];
let aggregated_signature =
aggregate_signature_shares(&params, &verification_key, &attributes, &signature_shares)?;
Ok(Wallet {
sig: aggregated_signature,
v: req_info.get_v(),
t: req_info.get_t(),
l: Cell::new(0),
})
}
@@ -1,8 +1,3 @@
use std::collections::HashSet;
use bls12_381::G1Projective;
use group::Curve;
use crate::{PayInfo, VerificationKeyAuth};
use crate::error::{CompactEcashError, Result};
use crate::scheme::keygen::PublicKeyUser;
@@ -51,9 +46,6 @@ pub fn identify(params: &Parameters, public_keys_u: &[PublicKeyUser], verificati
#[cfg(test)]
mod tests {
use std::collections::HashSet;
use group::Curve;
use itertools::izip;
use crate::{aggregate_verification_keys, aggregate_wallets, generate_keypair_user, issue_verify, issue_wallet, PartialWallet, PayInfo, ttp_keygen, VerificationKeyAuth, withdrawal_request};
@@ -109,7 +101,7 @@ mod tests {
let pay_info1 = PayInfo { info: [6u8; 32] };
let spend_vv = 1;
let (payment1, upd_wallet) = aggr_wallet.spend(
let (payment1, _upd_wallet) = aggr_wallet.spend(
&params,
&verification_key,
&user_keypair.secret_key(),
@@ -221,7 +213,7 @@ mod tests {
// GENERATE KEYS FOR OTHER USERS
let mut public_keys: Vec<PublicKeyUser> = Default::default();
for i in 0..50 {
for _i in 0..50 {
let sk = grp.random_scalar();
let sk_user = SecretKeyUser { sk };
let pk_user = sk_user.public_key(&grp);
@@ -271,7 +263,7 @@ mod tests {
let pay_info1 = PayInfo { info: [6u8; 32] };
let spend_vv = 1;
let (payment1, _) = aggr_wallet.spend(
let (payment1, _upd_wallet) = aggr_wallet.spend(
&params,
&verification_key,
&user_keypair.secret_key(),
@@ -5,7 +5,7 @@ use std::convert::TryFrom;
use std::convert::TryInto;
use bls12_381::{G1Projective, G2Projective, Scalar};
use group::{Curve, GroupEncoding};
use group::Curve;
use crate::error::{CompactEcashError, Result};
use crate::scheme::aggregation::aggregate_verification_keys;
@@ -1,9 +1,7 @@
use std::cell::Cell;
use std::convert::TryFrom;
use std::convert::TryInto;
use bls12_381::{G1Projective, G2Prepared, G2Projective, Scalar};
use group::{Curve, Group};
use group::Curve;
use crate::Attribute;
use crate::error::{CompactEcashError, Result};
@@ -11,7 +9,7 @@ use crate::proofs::proof_spend::{SpendInstance, SpendProof, SpendWitness};
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::utils::{
check_bilinear_pairing, hash_to_scalar, Signature, SignerIndex, try_deserialize_g1_projective,
check_bilinear_pairing, hash_to_scalar, Signature, SignerIndex,
};
pub mod aggregation;
@@ -41,7 +39,6 @@ impl PartialWallet {
pub struct Wallet {
sig: Signature,
v: Scalar,
t: Scalar,
pub l: Cell<u64>,
}
@@ -52,9 +49,6 @@ impl Wallet {
pub fn v(&self) -> Scalar {
self.v
}
pub fn t(&self) -> Scalar {
self.t
}
pub fn l(&self) -> u64 {
self.l.get()
}
@@ -63,9 +57,6 @@ impl Wallet {
self.l.set(self.l.get() + 1);
}
fn down(&self) {
self.l.set(self.l.get() - 1);
}
pub fn spend(
&self,
@@ -86,7 +77,7 @@ impl Wallet {
// randomize signature in the wallet
let (signature_prime, sign_blinding_factor) = self.signature().randomise(grparams);
// construct kappa i.e., blinded attributes for show
let attributes = vec![sk_user.sk, self.v(), self.t()];
let attributes = vec![sk_user.sk, self.v()];
// compute kappa
let kappa = compute_kappa(
&grparams,
@@ -95,13 +86,11 @@ impl Wallet {
sign_blinding_factor,
);
// pick random openings o_c, o_d
// pick random openings o_c
let o_c = grparams.random_scalar();
let o_d = grparams.random_scalar();
// compute commitments C, D
// compute commitments C
let cc = grparams.gen1() * o_c + grparams.gamma1() * self.v();
let dd = grparams.gen1() * o_d + grparams.gamma1() * self.t();
let mut aa: Vec<G1Projective> = Default::default();
@@ -111,8 +100,6 @@ impl Wallet {
let mut o_a: Vec<Scalar> = Default::default();
let mut o_mu: Vec<Scalar> = Default::default();
let mut mu: Vec<Scalar> = Default::default();
let mut o_lambda: Vec<Scalar> = Default::default();
let mut lambda: Vec<Scalar> = Default::default();
let mut r_k_vec: Vec<Scalar> = Default::default();
let mut kappa_k_vec: Vec<G2Projective> = Default::default();
let mut sign_lk_prime_vec: Vec<Signature> = Default::default();
@@ -131,10 +118,10 @@ impl Wallet {
aa.push(aa_k);
// evaluate the pseudorandom functions
let ss_k = pseudorandom_fgv(&grparams, self.v(), self.l() + k);
let ss_k = pseudorandom_f_delta_v(&grparams, self.v(), self.l() + k);
ss.push(ss_k);
let tt_k =
grparams.gen1() * sk_user.sk + pseudorandom_fgt(&grparams, self.t(), self.l() + k) * rr_k;
grparams.gen1() * sk_user.sk + pseudorandom_f_g_v(&grparams, self.v(), self.l() + k) * rr_k;
tt.push(tt_k);
// compute values mu, o_mu, lambda, o_lambda
@@ -146,14 +133,6 @@ impl Wallet {
let o_mu_k = ((o_a_k + o_c) * mu_k).neg();
o_mu.push(o_mu_k);
let lambda_k = (self.t() + Scalar::from(self.l() + k) + Scalar::from(1))
.invert()
.unwrap();
lambda.push(lambda_k);
let o_lambda_k = ((o_a_k + o_d) * lambda_k).neg();
o_lambda.push(o_lambda_k);
// parse the signature associated with value l+k
let sign_lk = params.get_sign_by_idx(self.l() + k)?;
// randomise the signature associated with value l+k
@@ -162,8 +141,8 @@ impl Wallet {
r_k_vec.push(r_k);
// compute kappa_k
let kappa_k = grparams.gen2() * r_k
+ params.pkRP().alpha
+ params.pkRP().beta * Scalar::from(self.l() + k);
+ params.pk_rp().alpha
+ params.pk_rp().beta * Scalar::from(self.l() + k);
kappa_k_vec.push(kappa_k);
}
@@ -172,7 +151,6 @@ impl Wallet {
let spend_instance = SpendInstance {
kappa,
cc,
dd,
aa: aa.clone(),
ss: ss.clone(),
tt: tt.clone(),
@@ -182,13 +160,10 @@ impl Wallet {
attributes,
r: sign_blinding_factor,
o_c,
o_d,
lk,
o_a,
mu,
lambda,
o_mu,
o_lambda,
r_k: r_k_vec,
};
let zk_proof = SpendProof::construct(
@@ -210,7 +185,6 @@ impl Wallet {
kappa_k: kappa_k_vec.clone(),
sig_lk: sign_lk_prime_vec,
cc,
dd,
zk_proof,
vv: spend_vv,
};
@@ -229,13 +203,13 @@ impl Wallet {
}
}
pub fn pseudorandom_fgv(params: &GroupParameters, v: Scalar, l: u64) -> G1Projective {
pub fn pseudorandom_f_delta_v(params: &GroupParameters, v: Scalar, l: u64) -> G1Projective {
let pow = (v + Scalar::from(l) + Scalar::from(1)).invert().unwrap();
params.gen1() * pow
params.delta() * pow
}
pub fn pseudorandom_fgt(params: &GroupParameters, t: Scalar, l: u64) -> G1Projective {
let pow = (t + Scalar::from(l) + Scalar::from(1)).invert().unwrap();
pub fn pseudorandom_f_g_v(params: &GroupParameters, v: Scalar, l: u64) -> G1Projective {
let pow = (v + Scalar::from(l) + Scalar::from(1)).invert().unwrap();
params.gen1() * pow
}
@@ -270,7 +244,6 @@ pub struct Payment {
pub kappa_k: Vec<G2Projective>,
pub sig_lk: Vec<Signature>,
pub cc: G1Projective,
pub dd: G1Projective,
pub zk_proof: SpendProof,
pub vv: u64,
}
@@ -331,7 +304,6 @@ impl Payment {
kappa: self.kappa,
aa: self.aa.clone(),
cc: self.cc,
dd: self.dd,
ss: self.ss.clone(),
tt: self.tt.clone(),
kappa_k: self.kappa_k.clone(),
@@ -2,7 +2,6 @@ use std::collections::HashMap;
use bls12_381::{G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, Scalar};
use ff::Field;
use group::{Curve, GroupEncoding};
use rand::thread_rng;
use crate::error::{CompactEcashError, Result};
@@ -17,6 +16,8 @@ pub struct GroupParameters {
g2: G2Affine,
/// Additional generators of the G1 group
gammas: Vec<G1Projective>,
// Additional generator of the G1 group
delta: G1Projective,
/// Precomputed G2 generator used for the miller loop
_g2_prepared_miller: G2Prepared,
}
@@ -27,10 +28,13 @@ impl GroupParameters {
.map(|i| hash_g1(format!("gamma{}", i)))
.collect();
let delta = hash_g1("delta");
Ok(GroupParameters {
g1: G1Affine::generator(),
g2: G2Affine::generator(),
gammas,
delta,
_g2_prepared_miller: G2Prepared::from(G2Affine::generator()),
})
}
@@ -55,9 +59,7 @@ impl GroupParameters {
self.gammas.get(2)
}
pub(crate) fn gamma3(&self) -> Option<&G1Projective> {
self.gammas.get(3)
}
pub(crate) fn delta(&self) -> &G1Projective { &self.delta }
pub fn random_scalar(&self) -> Scalar {
// lazily-initialized thread-local random number generator, seeded by the system
@@ -99,7 +101,7 @@ pub struct Parameters {
/// group parameters
grp: GroupParameters,
/// Public Key for range proof verification
pkRP: PublicKeyRP,
pk_rp: PublicKeyRP,
/// Max value of wallet
L: u64,
/// list of signatures for values l in [0, L]
@@ -110,8 +112,8 @@ impl Parameters {
pub fn grp(&self) -> &GroupParameters {
&self.grp
}
pub fn pkRP(&self) -> &PublicKeyRP {
&self.pkRP
pub fn pk_rp(&self) -> &PublicKeyRP {
&self.pk_rp
}
pub fn L(&self) -> u64 {
self.L
@@ -137,8 +139,8 @@ pub fn setup(L: u64) -> Parameters {
let grp = GroupParameters::new().unwrap();
let x = grp.random_scalar();
let y = grp.random_scalar();
let skRP = SecretKeyRP { x, y };
let pkRP = skRP.public_key(&grp);
let sk_rp = SecretKeyRP { x, y };
let pk_rp = sk_rp.public_key(&grp);
let mut signs = HashMap::new();
for l in 0..L {
let r = grp.random_scalar();
@@ -153,7 +155,7 @@ pub fn setup(L: u64) -> Parameters {
}
Parameters {
grp,
pkRP,
pk_rp,
L,
signs,
}
@@ -6,9 +6,8 @@ use crate::proofs::proof_withdrawal::{
WithdrawalReqInstance, WithdrawalReqProof, WithdrawalReqWitness,
};
use crate::scheme::keygen::{PublicKeyUser, SecretKeyAuth, SecretKeyUser, VerificationKeyAuth};
use crate::scheme::keygen::ttp_keygen;
use crate::scheme::PartialWallet;
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::scheme::setup::GroupParameters;
use crate::utils::{check_bilinear_pairing, hash_g1};
use crate::utils::{BlindedSignature, Signature};
@@ -24,7 +23,6 @@ pub struct RequestInfo {
com_opening: Scalar,
pc_coms_openings: Vec<Scalar>,
v: Scalar,
t: Scalar,
}
impl RequestInfo {
@@ -40,9 +38,6 @@ impl RequestInfo {
pub fn get_v(&self) -> Scalar {
self.v
}
pub fn get_t(&self) -> Scalar {
self.t
}
}
pub fn withdrawal_request(
@@ -50,9 +45,8 @@ pub fn withdrawal_request(
sk_user: &SecretKeyUser,
) -> Result<(WithdrawalRequest, RequestInfo)> {
let v = params.random_scalar();
let t = params.random_scalar();
let attributes = vec![sk_user.sk, v, t];
let attributes = vec![sk_user.sk, v];
let gammas = params.gammas();
let com_opening = params.random_scalar();
let com = params.gen1() * com_opening
@@ -105,7 +99,6 @@ pub fn withdrawal_request(
com_opening,
pc_coms_openings: pc_coms_openings.clone(),
v,
t,
};
Ok((req, req_info))
@@ -176,7 +169,7 @@ pub fn issue_verify(
let unblinded_c = c - blinding_removers;
let attr = vec![sk_user.sk, req_info.v, req_info.t];
let attr = vec![sk_user.sk, req_info.v];
let signed_attributes = attr
.iter()
@@ -203,7 +196,3 @@ pub fn issue_verify(
})
}
#[cfg(test)]
mod tests {
use super::*;
}
@@ -1,18 +1,16 @@
use itertools::izip;
use crate::error::CompactEcashError;
use crate::scheme::{PartialWallet, Payment, pseudorandom_fgt};
use crate::scheme::aggregation::{
aggregate_signature_shares, aggregate_verification_keys, aggregate_wallets,
aggregate_verification_keys, aggregate_wallets,
};
use crate::scheme::identify::identify;
use crate::scheme::keygen::{
generate_keypair_user, PublicKeyUser, SecretKeyUser, ttp_keygen, VerificationKeyAuth,
generate_keypair_user, ttp_keygen, VerificationKeyAuth,
};
use crate::scheme::PartialWallet;
use crate::scheme::PayInfo;
use crate::scheme::setup::{GroupParameters, Parameters, setup};
use crate::scheme::setup::setup;
use crate::scheme::withdrawal::{issue_verify, issue_wallet, withdrawal_request};
use crate::utils::{hash_to_scalar, SignatureShare};
#[test]
fn main() -> Result<(), CompactEcashError> {
@@ -62,7 +60,7 @@ fn main() -> Result<(), CompactEcashError> {
let pay_info = PayInfo { info: [6u8; 32] };
let spend_vv = 1;
let (payment, upd_wallet) = aggr_wallet.spend(
let (payment, _) = aggr_wallet.spend(
&params,
&verification_key,
&user_keypair.secret_key(),