Update get range proof signature function to return an error

This commit is contained in:
aniampio
2022-04-19 16:55:57 +03:00
committed by durch
parent 5f545675e1
commit cec35ee4d0
26 changed files with 353 additions and 303 deletions
+3
View File
@@ -25,6 +25,9 @@ pub enum CompactEcashError {
#[error("Spend Verification related error: {0}")]
Spend(String),
#[error("ZKP Proof related error: {0}")]
RangeProofOutOfBound(String),
#[error("Tried to deserialize {object} with bytes of invalid length. Expected {actual} < {} or {modulus_target} % {modulus} == 0")]
DeserializationInvalidLength {
actual: usize,
+7 -7
View File
@@ -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 sha2::Sha256;
@@ -20,10 +20,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 +51,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());
@@ -5,7 +5,7 @@ use bls12_381::{G1Projective, G2Projective, Scalar};
use group::{Curve, Group, GroupEncoding};
use crate::error::{CompactEcashError, Result};
use crate::proofs::{ChallengeDigest, compute_challenge, produce_response, produce_responses};
use crate::proofs::{compute_challenge, produce_response, produce_responses, ChallengeDigest};
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::utils::{try_deserialize_g1_projective, try_deserialize_g2_projective};
@@ -14,11 +14,11 @@ use crate::utils::{try_deserialize_g1_projective, try_deserialize_g2_projective}
#[cfg_attr(test, derive(PartialEq))]
pub struct SpendInstance {
pub kappa: G2Projective,
pub A: G1Projective,
pub C: G1Projective,
pub D: G1Projective,
pub S: G1Projective,
pub T: G1Projective,
pub aa: G1Projective,
pub cc: G1Projective,
pub dd: G1Projective,
pub ss: G1Projective,
pub tt: G1Projective,
pub kappa_l: G2Projective,
}
@@ -41,29 +41,29 @@ impl TryFrom<&[u8]> for SpendInstance {
&kappa_bytes,
CompactEcashError::Deserialization("Failed to deserialize kappa".to_string()),
)?;
let A_bytes = bytes[96..144].try_into().unwrap();
let A = try_deserialize_g1_projective(
&A_bytes,
let aa_bytes = bytes[96..144].try_into().unwrap();
let aa = try_deserialize_g1_projective(
&aa_bytes,
CompactEcashError::Deserialization("Failed to deserialize A".to_string()),
)?;
let C_bytes = bytes[144..192].try_into().unwrap();
let C = try_deserialize_g1_projective(
&C_bytes,
let cc_bytes = bytes[144..192].try_into().unwrap();
let cc = try_deserialize_g1_projective(
&cc_bytes,
CompactEcashError::Deserialization("Failed to deserialize C".to_string()),
)?;
let D_bytes = bytes[192..240].try_into().unwrap();
let D = try_deserialize_g1_projective(
&D_bytes,
let dd_bytes = bytes[192..240].try_into().unwrap();
let dd = try_deserialize_g1_projective(
&dd_bytes,
CompactEcashError::Deserialization("Failed to deserialize D".to_string()),
)?;
let S_bytes = bytes[240..288].try_into().unwrap();
let S = try_deserialize_g1_projective(
&S_bytes,
let ss_bytes = bytes[240..288].try_into().unwrap();
let ss = try_deserialize_g1_projective(
&ss_bytes,
CompactEcashError::Deserialization("Failed to deserialize S".to_string()),
)?;
let T_bytes = bytes[288..336].try_into().unwrap();
let T = try_deserialize_g1_projective(
&T_bytes,
let tt_bytes = bytes[288..336].try_into().unwrap();
let tt = try_deserialize_g1_projective(
&tt_bytes,
CompactEcashError::Deserialization("Failed to deserialize T".to_string()),
)?;
let kappa_l_bytes = bytes[336..432].try_into().unwrap();
@@ -74,11 +74,11 @@ impl TryFrom<&[u8]> for SpendInstance {
Ok(SpendInstance {
kappa,
A,
C,
D,
S,
T,
aa,
cc,
dd,
ss,
tt,
kappa_l,
})
}
@@ -88,11 +88,11 @@ impl SpendInstance {
pub(crate) fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::with_capacity(2 * 96 + 5 * 48);
bytes.extend_from_slice(self.kappa.to_bytes().as_ref());
bytes.extend_from_slice(self.A.to_bytes().as_ref());
bytes.extend_from_slice(self.C.to_bytes().as_ref());
bytes.extend_from_slice(self.D.to_bytes().as_ref());
bytes.extend_from_slice(self.S.to_bytes().as_ref());
bytes.extend_from_slice(self.T.to_bytes().as_ref());
bytes.extend_from_slice(self.aa.to_bytes().as_ref());
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.to_bytes().as_ref());
bytes.extend_from_slice(self.tt.to_bytes().as_ref());
bytes.extend_from_slice(self.kappa_l.to_bytes().as_ref());
bytes
}
@@ -136,7 +136,7 @@ impl SpendProof {
instance: &SpendInstance,
witness: &SpendWitness,
verification_key: &VerificationKeyAuth,
R: Scalar,
rr: Scalar,
) -> Self {
let grparams = params.grp();
// generate random values to replace each witness
@@ -167,21 +167,19 @@ impl SpendProof {
let zkcm_kappa = grparams.gen2() * r_r
+ verification_key.alpha
+ r_attributes
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(attr, beta_i)| beta_i * attr)
.sum::<G2Projective>();
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(attr, beta_i)| beta_i * attr)
.sum::<G2Projective>();
let zkcm_A = g1 * r_o_a + gamma1 * r_l;
let zkcm_C = g1 * r_o_c + gamma1 * r_v;
let zkcm_D = g1 * r_o_d + gamma1 * r_t;
let zkcm_S = g1 * r_mu;
let zkcm_gamma11 = (instance.A + instance.C + gamma1) * r_mu + g1 * r_o_mu;
let zkcm_T = g1 * r_sk + (g1 * R) * r_lambda;
let zkcm_gamma12 = (instance.A + instance.D + gamma1) * r_lambda + g1 * r_o_lambda;
let zkcm_kappa_l = grparams.gen2() * r_r_l
+ params.pkRP().alpha
+ params.pkRP().beta * r_l;
let zkcm_aa = g1 * r_o_a + gamma1 * r_l;
let zkcm_cc = g1 * r_o_c + gamma1 * r_v;
let zkcm_dd = g1 * r_o_d + gamma1 * r_t;
let zkcm_ss = g1 * r_mu;
let zkcm_gamma11 = (instance.aa + instance.cc + gamma1) * r_mu + g1 * r_o_mu;
let zkcm_tt = g1 * r_sk + (g1 * rr) * r_lambda;
let zkcm_gamma12 = (instance.aa + instance.dd + gamma1) * r_lambda + g1 * r_o_lambda;
let zkcm_kappa_l = grparams.gen2() * r_r_l + params.pkRP().alpha + params.pkRP().beta * r_l;
// compute the challenge
let challenge = compute_challenge::<ChallengeDigest, _, _>(
@@ -191,15 +189,15 @@ impl SpendProof {
.chain(beta2_bytes.iter().map(|b| b.as_ref()))
.chain(std::iter::once(instance.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_kappa.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_A.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_C.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_D.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_S.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_aa.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(std::iter::once(zkcm_ss.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_kappa_l.to_bytes().as_ref()))
.chain(std::iter::once(
zkcm_gamma11.to_affine().to_bytes().as_ref(),
))
.chain(std::iter::once(zkcm_T.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_tt.to_bytes().as_ref()))
.chain(std::iter::once(
zkcm_gamma12.to_affine().to_bytes().as_ref(),
)),
@@ -243,7 +241,7 @@ impl SpendProof {
params: &Parameters,
instance: &SpendInstance,
verification_key: &VerificationKeyAuth,
R: Scalar,
rr: Scalar,
) -> bool {
let grparams = params.grp();
let g1 = *grparams.gen1();
@@ -259,28 +257,28 @@ impl SpendProof {
+ grparams.gen2() * self.response_r
+ verification_key.alpha * (Scalar::one() - self.challenge)
+ self
.response_attributes
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(attr, beta_i)| beta_i * attr)
.sum::<G2Projective>();
.response_attributes
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(attr, beta_i)| beta_i * attr)
.sum::<G2Projective>();
let zkcm_A =
g1 * self.response_o_a + gamma1 * self.response_l + instance.A * self.challenge;
let zkcm_C = g1 * self.response_o_c
let zkcm_aa =
g1 * self.response_o_a + gamma1 * self.response_l + instance.aa * self.challenge;
let zkcm_cc = g1 * self.response_o_c
+ gamma1 * self.response_attributes[1]
+ instance.C * self.challenge;
let zkcm_D = g1 * self.response_o_d
+ instance.cc * self.challenge;
let zkcm_dd = g1 * self.response_o_d
+ gamma1 * self.response_attributes[2]
+ instance.D * self.challenge;
let zkcm_S = g1 * self.response_mu + instance.S * self.challenge;
let zkcm_gamma11 = (instance.A + instance.C + gamma1) * self.response_mu
+ instance.dd * self.challenge;
let zkcm_ss = g1 * self.response_mu + instance.ss * self.challenge;
let zkcm_gamma11 = (instance.aa + instance.cc + gamma1) * self.response_mu
+ g1 * self.response_o_mu
+ gamma1 * self.challenge;
let zkcm_T = g1 * self.response_attributes[0]
+ (g1 * R) * self.response_lambda
+ instance.T * self.challenge;
let zkcm_gamma12 = (instance.A + instance.D + gamma1) * self.response_lambda
let zkcm_tt = g1 * self.response_attributes[0]
+ (g1 * rr) * self.response_lambda
+ instance.tt * self.challenge;
let zkcm_gamma12 = (instance.aa + instance.dd + gamma1) * self.response_lambda
+ g1 * self.response_o_lambda
+ gamma1 * self.challenge;
@@ -297,15 +295,15 @@ impl SpendProof {
.chain(beta2_bytes.iter().map(|b| b.as_ref()))
.chain(std::iter::once(instance.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_kappa.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_A.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_C.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_D.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_S.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_aa.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(std::iter::once(zkcm_ss.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_kappa_l.to_bytes().as_ref()))
.chain(std::iter::once(
zkcm_gamma11.to_affine().to_bytes().as_ref(),
))
.chain(std::iter::once(zkcm_T.to_bytes().as_ref()))
.chain(std::iter::once(zkcm_tt.to_bytes().as_ref()))
.chain(std::iter::once(
zkcm_gamma12.to_affine().to_bytes().as_ref(),
)),
@@ -319,14 +317,14 @@ impl SpendProof {
mod tests {
use bls12_381::{G1Projective, G2Projective, Scalar};
use group::Curve;
use rand::thread_rng;
use rand::{thread_rng, Rng};
use crate::proofs::proof_spend::{SpendInstance, SpendProof, SpendWitness};
use crate::scheme::{pseudorandom_fgt, pseudorandom_fgv};
use crate::scheme::aggregation::aggregate_verification_keys;
use crate::scheme::keygen::{PublicKeyUser, ttp_keygen, VerificationKeyAuth};
use crate::scheme::keygen::{ttp_keygen, PublicKeyUser, VerificationKeyAuth};
use crate::scheme::setup::{setup, GroupParameters};
use crate::scheme::PayInfo;
use crate::scheme::setup::{GroupParameters, setup};
use crate::scheme::{pseudorandom_fgt, pseudorandom_fgv};
use crate::utils::hash_to_scalar;
#[test]
@@ -350,6 +348,7 @@ mod tests {
let v = grparams.random_scalar();
let t = grparams.random_scalar();
let attributes = vec![sk, v, t];
// the below value must be from range 0 to params.L()
let l = 5;
let gamma1 = *grparams.gamma1();
let g1 = *grparams.gen1();
@@ -358,27 +357,27 @@ mod tests {
let kappa = grparams.gen2() * r
+ verification_key.alpha
+ attributes
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
.sum::<G2Projective>();
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
.sum::<G2Projective>();
let o_a = grparams.random_scalar();
let o_c = grparams.random_scalar();
let o_d = grparams.random_scalar();
// compute commitments A, C, D
let A = g1 * o_a + gamma1 * Scalar::from(l);
let C = g1 * o_c + gamma1 * v;
let D = g1 * o_d + gamma1 * t;
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 payInfo = PayInfo { info: [37u8; 32] };
let R = hash_to_scalar(payInfo.info);
let pay_info = PayInfo { info: [37u8; 32] };
let rr = hash_to_scalar(pay_info.info);
// evaluate the pseudorandom functions
let S = pseudorandom_fgv(&grparams, v, l);
let T = g1 * sk + pseudorandom_fgt(&grparams, t, l) * R;
let ss = pseudorandom_fgv(&grparams, v, l);
let tt = g1 * sk + pseudorandom_fgt(&grparams, t, l) * rr;
// compute values mu, o_mu, lambda, o_lambda
let mu: Scalar = (v + Scalar::from(l) + Scalar::from(1)).invert().unwrap();
@@ -387,21 +386,20 @@ mod tests {
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);
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);
// compute kappa_l
let kappa_l = grparams.gen2() * r_l
+ params.pkRP().alpha
+ params.pkRP().beta * Scalar::from(l);
let kappa_l =
grparams.gen2() * r_l + params.pkRP().alpha + params.pkRP().beta * Scalar::from(l);
let instance = SpendInstance {
kappa,
A,
C,
D,
S,
T,
aa,
cc,
dd,
ss,
tt,
kappa_l,
};
@@ -418,7 +416,7 @@ mod tests {
o_mu,
o_lambda,
};
let zk_proof = SpendProof::construct(&params, &instance, &witness, &verification_key, R);
assert!(zk_proof.verify(&params, &instance, &verification_key, R))
let zk_proof = SpendProof::construct(&params, &instance, &witness, &verification_key, rr);
assert!(zk_proof.verify(&params, &instance, &verification_key, rr))
}
}
@@ -5,7 +5,7 @@ use group::GroupEncoding;
use itertools::izip;
use crate::error::{CompactEcashError, Result};
use crate::proofs::{ChallengeDigest, compute_challenge, produce_response, produce_responses};
use crate::proofs::{compute_challenge, produce_response, produce_responses, ChallengeDigest};
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()
@@ -192,26 +192,30 @@ impl WithdrawalReqProof {
}
}
pub(crate) fn verify(&self, params: &GroupParameters, instance: &WithdrawalReqInstance) -> bool {
pub(crate) fn verify(
&self,
params: &GroupParameters,
instance: &WithdrawalReqInstance,
) -> bool {
// recompute zk commitments for each instance
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];
@@ -288,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, PartialSignature, perform_lagrangian_interpolation_at_origin,
check_bilinear_pairing, perform_lagrangian_interpolation_at_origin, PartialSignature,
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() {
@@ -145,9 +145,9 @@ pub fn aggregate_signatures(
pub fn aggregate_wallets(
params: &GroupParameters,
verification_key: &VerificationKeyAuth,
skUser: &SecretKeyUser,
sk_user: &SecretKeyUser,
wallets: &[PartialWallet],
reqInfo: &RequestInfo,
req_info: &RequestInfo,
) -> Result<Wallet> {
// Aggregate partial wallets
let signature_shares: Vec<SignatureShare> = wallets
@@ -156,14 +156,14 @@ pub fn aggregate_wallets(
.map(|(idx, wallet)| SignatureShare::new(*wallet.signature(), (idx + 1) as u64))
.collect();
let attributes = vec![skUser.sk, reqInfo.get_v(), reqInfo.get_t()];
let attributes = vec![sk_user.sk, req_info.get_v(), req_info.get_t()];
let aggregated_signature =
aggregate_signature_shares(&params, &verification_key, &attributes, &signature_shares)?;
Ok(Wallet {
sig: aggregated_signature,
v: reqInfo.get_v(),
t: reqInfo.get_t(),
v: req_info.get_v(),
t: req_info.get_t(),
l: Cell::new(0),
})
}
@@ -2,11 +2,8 @@ use crate::error::Result;
use crate::scheme::keygen::PublicKeyUser;
use crate::scheme::Payment;
pub fn identify(
pay1: Payment,
pay2: Payment,
) -> Result<PublicKeyUser> {
pub fn identify(pay1: Payment, pay2: Payment) -> Result<PublicKeyUser> {
// TODO: We should include here the check for S and payInfo
let pkUser = (pay2.T * pay1.R - pay1.T * pay2.R) * ((pay1.R - pay2.R).invert().unwrap());
Ok(PublicKeyUser { pk: pkUser })
let pk_user = (pay2.tt * pay1.rr - pay1.tt * pay2.rr) * ((pay1.rr - pay2.rr).invert().unwrap());
Ok(PublicKeyUser { pk: pk_user })
}
@@ -11,11 +11,11 @@ use crate::error::{CompactEcashError, Result};
use crate::scheme::aggregation::aggregate_verification_keys;
use crate::scheme::setup::GroupParameters;
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 {
@@ -242,13 +242,13 @@ impl<'a> Mul<Scalar> for &'a VerificationKeyAuth {
}
impl<T> Sum<T> for VerificationKeyAuth
where
T: Borrow<VerificationKeyAuth>,
where
T: Borrow<VerificationKeyAuth>,
{
#[inline]
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item=T>,
where
I: Iterator<Item = T>,
{
let mut peekable = iter.peekable();
let head_attributes = match peekable.peek() {
@@ -440,4 +440,3 @@ pub fn ttp_keygen(
Ok(keypairs)
}
+68 -45
View File
@@ -5,14 +5,14 @@ use std::convert::TryInto;
use bls12_381::{G1Projective, G2Prepared, G2Projective, Scalar};
use group::{Curve, Group};
use crate::Attribute;
use crate::error::{CompactEcashError, Result};
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, try_deserialize_g1_projective, Signature, SignerIndex,
};
use crate::Attribute;
pub mod aggregation;
pub mod identify;
@@ -71,8 +71,8 @@ impl Wallet {
&self,
params: &Parameters,
verification_key: &VerificationKeyAuth,
skUser: &SecretKeyUser,
payInfo: &PayInfo,
sk_user: &SecretKeyUser,
pay_info: &PayInfo,
) -> Result<(Payment, &Self)> {
if self.l() > params.L() {
return Err(CompactEcashError::Spend(
@@ -84,7 +84,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![skUser.sk, self.v(), self.t()];
let attributes = vec![sk_user.sk, self.v(), self.t()];
// compute kappa
let kappa = compute_kappa(
&grparams,
@@ -99,16 +99,17 @@ impl Wallet {
let o_d = grparams.random_scalar();
// compute commitments A, C, D
let A = grparams.gen1() * o_a + grparams.gamma1() * Scalar::from(self.l());
let C = grparams.gen1() * o_c + grparams.gamma1() * self.v();
let D = grparams.gen1() * o_d + grparams.gamma1() * self.t();
let aa = grparams.gen1() * o_a + grparams.gamma1() * Scalar::from(self.l());
let cc = grparams.gen1() * o_c + grparams.gamma1() * self.v();
let dd = grparams.gen1() * o_d + grparams.gamma1() * self.t();
// compute hash of the payment info
let R = hash_to_scalar(payInfo.info);
let rr = hash_to_scalar(pay_info.info);
// evaluate the pseudorandom functions
let S = pseudorandom_fgv(&grparams, self.v(), self.l());
let T = grparams.gen1() * skUser.sk + pseudorandom_fgt(&grparams, self.t(), self.l()) * R;
let ss = pseudorandom_fgv(&grparams, self.v(), self.l());
let tt =
grparams.gen1() * sk_user.sk + pseudorandom_fgt(&grparams, self.t(), self.l()) * rr;
// compute values mu, o_mu, lambda, o_lambda
let mu: Scalar = (self.v() + Scalar::from(self.l()) + Scalar::from(1))
@@ -121,7 +122,7 @@ impl Wallet {
let o_lambda = ((o_a + o_d) * lambda).neg();
// parse the signature associated with value l
let sign_l = params.get_sign_by_idx(self.l());
let sign_l = params.get_sign_by_idx(self.l())?;
// randomise the signature associated with value l
let (sign_l_prime, sign_l_blinding_factor) = sign_l.randomise(grparams);
// compute kappa_l
@@ -130,16 +131,16 @@ impl Wallet {
+ params.pkRP().beta * Scalar::from(self.l());
// construct the zkp proof
let spendInstance = SpendInstance {
let spend_instance = SpendInstance {
kappa,
A,
C,
D,
S,
T,
aa,
cc,
dd,
ss,
tt,
kappa_l,
};
let spendWitness = SpendWitness {
let spend_witness = SpendWitness {
attributes,
r: sign_blinding_factor,
r_l: sign_l_blinding_factor,
@@ -152,19 +153,24 @@ impl Wallet {
o_mu,
o_lambda,
};
let zk_proof =
SpendProof::construct(&params, &spendInstance, &spendWitness, &verification_key, R);
let zk_proof = SpendProof::construct(
&params,
&spend_instance,
&spend_witness,
&verification_key,
rr,
);
// output pay and updated wallet
let pay = Payment {
kappa,
sig: signature_prime,
S,
T,
A,
C,
D,
R,
ss,
tt,
aa,
cc,
dd,
rr,
kappa_l,
sig_l: sign_l_prime,
zk_proof,
@@ -195,10 +201,10 @@ pub fn compute_kappa(
params.gen2() * blinding_factor
+ verification_key.alpha
+ attributes
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
.sum::<G2Projective>()
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
.sum::<G2Projective>()
}
pub struct PayInfo {
@@ -209,12 +215,12 @@ pub struct PayInfo {
pub struct Payment {
pub kappa: G2Projective,
pub sig: Signature,
pub S: G1Projective,
pub T: G1Projective,
pub A: G1Projective,
pub C: G1Projective,
pub D: G1Projective,
pub R: Scalar,
pub ss: G1Projective,
pub tt: G1Projective,
pub aa: G1Projective,
pub cc: G1Projective,
pub dd: G1Projective,
pub rr: Scalar,
pub kappa_l: G2Projective,
pub sig_l: Signature,
pub zk_proof: SpendProof,
@@ -225,7 +231,7 @@ impl Payment {
&self,
params: &Parameters,
verification_key: &VerificationKeyAuth,
payinfo: &PayInfo,
pay_info: &PayInfo,
) -> Result<bool> {
if bool::from(self.sig.0.is_identity()) {
return Err(CompactEcashError::Spend(
@@ -244,8 +250,25 @@ impl Payment {
));
}
if bool::from(self.sig_l.0.is_identity()) {
return Err(CompactEcashError::Spend(
"The element h of the signature on l equals the identity".to_string(),
));
}
if !check_bilinear_pairing(
&self.sig_l.0.to_affine(),
&G2Prepared::from(self.kappa_l.to_affine()),
&self.sig_l.1.to_affine(),
params.grp().prepared_miller_g2(),
) {
return Err(CompactEcashError::Spend(
"The bilinear check for kappa_l failed".to_string(),
));
}
// verify integrity of R
if !(self.R == hash_to_scalar(payinfo.info)) {
if !(self.rr == hash_to_scalar(pay_info.info)) {
return Err(CompactEcashError::Spend(
"Integrity of R does not hold".to_string(),
));
@@ -256,17 +279,17 @@ impl Payment {
// verify the zk proof
let instance = SpendInstance {
kappa: self.kappa,
A: self.A,
C: self.C,
D: self.D,
S: self.S,
T: self.T,
aa: self.aa,
cc: self.cc,
dd: self.dd,
ss: self.ss,
tt: self.tt,
kappa_l: self.kappa_l,
};
if !self
.zk_proof
.verify(&params, &instance, &verification_key, self.R)
.verify(&params, &instance, &verification_key, self.rr)
{
return Err(CompactEcashError::Spend(
"ZkProof verification failed".to_string(),
+36 -13
View File
@@ -5,7 +5,7 @@ use ff::Field;
use group::{Curve, GroupEncoding};
use rand::thread_rng;
use crate::error::Result;
use crate::error::{CompactEcashError, Result};
use crate::utils::{hash_g1, Signature};
const ATTRIBUTES_LEN: usize = 3;
@@ -28,13 +28,11 @@ impl GroupParameters {
.map(|i| hash_g1(format!("gamma{}", i)))
.collect();
Ok(GroupParameters {
g1: G1Affine::generator(),
g2: G2Affine::generator(),
gammas,
_g2_prepared_miller: G2Prepared::from(G2Affine::generator()),
})
}
@@ -77,7 +75,6 @@ impl GroupParameters {
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct SecretKeyRP {
pub(crate) x: Scalar,
@@ -86,7 +83,10 @@ pub struct SecretKeyRP {
impl SecretKeyRP {
pub fn public_key(&self, params: &GroupParameters) -> PublicKeyRP {
PublicKeyRP { alpha: params.gen2() * self.x, beta: params.gen2() * self.y }
PublicKeyRP {
alpha: params.gen2() * self.x,
beta: params.gen2() * self.y,
}
}
}
@@ -108,11 +108,30 @@ pub struct Parameters {
}
impl Parameters {
pub fn grp(&self) -> &GroupParameters { &self.grp }
pub fn pkRP(&self) -> &PublicKeyRP { &self.pkRP }
pub fn L(&self) -> u64 { self.L }
pub fn signs(&self) -> &HashMap<u64, Signature> { &self.signs }
pub fn get_sign_by_idx(&self, idx: u64) -> &Signature { self.signs.get(&idx).unwrap() }
pub fn grp(&self) -> &GroupParameters {
&self.grp
}
pub fn pkRP(&self) -> &PublicKeyRP {
&self.pkRP
}
pub fn L(&self) -> u64 {
self.L
}
pub fn signs(&self) -> &HashMap<u64, Signature> {
&self.signs
}
pub fn get_sign_by_idx(&self, idx: u64) -> Result<&Signature> {
match self.signs.get(&idx) {
Some(val) => return Ok(val),
None => {
return Err(CompactEcashError::RangeProofOutOfBound(
"Cannot find the range proof signature for the given value. \
Check if the requested value is within the bound 0..L"
.to_string(),
));
}
}
}
}
pub fn setup() -> Parameters {
@@ -125,7 +144,13 @@ pub fn setup() -> Parameters {
for l in 0..MAX_COIN_VALUE {
let r = grp.random_scalar();
let h = grp.gen1() * r;
signs.insert(l, Signature { 0: h, 1: h * (x + y * Scalar::from(l)) });
signs.insert(
l,
Signature {
0: h,
1: h * (x + y * Scalar::from(l)),
},
);
}
Parameters {
grp,
@@ -134,5 +159,3 @@ pub fn setup() -> Parameters {
signs,
}
}
@@ -5,10 +5,10 @@ use crate::error::{CompactEcashError, Result};
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::keygen::{PublicKeyUser, SecretKeyAuth, SecretKeyUser, VerificationKeyAuth};
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::scheme::PartialWallet;
use crate::utils::{check_bilinear_pairing, hash_g1};
use crate::utils::{BlindedSignature, Signature};
@@ -57,10 +57,10 @@ pub fn withdrawal_request(
let com_opening = params.random_scalar();
let com = params.gen1() * com_opening
+ attributes
.iter()
.zip(gammas)
.map(|(&m, gamma)| gamma * m)
.sum::<G1Projective>();
.iter()
.zip(gammas)
.map(|(&m, gamma)| gamma * m)
.sum::<G1Projective>();
// Value h in the paper
let com_hash = hash_g1(com.to_bytes());
+21 -20
View File
@@ -1,17 +1,17 @@
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,
};
use crate::scheme::identify::identify;
use crate::scheme::keygen::{
generate_keypair_user, PublicKeyUser, SecretKeyUser, ttp_keygen, VerificationKeyAuth,
generate_keypair_user, ttp_keygen, PublicKeyUser, SecretKeyUser, VerificationKeyAuth,
};
use crate::scheme::PayInfo;
use crate::scheme::setup::{GroupParameters, Parameters, setup};
use crate::scheme::setup::{setup, GroupParameters, Parameters};
use crate::scheme::withdrawal::{issue_verify, issue_wallet, withdrawal_request};
use crate::scheme::PayInfo;
use crate::scheme::{pseudorandom_fgt, PartialWallet, Payment};
use crate::utils::{hash_to_scalar, SignatureShare};
#[test]
@@ -45,8 +45,8 @@ fn main() -> Result<(), CompactEcashError> {
wallet_blinded_signatures.iter(),
verification_keys_auth.iter()
)
.map(|(w, vk)| issue_verify(&grparams, vk, &user_keypair.secret_key(), w, &req_info).unwrap())
.collect();
.map(|(w, vk)| issue_verify(&grparams, vk, &user_keypair.secret_key(), w, &req_info).unwrap())
.collect();
// Aggregate partial wallets
let aggr_wallet = aggregate_wallets(
@@ -58,40 +58,41 @@ fn main() -> Result<(), CompactEcashError> {
)?;
// Let's try to spend some coins
let payInfo = PayInfo { info: [6u8; 32] };
let pay_info = PayInfo { info: [6u8; 32] };
let (payment, upd_wallet) = aggr_wallet.spend(
&params,
&verification_key,
&user_keypair.secret_key(),
&payInfo,
&pay_info,
)?;
assert!(payment
.spend_verify(&params, &verification_key, &payInfo)
.spend_verify(&params, &verification_key, &pay_info)
.unwrap());
// try to spend twice the same payment with different payInfo.
// try to spend twice the same payment with different payInfo
let payment1 = payment.clone();
let payInfo2 = PayInfo { info: [9u8; 32] };
let R2 = hash_to_scalar(payInfo2.info);
let pay_info2 = PayInfo { info: [9u8; 32] };
let rr2 = hash_to_scalar(pay_info2.info);
let l2 = aggr_wallet.l() - 1;
let payment2 = Payment {
kappa: payment1.kappa.clone(),
sig: payment1.sig.clone(),
S: payment1.S.clone(),
T: grparams.gen1() * user_keypair.secret_key().sk + pseudorandom_fgt(&grparams, aggr_wallet.t(), l2) * R2,
A: payment1.A.clone(),
C: payment1.C.clone(),
D: payment1.D.clone(),
R: R2,
ss: payment1.ss.clone(),
tt: grparams.gen1() * user_keypair.secret_key().sk
+ pseudorandom_fgt(&grparams, aggr_wallet.t(), l2) * rr2,
aa: payment1.aa.clone(),
cc: payment1.cc.clone(),
dd: payment1.dd.clone(),
rr: rr2,
kappa_l: payment1.kappa_l.clone(),
sig_l: payment1.sig_l.clone(),
zk_proof: payment1.zk_proof.clone(),
};
let identifiedUser = identify(payment1, payment2).unwrap();
assert_eq!(user_keypair.public_key().pk, identifiedUser.pk);
let identified_user = identify(payment1, payment2).unwrap();
assert_eq!(user_keypair.public_key().pk, identified_user.pk);
Ok(())
}
+6 -6
View File
@@ -6,10 +6,10 @@ use core::ops::Mul;
use std::convert::{TryFrom, 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::{Curve, Group};
@@ -85,9 +85,9 @@ pub(crate) fn perform_lagrangian_interpolation_at_origin<T>(
points: &[SignerIndex],
values: &[T],
) -> Result<T>
where
T: Sum,
for<'a> &'a T: Mul<Scalar, Output=T>,
where
T: Sum,
for<'a> &'a T: Mul<Scalar, Output = T>,
{
if points.is_empty() || values.is_empty() {
return Err(CompactEcashError::Interpolation(
+3 -3
View File
@@ -1,11 +1,11 @@
use bls12_381::Scalar;
mod error;
mod proofs;
mod scheme;
#[cfg(test)]
mod tests;
mod error;
mod utils;
mod traits;
mod utils;
pub type Attribute = Scalar;
pub type Attribute = Scalar;
@@ -0,0 +1 @@
@@ -0,0 +1 @@
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+1 -1
View File
@@ -2,5 +2,5 @@ pub mod aggregation;
pub mod identify;
pub mod keygen;
pub mod setup;
pub mod structure_preserving_signature;
pub mod withdrawal;
pub mod structure_preserving_signature;
+13 -6
View File
@@ -41,7 +41,9 @@ impl GroupParameters {
&self._g2_prepared_miller
}
pub(crate) fn getL(&self) -> u64 { self.L }
pub(crate) fn getL(&self) -> u64 {
self.L
}
pub(crate) fn random_scalar(&self) -> Scalar {
// lazily-initialized thread-local random number generator, seeded by the system
@@ -60,7 +62,6 @@ pub struct Parameters {
paramsAuth: ParametersAuthority,
}
impl Parameters {
pub fn new(grp: GroupParameters) -> Parameters {
let g1 = grp.gen1();
@@ -78,10 +79,16 @@ impl Parameters {
let sigma = g1 * z;
let theta = eta * z;
let sigmasUser: Vec<G1Projective> = (1..=grp.getL()).map(|i| sigma * (y * Scalar::from(i))).collect();
let thetasUser: Vec<G1Projective> = (1..=grp.getL()).map(|i| theta * (y * Scalar::from(i))).collect();
let sigmasUser: Vec<G1Projective> = (1..=grp.getL())
.map(|i| sigma * (y * Scalar::from(i)))
.collect();
let thetasUser: Vec<G1Projective> = (1..=grp.getL())
.map(|i| theta * (y * Scalar::from(i)))
.collect();
let deltasAuth: Vec<G2Projective> = (0..=grp.getL() - 1).map(|i| g2 * (y * Scalar::from(i))).collect();
let deltasAuth: Vec<G2Projective> = (0..=grp.getL() - 1)
.map(|i| g2 * (y * Scalar::from(i)))
.collect();
let etasUser: Vec<G1Projective> = vec_a.iter().map(|x| g1 * x).collect();
let mut etasAuth: Vec<G2Projective> = Default::default();
@@ -137,4 +144,4 @@ pub struct ParametersUser {
pub struct ParametersAuthority {
deltas: Vec<G2Projective>,
etas: Vec<G2Projective>,
}
}
@@ -3,8 +3,8 @@ use std::convert::TryFrom;
use bls12_381::{G1Projective, G2Projective, Scalar};
use group::Curve;
use crate::Attribute;
use crate::scheme::setup::GroupParameters;
use crate::Attribute;
#[derive(Debug, Clone)]
pub(crate) struct SPSVerificationKey {
@@ -24,13 +24,22 @@ pub(crate) struct SPSSecretKey {
}
impl SPSSecretKey {
pub fn z(&self) -> Scalar { self.z }
pub fn y(&self) -> Scalar { self.y }
pub fn z(&self) -> Scalar {
self.z
}
pub fn y(&self) -> Scalar {
self.y
}
pub fn sign(&self, grparams: GroupParameters, attributes: Vec<Attribute>) -> SPSSignature {
let r = grparams.random_scalar();
let R = grparams.gen1() * r;
let prod: Vec<Scalar> = attributes.iter().zip(self.ws.iter()).map(|(w_i, m_i)| m_i * w_i.neg()).collect();
let Z = grparams.gen1() * (self.z() - r * self.y()) + prod.iter().fold(1 | acc, x | acc * x);
let prod: Vec<Scalar> = attributes
.iter()
.zip(self.ws.iter())
.map(|(w_i, m_i)| m_i * w_i.neg())
.collect();
let Z =
grparams.gen1() * (self.z() - r * self.y()) + prod.iter().fold(1 | acc, x | acc * x);
// let sum = a.iter().fold(0, |acc, x| acc + x);
// let Z: G1Projective = grparams.gen1() * (self.z() - r * self.y())
// + attributes
@@ -76,4 +85,3 @@ impl SPSKeyPair {
}
pub struct SPSSignature {}
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+4 -4
View File
@@ -1,8 +1,8 @@
use crate::error::DivisibleEcashError;
pub trait Bytable
where
Self: Sized,
where
Self: Sized,
{
fn to_byte_vec(&self) -> Vec<u8>;
@@ -10,8 +10,8 @@ pub trait Bytable
}
pub trait Base58
where
Self: Bytable,
where
Self: Bytable,
{
fn try_from_bs58<S: AsRef<str>>(x: S) -> Result<Self, DivisibleEcashError> {
Self::try_from_byte_slice(&bs58::decode(x.as_ref()).into_vec().unwrap())
+12 -8
View File
@@ -6,10 +6,10 @@ use core::ops::Mul;
use std::convert::{TryFrom, 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::{Curve, Group};
@@ -85,9 +85,9 @@ pub(crate) fn perform_lagrangian_interpolation_at_origin<T>(
points: &[SignerIndex],
values: &[T],
) -> Result<T>
where
T: Sum,
for<'a> &'a T: Mul<Scalar, Output=T>,
where
T: Sum,
for<'a> &'a T: Mul<Scalar, Output = T>,
{
if points.is_empty() || values.is_empty() {
return Err(DivisibleEcashError::Interpolation(
@@ -221,12 +221,16 @@ impl TryFrom<&[u8]> for Signature {
let sig1 = try_deserialize_g1_projective(
sig1_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize compressed sig1".to_string()),
DivisibleEcashError::Deserialization(
"Failed to deserialize compressed sig1".to_string(),
),
)?;
let sig2 = try_deserialize_g1_projective(
sig2_bytes,
DivisibleEcashError::Deserialization("Failed to deserialize compressed sig2".to_string()),
DivisibleEcashError::Deserialization(
"Failed to deserialize compressed sig2".to_string(),
),
)?;
Ok(Signature(sig1, sig2))
-23
View File
@@ -27,31 +27,8 @@ pub use scheme::verification::prove_bandwidth_credential;
pub use scheme::verification::verify_credential;
pub use scheme::verification::Theta;
pub use scheme::BlindedSignature;
pub use scheme::issuance::blind_sign;
pub use scheme::issuance::prepare_blind_sign;
pub use scheme::issuance::BlindSignRequest;
pub use scheme::keygen::ttp_keygen;
pub use scheme::keygen::KeyPair;
pub use scheme::keygen::VerificationKey;
pub use scheme::setup::setup;
pub use scheme::setup::Parameters;
pub use scheme::verification::prove_bandwidth_credential;
pub use scheme::verification::verify_credential;
pub use scheme::verification::Theta;
pub use scheme::BlindedSignature;
pub use scheme::issuance::blind_sign;
pub use scheme::issuance::BlindSignRequest;
pub use scheme::issuance::prepare_blind_sign;
pub use scheme::keygen::KeyPair;
pub use scheme::keygen::ttp_keygen;
pub use scheme::keygen::VerificationKey;
pub use scheme::setup::Parameters;
pub use scheme::setup::setup;
pub use scheme::Signature;
pub use scheme::SignatureShare;
pub use scheme::verification::prove_bandwidth_credential;
pub use scheme::verification::Theta;
pub use scheme::verification::verify_credential;
pub use traits::Base58;
pub use utils::hash_to_scalar;
+12 -12
View File
@@ -5,10 +5,9 @@ use core::ops::Neg;
use std::convert::TryFrom;
use std::convert::TryInto;
use bls12_381::{G1Affine, G2Prepared, G2Projective, multi_miller_loop, Scalar};
use bls12_381::{multi_miller_loop, G1Affine, G2Prepared, G2Projective, Scalar};
use group::{Curve, Group};
use crate::Attribute;
use crate::error::{CoconutError, Result};
use crate::proofs::ProofKappaZeta;
use crate::scheme::double_use::BlindedSerialNumber;
@@ -17,6 +16,7 @@ use crate::scheme::Signature;
use crate::scheme::VerificationKey;
use crate::traits::{Base58, Bytable};
use crate::utils::try_deserialize_g2_projective;
use crate::Attribute;
// TODO NAMING: this whole thing
// Theta
@@ -136,10 +136,10 @@ pub fn compute_kappa(
params.gen2() * blinding_factor
+ verification_key.alpha
+ private_attributes
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
.sum::<G2Projective>()
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
.sum::<G2Projective>()
}
pub fn compute_zeta(params: &Parameters, serial_number: Attribute) -> G2Projective {
@@ -296,11 +296,11 @@ pub fn verify(
) -> bool {
let kappa = (verification_key.alpha
+ public_attributes
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(m_i, b_i)| b_i * m_i)
.sum::<G2Projective>())
.to_affine();
.iter()
.zip(verification_key.beta_g2.iter())
.map(|(m_i, b_i)| b_i * m_i)
.sum::<G2Projective>())
.to_affine();
check_bilinear_pairing(
&sig.0.to_affine(),
@@ -345,7 +345,7 @@ mod tests {
serial_number,
binding_number,
)
.unwrap();
.unwrap();
let bytes = theta.to_bytes();
assert_eq!(Theta::try_from(bytes.as_slice()).unwrap(), theta);