Update for compact e-cash - remove requirement for security tag
This commit is contained in:
@@ -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(¶ms, &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(
|
||||
¶ms,
|
||||
&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(
|
||||
¶ms,
|
||||
&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(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&user_keypair.secret_key(),
|
||||
|
||||
Reference in New Issue
Block a user