Run cargo fmt
This commit is contained in:
@@ -22,8 +22,10 @@ use client_core::client::topology_control::{
|
||||
TopologyAccessor, TopologyRefresher, TopologyRefresherConfig,
|
||||
};
|
||||
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
|
||||
use coconut_interface::{Credential, hash_to_scalar, Parameters};
|
||||
use credentials::bandwidth::{prepare_for_spending, BandwidthVoucherAttributes, BANDWIDTH_VALUE, TOTAL_ATTRIBUTES};
|
||||
use coconut_interface::{hash_to_scalar, Credential, Parameters};
|
||||
use credentials::bandwidth::{
|
||||
prepare_for_spending, BandwidthVoucherAttributes, BANDWIDTH_VALUE, TOTAL_ATTRIBUTES,
|
||||
};
|
||||
use credentials::obtain_aggregate_verification_key;
|
||||
use crypto::asymmetric::identity;
|
||||
use futures::channel::mpsc;
|
||||
@@ -174,15 +176,15 @@ impl NymClient {
|
||||
.expect("could not obtain aggregate verification key of validators");
|
||||
|
||||
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
|
||||
let bandwidth_credential_attributes = BandwidthVoucherAttributes{
|
||||
serial_number : params.random_scalar(),
|
||||
binding_number : params.random_scalar(),
|
||||
voucher_value : hash_to_scalar(BANDWIDTH_VALUE.to_be_bytes()),
|
||||
voucher_info : hash_to_scalar(String::from("BandwidthVoucher").as_bytes()),
|
||||
let bandwidth_credential_attributes = BandwidthVoucherAttributes {
|
||||
serial_number: params.random_scalar(),
|
||||
binding_number: params.random_scalar(),
|
||||
voucher_value: hash_to_scalar(BANDWIDTH_VALUE.to_be_bytes()),
|
||||
voucher_info: hash_to_scalar(String::from("BandwidthVoucher").as_bytes()),
|
||||
};
|
||||
|
||||
let bandwidth_credential = credentials::bandwidth::obtain_signature(
|
||||
¶ms,
|
||||
¶ms,
|
||||
&bandwidth_credential_attributes,
|
||||
&self.config.get_base().get_validator_api_endpoints(),
|
||||
&verification_key,
|
||||
|
||||
@@ -6,9 +6,11 @@ use crate::commands::override_config;
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use client_core::client::key_manager::KeyManager;
|
||||
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
|
||||
use coconut_interface::{Credential, hash_to_scalar, Parameters};
|
||||
use coconut_interface::{hash_to_scalar, Credential, Parameters};
|
||||
use config::NymConfig;
|
||||
use credentials::bandwidth::{prepare_for_spending, BandwidthVoucherAttributes, BANDWIDTH_VALUE, TOTAL_ATTRIBUTES};
|
||||
use credentials::bandwidth::{
|
||||
prepare_for_spending, BandwidthVoucherAttributes, BANDWIDTH_VALUE, TOTAL_ATTRIBUTES,
|
||||
};
|
||||
use credentials::obtain_aggregate_verification_key;
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
use gateway_client::GatewayClient;
|
||||
@@ -68,19 +70,29 @@ async fn prepare_temporary_credential(validators: &[Url], raw_identity: &[u8]) -
|
||||
.expect("could not obtain aggregate verification key of validators");
|
||||
|
||||
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
|
||||
let bandwidth_credential_attributes = BandwidthVoucherAttributes{
|
||||
serial_number : params.random_scalar(),
|
||||
binding_number : params.random_scalar(),
|
||||
voucher_value : hash_to_scalar(BANDWIDTH_VALUE.to_be_bytes()),
|
||||
voucher_info : hash_to_scalar(String::from("BandwidthVoucher").as_bytes()),
|
||||
let bandwidth_credential_attributes = BandwidthVoucherAttributes {
|
||||
serial_number: params.random_scalar(),
|
||||
binding_number: params.random_scalar(),
|
||||
voucher_value: hash_to_scalar(BANDWIDTH_VALUE.to_be_bytes()),
|
||||
voucher_info: hash_to_scalar(String::from("BandwidthVoucher").as_bytes()),
|
||||
};
|
||||
|
||||
let bandwidth_credential = credentials::bandwidth::obtain_signature(¶ms, &bandwidth_credential_attributes, validators, &verification_key)
|
||||
.await
|
||||
.expect("could not obtain bandwidth credential");
|
||||
let bandwidth_credential = credentials::bandwidth::obtain_signature(
|
||||
¶ms,
|
||||
&bandwidth_credential_attributes,
|
||||
validators,
|
||||
&verification_key,
|
||||
)
|
||||
.await
|
||||
.expect("could not obtain bandwidth credential");
|
||||
|
||||
prepare_for_spending(raw_identity, &bandwidth_credential, &bandwidth_credential_attributes, &verification_key)
|
||||
.expect("could not prepare out bandwidth credential for spending")
|
||||
prepare_for_spending(
|
||||
raw_identity,
|
||||
&bandwidth_credential,
|
||||
&bandwidth_credential_attributes,
|
||||
&verification_key,
|
||||
)
|
||||
.expect("could not prepare out bandwidth credential for spending")
|
||||
}
|
||||
|
||||
async fn register_with_gateway(
|
||||
|
||||
@@ -23,8 +23,10 @@ use client_core::client::topology_control::{
|
||||
TopologyAccessor, TopologyRefresher, TopologyRefresherConfig,
|
||||
};
|
||||
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
|
||||
use coconut_interface::{Credential, hash_to_scalar, Parameters};
|
||||
use credentials::bandwidth::{prepare_for_spending, BandwidthVoucherAttributes, BANDWIDTH_VALUE, TOTAL_ATTRIBUTES};
|
||||
use coconut_interface::{hash_to_scalar, Credential, Parameters};
|
||||
use credentials::bandwidth::{
|
||||
prepare_for_spending, BandwidthVoucherAttributes, BANDWIDTH_VALUE, TOTAL_ATTRIBUTES,
|
||||
};
|
||||
use credentials::obtain_aggregate_verification_key;
|
||||
use crypto::asymmetric::identity;
|
||||
use futures::channel::mpsc;
|
||||
@@ -162,11 +164,11 @@ impl NymClient {
|
||||
.expect("could not obtain aggregate verification key of validators");
|
||||
|
||||
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
|
||||
let bandwidth_credential_attributes = BandwidthVoucherAttributes{
|
||||
serial_number : params.random_scalar(),
|
||||
binding_number : params.random_scalar(),
|
||||
voucher_value : hash_to_scalar(BANDWIDTH_VALUE.to_be_bytes()),
|
||||
voucher_info : hash_to_scalar(String::from("BandwidthVoucher").as_bytes()),
|
||||
let bandwidth_credential_attributes = BandwidthVoucherAttributes {
|
||||
serial_number: params.random_scalar(),
|
||||
binding_number: params.random_scalar(),
|
||||
voucher_value: hash_to_scalar(BANDWIDTH_VALUE.to_be_bytes()),
|
||||
voucher_info: hash_to_scalar(String::from("BandwidthVoucher").as_bytes()),
|
||||
};
|
||||
|
||||
let bandwidth_credential = credentials::bandwidth::obtain_signature(
|
||||
|
||||
@@ -6,9 +6,11 @@ use crate::commands::override_config;
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use client_core::client::key_manager::KeyManager;
|
||||
use client_core::config::persistence::key_pathfinder::ClientKeyPathfinder;
|
||||
use coconut_interface::{Credential, hash_to_scalar, Parameters};
|
||||
use coconut_interface::{hash_to_scalar, Credential, Parameters};
|
||||
use config::NymConfig;
|
||||
use credentials::bandwidth::{prepare_for_spending, BandwidthVoucherAttributes, BANDWIDTH_VALUE, TOTAL_ATTRIBUTES};
|
||||
use credentials::bandwidth::{
|
||||
prepare_for_spending, BandwidthVoucherAttributes, BANDWIDTH_VALUE, TOTAL_ATTRIBUTES,
|
||||
};
|
||||
use credentials::obtain_aggregate_verification_key;
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
use gateway_client::GatewayClient;
|
||||
@@ -68,19 +70,29 @@ async fn prepare_temporary_credential(validators: &[Url], raw_identity: &[u8]) -
|
||||
.expect("could not obtain aggregate verification key of validators");
|
||||
|
||||
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
|
||||
let bandwidth_credential_attributes = BandwidthVoucherAttributes{
|
||||
serial_number : params.random_scalar(),
|
||||
binding_number : params.random_scalar(),
|
||||
voucher_value : hash_to_scalar(BANDWIDTH_VALUE.to_be_bytes()),
|
||||
voucher_info : hash_to_scalar(String::from("BandwidthVoucher").as_bytes()),
|
||||
let bandwidth_credential_attributes = BandwidthVoucherAttributes {
|
||||
serial_number: params.random_scalar(),
|
||||
binding_number: params.random_scalar(),
|
||||
voucher_value: hash_to_scalar(BANDWIDTH_VALUE.to_be_bytes()),
|
||||
voucher_info: hash_to_scalar(String::from("BandwidthVoucher").as_bytes()),
|
||||
};
|
||||
|
||||
let bandwidth_credential = credentials::bandwidth::obtain_signature(¶ms, &bandwidth_credential_attributes, validators, &verification_key)
|
||||
.await
|
||||
.expect("could not obtain bandwidth credential");
|
||||
let bandwidth_credential = credentials::bandwidth::obtain_signature(
|
||||
¶ms,
|
||||
&bandwidth_credential_attributes,
|
||||
validators,
|
||||
&verification_key,
|
||||
)
|
||||
.await
|
||||
.expect("could not obtain bandwidth credential");
|
||||
|
||||
prepare_for_spending(raw_identity, &bandwidth_credential, &bandwidth_credential_attributes, &verification_key)
|
||||
.expect("could not prepare out bandwidth credential for spending")
|
||||
prepare_for_spending(
|
||||
raw_identity,
|
||||
&bandwidth_credential,
|
||||
&bandwidth_credential_attributes,
|
||||
&verification_key,
|
||||
)
|
||||
.expect("could not prepare out bandwidth credential for spending")
|
||||
}
|
||||
|
||||
async fn register_with_gateway(
|
||||
|
||||
@@ -10,7 +10,10 @@ use url::Url;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::utils::{obtain_aggregate_signature, prepare_credential_for_spending, ValidatorInfo};
|
||||
use coconut_interface::{hash_to_scalar, Credential, Parameters, Signature, VerificationKey, Attribute, PrivateAttribute, PublicAttribute};
|
||||
use coconut_interface::{
|
||||
hash_to_scalar, Attribute, Credential, Parameters, PrivateAttribute, PublicAttribute,
|
||||
Signature, VerificationKey,
|
||||
};
|
||||
|
||||
pub const BANDWIDTH_VALUE: u64 = 10 * 1024 * 1024 * 1024; // 10 GB
|
||||
|
||||
@@ -22,16 +25,14 @@ pub const SERIAL_NUMBER_LEN: usize = 47;
|
||||
pub const BINDING_NUMBER_LEN: usize = 47;
|
||||
pub const VOUCHER_INFO_LEN: usize = 47;
|
||||
|
||||
|
||||
pub struct BandwidthVoucherAttributes {
|
||||
pub serial_number : PrivateAttribute,
|
||||
pub binding_number : PrivateAttribute,
|
||||
pub voucher_value : PublicAttribute,
|
||||
pub voucher_info : PublicAttribute,
|
||||
pub serial_number: PrivateAttribute,
|
||||
pub binding_number: PrivateAttribute,
|
||||
pub voucher_value: PublicAttribute,
|
||||
pub voucher_info: PublicAttribute,
|
||||
}
|
||||
|
||||
impl BandwidthVoucherAttributes {
|
||||
|
||||
pub fn get_public_attributes(&self) -> Vec<PublicAttribute> {
|
||||
let mut pub_attributes = Vec::with_capacity(PUBLIC_ATTRIBUTES as usize);
|
||||
pub_attributes.push(self.voucher_value);
|
||||
@@ -48,12 +49,23 @@ impl BandwidthVoucherAttributes {
|
||||
}
|
||||
|
||||
// TODO: this definitely has to be moved somewhere else. It's just a temporary solution
|
||||
pub async fn obtain_signature(params: &Parameters, attributes: &BandwidthVoucherAttributes, validators: &[Url], verification_key: &VerificationKey) -> Result<Signature, Error> {
|
||||
|
||||
pub async fn obtain_signature(
|
||||
params: &Parameters,
|
||||
attributes: &BandwidthVoucherAttributes,
|
||||
validators: &[Url],
|
||||
verification_key: &VerificationKey,
|
||||
) -> Result<Signature, Error> {
|
||||
let public_attributes = attributes.get_public_attributes();
|
||||
let private_attributes = attributes.get_private_attributes();
|
||||
|
||||
obtain_aggregate_signature(¶ms, &public_attributes, &private_attributes, validators, verification_key).await
|
||||
obtain_aggregate_signature(
|
||||
¶ms,
|
||||
&public_attributes,
|
||||
&private_attributes,
|
||||
validators,
|
||||
verification_key,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub fn prepare_for_spending(
|
||||
|
||||
@@ -7,8 +7,8 @@ use coconut_interface::{
|
||||
prove_credential, Attribute, BlindSignRequestBody, Credential, Parameters, Signature,
|
||||
SignatureShare, VerificationKey,
|
||||
};
|
||||
use url::Url;
|
||||
use std::borrow::Borrow;
|
||||
use url::Url;
|
||||
|
||||
/// Contacts all provided validators and then aggregate their verification keys.
|
||||
///
|
||||
@@ -64,7 +64,7 @@ async fn obtain_partial_credential(
|
||||
public_attributes: &[Attribute],
|
||||
private_attributes: &[Attribute],
|
||||
client: &validator_client::ApiClient,
|
||||
validator_vk : &VerificationKey,
|
||||
validator_vk: &VerificationKey,
|
||||
) -> Result<Signature, Error> {
|
||||
let elgamal_keypair = coconut_interface::elgamal_keygen(params);
|
||||
let blind_sign_request = prepare_blind_sign(
|
||||
@@ -85,12 +85,21 @@ async fn obtain_partial_credential(
|
||||
.blind_sign(&blind_sign_request_body)
|
||||
.await?
|
||||
.blinded_signature;
|
||||
Ok(blinded_signature.unblind(¶ms, elgamal_keypair.private_key(), validator_vk , &private_attributes, &public_attributes, &blind_sign_request.commitment_hash).unwrap())
|
||||
Ok(blinded_signature
|
||||
.unblind(
|
||||
¶ms,
|
||||
elgamal_keypair.private_key(),
|
||||
validator_vk,
|
||||
&private_attributes,
|
||||
&public_attributes,
|
||||
&blind_sign_request.commitment_hash,
|
||||
)
|
||||
.unwrap())
|
||||
}
|
||||
|
||||
pub struct ValidatorInfo {
|
||||
url : Url,
|
||||
verification_key : VerificationKey,
|
||||
url: Url,
|
||||
verification_key: VerificationKey,
|
||||
}
|
||||
|
||||
pub async fn obtain_aggregate_signature(
|
||||
@@ -109,16 +118,27 @@ pub async fn obtain_aggregate_signature(
|
||||
let mut client = validator_client::ApiClient::new(validators[0].clone());
|
||||
let validator_partial_vk = client.get_coconut_verification_key().await?;
|
||||
|
||||
let first =
|
||||
obtain_partial_credential(params, public_attributes, private_attributes, &client, &validator_partial_vk.key).await?;
|
||||
let first = obtain_partial_credential(
|
||||
params,
|
||||
public_attributes,
|
||||
private_attributes,
|
||||
&client,
|
||||
&validator_partial_vk.key,
|
||||
)
|
||||
.await?;
|
||||
shares.push(SignatureShare::new(first, 0));
|
||||
|
||||
for (id, validator_url) in validators.iter().enumerate().skip(1) {
|
||||
client.change_validator_api(validator_url.clone());
|
||||
let validator_partial_vk = client.get_coconut_verification_key().await?;
|
||||
let signature =
|
||||
obtain_partial_credential(params, public_attributes, private_attributes, &client, &validator_partial_vk.key)
|
||||
.await?;
|
||||
let signature = obtain_partial_credential(
|
||||
params,
|
||||
public_attributes,
|
||||
private_attributes,
|
||||
&client,
|
||||
&validator_partial_vk.key,
|
||||
)
|
||||
.await?;
|
||||
let share = SignatureShare::new(signature, id as u64);
|
||||
shares.push(share)
|
||||
}
|
||||
@@ -127,7 +147,12 @@ pub async fn obtain_aggregate_signature(
|
||||
attributes.extend_from_slice(&private_attributes);
|
||||
attributes.extend_from_slice(&public_attributes);
|
||||
|
||||
Ok(aggregate_signature_shares(¶ms, verification_key, &attributes, &shares)?)
|
||||
Ok(aggregate_signature_shares(
|
||||
¶ms,
|
||||
verification_key,
|
||||
&attributes,
|
||||
&shares,
|
||||
)?)
|
||||
}
|
||||
|
||||
// TODO: better type flow
|
||||
@@ -139,8 +164,13 @@ pub fn prepare_credential_for_spending(
|
||||
signature: &Signature,
|
||||
verification_key: &VerificationKey,
|
||||
) -> Result<Credential, Error> {
|
||||
|
||||
let theta = prove_credential(params, verification_key, signature, serial_number, binding_number)?;
|
||||
let theta = prove_credential(
|
||||
params,
|
||||
verification_key,
|
||||
signature,
|
||||
serial_number,
|
||||
binding_number,
|
||||
)?;
|
||||
|
||||
Ok(Credential::new(
|
||||
(public_attributes.len() + 2) as u32,
|
||||
|
||||
@@ -112,7 +112,7 @@ impl PrivateKey {
|
||||
.to_string(),
|
||||
),
|
||||
)
|
||||
.map(PrivateKey)
|
||||
.map(PrivateKey)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ impl TryFrom<&[u8]> for PublicKey {
|
||||
"Failed to deserialize compressed ElGamal public key".to_string(),
|
||||
),
|
||||
)
|
||||
.map(PublicKey)
|
||||
.map(PublicKey)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@ mod tests {
|
||||
ciphertext.0.to_affine().to_compressed(),
|
||||
ciphertext.1.to_affine().to_compressed(),
|
||||
]
|
||||
.concat();
|
||||
.concat();
|
||||
assert_eq!(expected_bytes, bytes);
|
||||
assert_eq!(ciphertext, Ciphertext::try_from(&bytes[..]).unwrap())
|
||||
}
|
||||
|
||||
@@ -38,9 +38,9 @@ pub enum CoconutError {
|
||||
#[error("Deserialization error: {0}")]
|
||||
Deserialization(String),
|
||||
#[error(
|
||||
"Deserailization error, expected at least {} bytes, got {}",
|
||||
min,
|
||||
actual
|
||||
"Deserailization error, expected at least {} bytes, got {}",
|
||||
min,
|
||||
actual
|
||||
)]
|
||||
DeserializationMinLength { min: usize, actual: usize },
|
||||
#[error("Tried to deserialize {object} with bytes of invalid length. Expected {actual} < {} or {modulus_target} % {modulus} == 0")]
|
||||
|
||||
@@ -53,7 +53,6 @@ pub type Attribute = Scalar;
|
||||
pub type PrivateAttribute = Attribute;
|
||||
pub type PublicAttribute = Attribute;
|
||||
|
||||
|
||||
impl Bytable for Attribute {
|
||||
fn to_byte_vec(&self) -> Vec<u8> {
|
||||
self.to_bytes().to_vec()
|
||||
|
||||
@@ -18,18 +18,18 @@ use std::borrow::Borrow;
|
||||
use std::convert::TryInto;
|
||||
|
||||
use bls12_381::{G1Projective, G2Projective, Scalar};
|
||||
use digest::Digest;
|
||||
use digest::generic_array::typenum::Unsigned;
|
||||
use digest::Digest;
|
||||
use group::GroupEncoding;
|
||||
use itertools::izip;
|
||||
use sha2::Sha256;
|
||||
|
||||
use crate::{Attribute, elgamal, ElGamalKeyPair, PublicKey};
|
||||
use crate::elgamal::Ciphertext;
|
||||
use crate::error::{CoconutError, Result};
|
||||
use crate::scheme::{Signature, VerificationKey};
|
||||
use crate::scheme::setup::Parameters;
|
||||
use crate::scheme::{Signature, VerificationKey};
|
||||
use crate::utils::{hash_g1, try_deserialize_scalar, try_deserialize_scalar_vec};
|
||||
use crate::{elgamal, Attribute, ElGamalKeyPair, PublicKey};
|
||||
|
||||
// as per the reference python implementation
|
||||
type ChallengeDigest = Sha256;
|
||||
@@ -51,10 +51,10 @@ pub struct ProofCmCs {
|
||||
// and as per the bls12-381 library all elements are using big-endian form
|
||||
/// 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 {
|
||||
@@ -76,15 +76,14 @@ fn compute_challenge<D, I, B>(iter: I) -> Scalar
|
||||
Scalar::from_bytes_wide(&bytes)
|
||||
}
|
||||
|
||||
fn produce_response(witness: &Scalar, challenge: &Scalar, secret: &Scalar) -> Scalar
|
||||
{
|
||||
fn produce_response(witness: &Scalar, challenge: &Scalar, secret: &Scalar) -> Scalar {
|
||||
witness - challenge * secret
|
||||
}
|
||||
|
||||
// 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());
|
||||
|
||||
@@ -151,10 +150,10 @@ impl ProofCmCs {
|
||||
// Ccm = (wr * g1) + (wm[0] * hs[0]) + ... + (wm[i] * hs[i])
|
||||
let commitment_attributes = g1 * witness_commitment_opening
|
||||
+ witness_attributes
|
||||
.iter()
|
||||
.zip(params.gen_hs().iter())
|
||||
.map(|(wm_i, hs_i)| hs_i * wm_i)
|
||||
.sum::<G1Projective>();
|
||||
.iter()
|
||||
.zip(params.gen_hs().iter())
|
||||
.map(|(wm_i, hs_i)| hs_i * wm_i)
|
||||
.sum::<G1Projective>();
|
||||
|
||||
let ciphertexts_bytes = priv_attributes_ciphertexts
|
||||
.iter()
|
||||
@@ -245,19 +244,19 @@ impl ProofCmCs {
|
||||
self.response_keys.iter(),
|
||||
self.response_attributes.iter()
|
||||
)
|
||||
.map(|(c2, res_key, res_attr)| c2 * self.challenge + pub_key * res_key + h * res_attr)
|
||||
.map(|witness| witness.to_bytes())
|
||||
.collect::<Vec<_>>();
|
||||
.map(|(c2, res_key, res_attr)| c2 * self.challenge + pub_key * res_key + h * res_attr)
|
||||
.map(|witness| witness.to_bytes())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Cw = (cm * c) + (rr * g1) + (rm[0] * hs[0]) + ... + (rm[n] * hs[n])
|
||||
let commitment_attributes = commitment * self.challenge
|
||||
+ g1 * self.response_opening
|
||||
+ self
|
||||
.response_attributes
|
||||
.iter()
|
||||
.zip(params.gen_hs().iter())
|
||||
.map(|(res_attr, hs)| hs * res_attr)
|
||||
.sum::<G1Projective>();
|
||||
.response_attributes
|
||||
.iter()
|
||||
.zip(params.gen_hs().iter())
|
||||
.map(|(res_attr, hs)| hs * res_attr)
|
||||
.sum::<G1Projective>();
|
||||
|
||||
let ciphertexts_bytes = attributes_ciphertexts
|
||||
.iter()
|
||||
@@ -414,10 +413,10 @@ impl ProofKappaNu {
|
||||
let commitment_kappa = params.gen2() * witness_blinder
|
||||
+ verification_key.alpha
|
||||
+ witness_attributes
|
||||
.iter()
|
||||
.zip(verification_key.beta.iter())
|
||||
.map(|(wm_i, beta_i)| beta_i * wm_i)
|
||||
.sum::<G2Projective>();
|
||||
.iter()
|
||||
.zip(verification_key.beta.iter())
|
||||
.map(|(wm_i, beta_i)| beta_i * wm_i)
|
||||
.sum::<G2Projective>();
|
||||
|
||||
// zeta is the public value associated with the serial number
|
||||
let commitment_zeta = params.gen2() * witness_serial_number;
|
||||
@@ -433,8 +432,10 @@ impl ProofKappaNu {
|
||||
|
||||
// responses
|
||||
let response_blinder = produce_response(&witness_blinder, &challenge, &blinding_factor);
|
||||
let response_serial_number = produce_response(&witness_serial_number, &challenge, &serial_number);
|
||||
let response_binding_number = produce_response(&witness_binding_number, &challenge, &binding_number);
|
||||
let response_serial_number =
|
||||
produce_response(&witness_serial_number, &challenge, &serial_number);
|
||||
let response_binding_number =
|
||||
produce_response(&witness_binding_number, &challenge, &binding_number);
|
||||
|
||||
ProofKappaNu {
|
||||
challenge,
|
||||
@@ -468,15 +469,13 @@ impl ProofKappaNu {
|
||||
+ params.gen2() * self.response_blinder
|
||||
+ verification_key.alpha * (Scalar::one() - self.challenge)
|
||||
+ response_attributes
|
||||
.iter()
|
||||
.zip(verification_key.beta.iter())
|
||||
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
|
||||
.sum::<G2Projective>();
|
||||
.iter()
|
||||
.zip(verification_key.beta.iter())
|
||||
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
|
||||
.sum::<G2Projective>();
|
||||
|
||||
// zeta is the public value associated with the serial number
|
||||
let commitment_zeta = zeta * self.challenge
|
||||
+ params.gen2() * self.response_serial_number;
|
||||
|
||||
let commitment_zeta = zeta * self.challenge + params.gen2() * self.response_serial_number;
|
||||
|
||||
// compute the challenge
|
||||
let challenge = compute_challenge::<ChallengeDigest, _, _>(
|
||||
@@ -501,7 +500,6 @@ impl ProofKappaNu {
|
||||
bytes.extend_from_slice(&self.response_serial_number.to_bytes());
|
||||
bytes.extend_from_slice(&self.response_binding_number.to_bytes());
|
||||
|
||||
|
||||
// bytes.extend_from_slice(&attributes_len.to_le_bytes());
|
||||
// for rm in &self.response_attributes {
|
||||
// bytes.extend_from_slice(&rm.to_bytes());
|
||||
@@ -669,7 +667,7 @@ mod tests {
|
||||
&binding_number,
|
||||
&r,
|
||||
&kappa,
|
||||
&zeta
|
||||
&zeta,
|
||||
);
|
||||
|
||||
let bytes = pi_v.to_bytes();
|
||||
@@ -689,7 +687,7 @@ mod tests {
|
||||
&binding_number,
|
||||
&r,
|
||||
&kappa,
|
||||
&zeta
|
||||
&zeta,
|
||||
);
|
||||
|
||||
let bytes = pi_v.to_bytes();
|
||||
|
||||
@@ -19,11 +19,11 @@ use bls12_381::{G2Prepared, G2Projective, Scalar};
|
||||
use group::Curve;
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::{Attribute, Parameters};
|
||||
use crate::error::{CoconutError, Result};
|
||||
use crate::scheme::{PartialSignature, Signature, SignatureShare, SignerIndex, VerificationKey};
|
||||
use crate::scheme::verification::check_bilinear_pairing;
|
||||
use crate::scheme::{PartialSignature, Signature, SignatureShare, SignerIndex, VerificationKey};
|
||||
use crate::utils::perform_lagrangian_interpolation_at_origin;
|
||||
use crate::{Attribute, Parameters};
|
||||
|
||||
pub(crate) trait Aggregatable: Sized {
|
||||
fn aggregate(aggregatable: &[Self], indices: Option<&[SignerIndex]>) -> Result<Self>;
|
||||
@@ -36,10 +36,10 @@ pub(crate) trait Aggregatable: Sized {
|
||||
|
||||
// includes `VerificationKey`
|
||||
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() {
|
||||
@@ -101,17 +101,15 @@ pub fn aggregate_signatures(
|
||||
|
||||
let signature = match Aggregatable::aggregate(signatures, indices) {
|
||||
Ok(res) => res,
|
||||
Err(err) => return Err(err)
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
|
||||
// Verify the signature
|
||||
let alpha = verification_key.alpha;
|
||||
|
||||
let tmp = attributes.iter()
|
||||
.zip(
|
||||
verification_key
|
||||
.beta
|
||||
.iter())
|
||||
let tmp = attributes
|
||||
.iter()
|
||||
.zip(verification_key.beta.iter())
|
||||
.map(|(attr, beta_i)| beta_i * attr)
|
||||
.sum::<G2Projective>();
|
||||
|
||||
@@ -128,13 +126,24 @@ pub fn aggregate_signatures(
|
||||
Ok(signature)
|
||||
}
|
||||
|
||||
pub fn aggregate_signature_shares(params: &Parameters, verification_key: &VerificationKey, attributes: &[Attribute], shares: &[SignatureShare]) -> Result<Signature> {
|
||||
pub fn aggregate_signature_shares(
|
||||
params: &Parameters,
|
||||
verification_key: &VerificationKey,
|
||||
attributes: &[Attribute],
|
||||
shares: &[SignatureShare],
|
||||
) -> Result<Signature> {
|
||||
let (signatures, indices): (Vec<_>, Vec<_>) = shares
|
||||
.iter()
|
||||
.map(|share| (*share.signature(), share.index()))
|
||||
.unzip();
|
||||
|
||||
aggregate_signatures(¶ms, &verification_key, &attributes, &signatures, Some(&indices))
|
||||
aggregate_signatures(
|
||||
¶ms,
|
||||
&verification_key,
|
||||
&attributes,
|
||||
&signatures,
|
||||
Some(&indices),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -229,10 +238,24 @@ mod tests {
|
||||
|
||||
// aggregating (any) threshold works
|
||||
let aggr_vk_1 = aggregate_verification_keys(&vks[..3], Some(&[1, 2, 3])).unwrap();
|
||||
let aggr_sig1 = aggregate_signatures(¶ms, &aggr_vk_1, &attributes, &sigs[..3], Some(&[1, 2, 3])).unwrap();
|
||||
let aggr_sig1 = aggregate_signatures(
|
||||
¶ms,
|
||||
&aggr_vk_1,
|
||||
&attributes,
|
||||
&sigs[..3],
|
||||
Some(&[1, 2, 3]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let aggr_vk_2 = aggregate_verification_keys(&vks[2..], Some(&[3, 4, 5])).unwrap();
|
||||
let aggr_sig2 = aggregate_signatures(¶ms, &aggr_vk_1, &attributes, &sigs[2..], Some(&[3, 4, 5])).unwrap();
|
||||
let aggr_sig2 = aggregate_signatures(
|
||||
¶ms,
|
||||
&aggr_vk_1,
|
||||
&attributes,
|
||||
&sigs[2..],
|
||||
Some(&[3, 4, 5]),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(aggr_sig1, aggr_sig2);
|
||||
|
||||
// verify credential for good measure
|
||||
@@ -240,22 +263,50 @@ mod tests {
|
||||
|
||||
// aggregating threshold+1 works
|
||||
let aggr_vk_more = aggregate_verification_keys(&vks[1..], Some(&[2, 3, 4, 5])).unwrap();
|
||||
let aggr_more = aggregate_signatures(¶ms, &aggr_vk_more, &attributes, &sigs[1..], Some(&[2, 3, 4, 5])).unwrap();
|
||||
let aggr_more = aggregate_signatures(
|
||||
¶ms,
|
||||
&aggr_vk_more,
|
||||
&attributes,
|
||||
&sigs[1..],
|
||||
Some(&[2, 3, 4, 5]),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(aggr_sig1, aggr_more);
|
||||
|
||||
// aggregating all
|
||||
let aggr_vk_all = aggregate_verification_keys(&vks, Some(&[1, 2, 3, 4, 5])).unwrap();
|
||||
let aggr_all = aggregate_signatures(¶ms, &aggr_vk_all, &attributes, &sigs, Some(&[1, 2, 3, 4, 5])).unwrap();
|
||||
let aggr_all = aggregate_signatures(
|
||||
¶ms,
|
||||
&aggr_vk_all,
|
||||
&attributes,
|
||||
&sigs,
|
||||
Some(&[1, 2, 3, 4, 5]),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(aggr_all, aggr_sig1);
|
||||
|
||||
// not taking enough points (threshold was 3) should fail
|
||||
let aggr_vk_not_enough = aggregate_verification_keys(&vks[..2], Some(&[1, 2, ])).unwrap();
|
||||
let aggr_not_enough = aggregate_signatures(¶ms, &aggr_vk_not_enough, &attributes, &sigs[..2], Some(&[1, 2])).unwrap();
|
||||
let aggr_vk_not_enough = aggregate_verification_keys(&vks[..2], Some(&[1, 2])).unwrap();
|
||||
let aggr_not_enough = aggregate_signatures(
|
||||
¶ms,
|
||||
&aggr_vk_not_enough,
|
||||
&attributes,
|
||||
&sigs[..2],
|
||||
Some(&[1, 2]),
|
||||
)
|
||||
.unwrap();
|
||||
assert_ne!(aggr_not_enough, aggr_sig1);
|
||||
|
||||
// taking wrong index should fail
|
||||
let aggr_vk_bad = aggregate_verification_keys(&vks[2..], Some(&[1, 2, 3])).unwrap();
|
||||
assert!(aggregate_signatures(¶ms, &aggr_vk_bad, &attributes, &sigs[2..], Some(&[42, 123, 100])).is_err());
|
||||
assert!(aggregate_signatures(
|
||||
¶ms,
|
||||
&aggr_vk_bad,
|
||||
&attributes,
|
||||
&sigs[2..],
|
||||
Some(&[42, 123, 100])
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
fn random_signature() -> Signature {
|
||||
@@ -279,7 +330,9 @@ mod tests {
|
||||
.unzip();
|
||||
|
||||
let aggr_vk_all = aggregate_verification_keys(&vks, None).unwrap();
|
||||
assert!(aggregate_signatures(¶ms, &aggr_vk_all, &attributes, &signatures, None).is_err());
|
||||
assert!(
|
||||
aggregate_signatures(¶ms, &aggr_vk_all, &attributes, &signatures, None).is_err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -294,8 +347,18 @@ mod tests {
|
||||
.unzip();
|
||||
let aggr_vk_all = aggregate_verification_keys(&vks, None).unwrap();
|
||||
|
||||
assert!(aggregate_signatures(¶ms, &aggr_vk_all, &attributes, &signatures, Some(&[])).is_err());
|
||||
assert!(aggregate_signatures(¶ms, &aggr_vk_all, &attributes, &signatures, Some(&[1, 2])).is_err());
|
||||
assert!(
|
||||
aggregate_signatures(¶ms, &aggr_vk_all, &attributes, &signatures, Some(&[]))
|
||||
.is_err()
|
||||
);
|
||||
assert!(aggregate_signatures(
|
||||
¶ms,
|
||||
&aggr_vk_all,
|
||||
&attributes,
|
||||
&signatures,
|
||||
Some(&[1, 2])
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -310,7 +373,14 @@ mod tests {
|
||||
.unzip();
|
||||
let aggr_vk_all = aggregate_verification_keys(&vks, None).unwrap();
|
||||
|
||||
assert!(aggregate_signatures(¶ms, &aggr_vk_all, &attributes, &signatures, Some(&[1, 1])).is_err());
|
||||
assert!(aggregate_signatures(
|
||||
¶ms,
|
||||
&aggr_vk_all,
|
||||
&attributes,
|
||||
&signatures,
|
||||
Some(&[1, 1])
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
// TODO: test for aggregating non-threshold keys
|
||||
|
||||
@@ -18,21 +18,21 @@ use std::convert::TryInto;
|
||||
use bls12_381::{G1Affine, G1Projective, Scalar};
|
||||
use group::{Curve, GroupEncoding};
|
||||
|
||||
use crate::{Attribute, elgamal, ElGamalKeyPair, VerificationKey};
|
||||
use crate::elgamal::{Ciphertext, EphemeralKey};
|
||||
use crate::error::{CoconutError, Result};
|
||||
use crate::proofs::ProofCmCs;
|
||||
use crate::scheme::setup::Parameters;
|
||||
use crate::scheme::BlindedSignature;
|
||||
use crate::scheme::SecretKey;
|
||||
use crate::scheme::setup::Parameters;
|
||||
use crate::{elgamal, Attribute, ElGamalKeyPair, VerificationKey};
|
||||
// TODO: possibly completely remove those two functions.
|
||||
// They only exist to have a simpler and smaller code snippets to test
|
||||
// basic functionalities.
|
||||
use crate::traits::{Base58, Bytable};
|
||||
use crate::utils::{hash_g1, try_deserialize_g1_projective};
|
||||
/// Creates a Coconut Signature under a given secret key on a set of public attributes only.
|
||||
#[cfg(test)]
|
||||
use crate::Signature;
|
||||
use crate::traits::{Base58, Bytable};
|
||||
use crate::utils::{hash_g1, try_deserialize_g1_projective};
|
||||
|
||||
// TODO NAMING: double check this one
|
||||
// Lambda
|
||||
@@ -160,7 +160,6 @@ impl BlindSignRequest {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn compute_private_attributes_commitment(
|
||||
params: &Parameters,
|
||||
private_attributes: &[Attribute],
|
||||
@@ -171,7 +170,10 @@ pub fn compute_private_attributes_commitment(
|
||||
// Produces h0 ^ m0 * h1^m1 * .... * hn^mn
|
||||
// where m0, m1, ...., mn are private attributes
|
||||
let attr_cm = private_attributes
|
||||
.iter().zip(hs).map(|(&m, h)| h * m).sum::<G1Projective>();
|
||||
.iter()
|
||||
.zip(hs)
|
||||
.map(|(&m, h)| h * m)
|
||||
.sum::<G1Projective>();
|
||||
|
||||
// Produces g1^r * h0 ^ m0 * h1^m1 * .... * hn^mn
|
||||
let commitment = params.gen1() * commitment_opening + attr_cm;
|
||||
@@ -222,7 +224,13 @@ pub fn prepare_blind_sign(
|
||||
// Compute the challenge as the commitment hash
|
||||
let commitment_hash = compute_commitment_hash(commitment);
|
||||
// build ElGamal encryption
|
||||
let (private_attributes_ciphertexts, ephemeral_keys): (Vec<_>, Vec<_>) = compute_attribute_encryption(params, private_attributes, elgamal_keypair.public_key(), commitment_hash);
|
||||
let (private_attributes_ciphertexts, ephemeral_keys): (Vec<_>, Vec<_>) =
|
||||
compute_attribute_encryption(
|
||||
params,
|
||||
private_attributes,
|
||||
elgamal_keypair.public_key(),
|
||||
commitment_hash,
|
||||
);
|
||||
|
||||
let pi_s = ProofCmCs::construct(
|
||||
params,
|
||||
@@ -330,10 +338,10 @@ pub fn sign(
|
||||
// x + m0 * y0 + m1 * y1 + ... mn * yn
|
||||
let exponent = secret_key.x
|
||||
+ public_attributes
|
||||
.iter()
|
||||
.zip(secret_key.ys.iter())
|
||||
.map(|(m_i, y_i)| m_i * y_i)
|
||||
.sum::<Scalar>();
|
||||
.iter()
|
||||
.zip(secret_key.ys.iter())
|
||||
.map(|(m_i, y_i)| m_i * y_i)
|
||||
.sum::<Scalar>();
|
||||
|
||||
let sig2 = h * exponent;
|
||||
Ok(Signature(h, sig2))
|
||||
@@ -356,7 +364,7 @@ mod tests {
|
||||
&private_attributes,
|
||||
&public_attributes,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
let bytes = lambda.to_bytes();
|
||||
println!("{:?}", bytes.len());
|
||||
@@ -374,7 +382,7 @@ mod tests {
|
||||
&private_attributes,
|
||||
&public_attributes,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
let bytes = lambda.to_bytes();
|
||||
assert_eq!(
|
||||
|
||||
@@ -22,15 +22,15 @@ use bls12_381::{G2Projective, Scalar};
|
||||
use group::Curve;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
use crate::Base58;
|
||||
use crate::error::{CoconutError, Result};
|
||||
use crate::scheme::aggregation::aggregate_verification_keys;
|
||||
use crate::scheme::setup::Parameters;
|
||||
use crate::scheme::SignerIndex;
|
||||
use crate::traits::Bytable;
|
||||
use crate::utils::{
|
||||
Polynomial, try_deserialize_g2_projective, try_deserialize_scalar, try_deserialize_scalar_vec,
|
||||
try_deserialize_g2_projective, try_deserialize_scalar, try_deserialize_scalar_vec, Polynomial,
|
||||
};
|
||||
use crate::Base58;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
@@ -220,13 +220,13 @@ impl<'a> Mul<Scalar> for &'a VerificationKey {
|
||||
}
|
||||
|
||||
impl<T> Sum<T> for VerificationKey
|
||||
where
|
||||
T: Borrow<VerificationKey>,
|
||||
where
|
||||
T: Borrow<VerificationKey>,
|
||||
{
|
||||
#[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() {
|
||||
|
||||
@@ -22,7 +22,6 @@ use group::Curve;
|
||||
|
||||
pub use keygen::{SecretKey, VerificationKey};
|
||||
|
||||
use crate::{Attribute, elgamal};
|
||||
use crate::elgamal::Ciphertext;
|
||||
use crate::error::{CoconutError, Result};
|
||||
use crate::scheme::aggregation::{aggregate_signature_shares, aggregate_signatures};
|
||||
@@ -30,6 +29,7 @@ use crate::scheme::setup::Parameters;
|
||||
use crate::scheme::verification::check_bilinear_pairing;
|
||||
use crate::traits::{Base58, Bytable};
|
||||
use crate::utils::try_deserialize_g1_projective;
|
||||
use crate::{elgamal, Attribute};
|
||||
|
||||
pub mod aggregation;
|
||||
pub mod issuance;
|
||||
@@ -155,13 +155,15 @@ impl TryFrom<&[u8]> for BlindedSignature {
|
||||
}
|
||||
|
||||
impl BlindedSignature {
|
||||
pub fn unblind(&self,
|
||||
params: &Parameters,
|
||||
private_key: &elgamal::PrivateKey,
|
||||
partial_verification_key: &VerificationKey,
|
||||
private_attributes: &[Attribute],
|
||||
public_attributes: &[Attribute],
|
||||
commitment_hash: &G1Projective) -> Result<Signature> {
|
||||
pub fn unblind(
|
||||
&self,
|
||||
params: &Parameters,
|
||||
private_key: &elgamal::PrivateKey,
|
||||
partial_verification_key: &VerificationKey,
|
||||
private_attributes: &[Attribute],
|
||||
public_attributes: &[Attribute],
|
||||
commitment_hash: &G1Projective,
|
||||
) -> Result<Signature> {
|
||||
// parse the signature
|
||||
let h = &self.0;
|
||||
let c = &self.1;
|
||||
@@ -179,10 +181,7 @@ impl BlindedSignature {
|
||||
let tmp = private_attributes
|
||||
.iter()
|
||||
.chain(public_attributes.iter())
|
||||
.zip(
|
||||
partial_verification_key
|
||||
.beta
|
||||
.iter())
|
||||
.zip(partial_verification_key.beta.iter())
|
||||
.map(|(attr, beta_i)| beta_i * attr)
|
||||
.sum::<G2Projective>();
|
||||
|
||||
@@ -255,13 +254,8 @@ mod tests {
|
||||
let keypair1 = keygen(&mut params);
|
||||
let keypair2 = keygen(&mut params);
|
||||
|
||||
let lambda = prepare_blind_sign(
|
||||
&mut params,
|
||||
&elgamal_keypair,
|
||||
&private_attributes,
|
||||
&[],
|
||||
)
|
||||
.unwrap();
|
||||
let lambda =
|
||||
prepare_blind_sign(&mut params, &elgamal_keypair, &private_attributes, &[]).unwrap();
|
||||
|
||||
let sig1 = blind_sign(
|
||||
&mut params,
|
||||
@@ -270,9 +264,16 @@ mod tests {
|
||||
&lambda,
|
||||
&[],
|
||||
)
|
||||
.unwrap()
|
||||
.unblind(¶ms, elgamal_keypair.private_key(), &keypair1.verification_key(), &private_attributes, &[], lambda.commitment_hash).
|
||||
unwrap();
|
||||
.unwrap()
|
||||
.unblind(
|
||||
¶ms,
|
||||
elgamal_keypair.private_key(),
|
||||
&keypair1.verification_key(),
|
||||
&private_attributes,
|
||||
&[],
|
||||
lambda.commitment_hash,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let sig2 = blind_sign(
|
||||
&mut params,
|
||||
@@ -281,9 +282,16 @@ mod tests {
|
||||
&lambda,
|
||||
&[],
|
||||
)
|
||||
.unwrap()
|
||||
.unblind(¶ms, elgamal_keypair.private_key(), &keypair2.verification_key(), &private_attributes, &[], lambda.commitment_hash)
|
||||
.unwrap();
|
||||
.unwrap()
|
||||
.unblind(
|
||||
¶ms,
|
||||
elgamal_keypair.private_key(),
|
||||
&keypair2.verification_key(),
|
||||
&private_attributes,
|
||||
&[],
|
||||
lambda.commitment_hash,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let theta1 = prove_credential(
|
||||
&mut params,
|
||||
@@ -291,7 +299,7 @@ mod tests {
|
||||
&sig1,
|
||||
&private_attributes,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
let theta2 = prove_credential(
|
||||
&mut params,
|
||||
@@ -299,7 +307,7 @@ mod tests {
|
||||
&sig2,
|
||||
&private_attributes,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
assert!(verify_credential(
|
||||
¶ms,
|
||||
@@ -371,7 +379,7 @@ mod tests {
|
||||
&private_attributes,
|
||||
&public_attributes,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
let sig1 = blind_sign(
|
||||
&mut params,
|
||||
@@ -380,9 +388,16 @@ mod tests {
|
||||
&lambda,
|
||||
&public_attributes,
|
||||
)
|
||||
.unwrap()
|
||||
.unblind(¶ms, elgamal_keypair.private_key(), &keypair1.verification_key(), &private_attributes, &public_attributes, lambda.commitment_hash)
|
||||
.unwrap();
|
||||
.unwrap()
|
||||
.unblind(
|
||||
¶ms,
|
||||
elgamal_keypair.private_key(),
|
||||
&keypair1.verification_key(),
|
||||
&private_attributes,
|
||||
&public_attributes,
|
||||
lambda.commitment_hash,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let sig2 = blind_sign(
|
||||
&mut params,
|
||||
@@ -391,9 +406,16 @@ mod tests {
|
||||
&lambda,
|
||||
&public_attributes,
|
||||
)
|
||||
.unwrap()
|
||||
.unblind(¶ms, elgamal_keypair.private_key(), &keypair2.verification_key(), &private_attributes, &public_attributes, lambda.commitment_hash)
|
||||
.unwrap();
|
||||
.unwrap()
|
||||
.unblind(
|
||||
¶ms,
|
||||
elgamal_keypair.private_key(),
|
||||
&keypair2.verification_key(),
|
||||
&private_attributes,
|
||||
&public_attributes,
|
||||
lambda.commitment_hash,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let theta1 = prove_credential(
|
||||
&mut params,
|
||||
@@ -401,7 +423,7 @@ mod tests {
|
||||
&sig1,
|
||||
&private_attributes,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
let theta2 = prove_credential(
|
||||
&mut params,
|
||||
@@ -409,7 +431,7 @@ mod tests {
|
||||
&sig2,
|
||||
&private_attributes,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
assert!(verify_credential(
|
||||
¶ms,
|
||||
@@ -448,7 +470,7 @@ mod tests {
|
||||
&private_attributes,
|
||||
&public_attributes,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
let sigs = keypairs
|
||||
.iter()
|
||||
@@ -460,9 +482,16 @@ mod tests {
|
||||
&lambda,
|
||||
&public_attributes,
|
||||
)
|
||||
.unwrap()
|
||||
.unblind(¶ms, elgamal_keypair.private_key(), &keypair.verification_key(), &private_attributes, &public_attributes, lambda.commitment_hash)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.unblind(
|
||||
¶ms,
|
||||
elgamal_keypair.private_key(),
|
||||
&keypair.verification_key(),
|
||||
&private_attributes,
|
||||
&public_attributes,
|
||||
lambda.commitment_hash,
|
||||
)
|
||||
.unwrap()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -476,7 +505,9 @@ mod tests {
|
||||
attributes.extend_from_slice(&public_attributes);
|
||||
|
||||
let aggr_vk = aggregate_verification_keys(&vks[..2], Some(&[1, 2])).unwrap();
|
||||
let aggr_sig = aggregate_signatures(¶ms, &aggr_vk, &attributes, &sigs[..2], Some(&[1, 2])).unwrap();
|
||||
let aggr_sig =
|
||||
aggregate_signatures(¶ms, &aggr_vk, &attributes, &sigs[..2], Some(&[1, 2]))
|
||||
.unwrap();
|
||||
|
||||
let theta =
|
||||
prove_credential(&mut params, &aggr_vk, &aggr_sig, &private_attributes).unwrap();
|
||||
@@ -490,7 +521,9 @@ mod tests {
|
||||
|
||||
// taking different subset of keys and credentials
|
||||
let aggr_vk = aggregate_verification_keys(&vks[1..], Some(&[2, 3])).unwrap();
|
||||
let aggr_sig = aggregate_signatures(¶ms, &aggr_vk, &attributes, &sigs[1..], Some(&[2, 3])).unwrap();
|
||||
let aggr_sig =
|
||||
aggregate_signatures(¶ms, &aggr_vk, &attributes, &sigs[1..], Some(&[2, 3]))
|
||||
.unwrap();
|
||||
|
||||
let theta =
|
||||
prove_credential(&mut params, &aggr_vk, &aggr_sig, &private_attributes).unwrap();
|
||||
@@ -516,7 +549,7 @@ mod tests {
|
||||
signature.0.to_affine().to_compressed(),
|
||||
signature.1.to_affine().to_compressed(),
|
||||
]
|
||||
.concat();
|
||||
.concat();
|
||||
assert_eq!(expected_bytes, bytes);
|
||||
assert_eq!(signature, Signature::try_from(&bytes[..]).unwrap())
|
||||
}
|
||||
@@ -536,10 +569,10 @@ mod tests {
|
||||
// also make sure it is equivalent to the internal g1 compressed bytes concatenated
|
||||
let expected_bytes = [
|
||||
blinded_sig.0.to_affine().to_compressed(),
|
||||
blinded_sig.1.0.to_affine().to_compressed(),
|
||||
blinded_sig.1.1.to_affine().to_compressed(),
|
||||
blinded_sig.1 .0.to_affine().to_compressed(),
|
||||
blinded_sig.1 .1.to_affine().to_compressed(),
|
||||
]
|
||||
.concat();
|
||||
.concat();
|
||||
assert_eq!(expected_bytes, bytes);
|
||||
assert_eq!(blinded_sig, BlindedSignature::try_from(&bytes[..]).unwrap())
|
||||
}
|
||||
|
||||
@@ -16,10 +16,9 @@ use core::ops::Neg;
|
||||
use std::convert::TryFrom;
|
||||
use std::convert::TryInto;
|
||||
|
||||
use bls12_381::{G1Affine, G1Projective, G2Prepared, G2Projective, multi_miller_loop, Scalar};
|
||||
use bls12_381::{multi_miller_loop, G1Affine, G1Projective, G2Prepared, G2Projective, Scalar};
|
||||
use group::{Curve, Group};
|
||||
|
||||
use crate::Attribute;
|
||||
use crate::error::{CoconutError, Result};
|
||||
use crate::proofs::ProofKappaNu;
|
||||
use crate::scheme::setup::Parameters;
|
||||
@@ -27,6 +26,7 @@ use crate::scheme::Signature;
|
||||
use crate::scheme::VerificationKey;
|
||||
use crate::traits::{Base58, Bytable};
|
||||
use crate::utils::{try_deserialize_g1_projective, try_deserialize_g2_projective};
|
||||
use crate::Attribute;
|
||||
|
||||
// TODO NAMING: this whole thing
|
||||
// Theta
|
||||
@@ -36,7 +36,7 @@ pub struct Theta {
|
||||
// blinded_message (kappa)
|
||||
pub blinded_message: G2Projective,
|
||||
// blinded serial number (zeta)
|
||||
pub blinded_serial_number : G2Projective,
|
||||
pub blinded_serial_number: G2Projective,
|
||||
// sigma
|
||||
pub credential: Signature,
|
||||
// pi_v
|
||||
@@ -133,10 +133,10 @@ pub fn compute_kappa(
|
||||
params.gen2() * blinding_factor
|
||||
+ verification_key.alpha
|
||||
+ private_attributes
|
||||
.iter()
|
||||
.zip(verification_key.beta.iter())
|
||||
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
|
||||
.sum::<G2Projective>()
|
||||
.iter()
|
||||
.zip(verification_key.beta.iter())
|
||||
.map(|(priv_attr, beta_i)| beta_i * priv_attr)
|
||||
.sum::<G2Projective>()
|
||||
}
|
||||
|
||||
pub fn compute_zeta(params: &Parameters, serial_number: Attribute) -> G2Projective {
|
||||
@@ -150,8 +150,7 @@ pub fn prove_credential(
|
||||
serial_number: Attribute,
|
||||
binding_number: Attribute,
|
||||
) -> Result<Theta> {
|
||||
|
||||
if verification_key.beta.len() < 2{
|
||||
if verification_key.beta.len() < 2 {
|
||||
return Err(
|
||||
CoconutError::Verification(
|
||||
format!("Tried to prove a credential for higher than supported by the provided verification key number of attributes (max: {}, requested: 2)",
|
||||
@@ -170,7 +169,12 @@ pub fn prove_credential(
|
||||
// kappa is computed on m as input, but thanks to the use or random value r,
|
||||
// it does not reveal any information about m.
|
||||
let private_attributes = vec![serial_number, binding_number];
|
||||
let blinded_message = compute_kappa(params, verification_key, &private_attributes, sign_blinding_factor);
|
||||
let blinded_message = compute_kappa(
|
||||
params,
|
||||
verification_key,
|
||||
&private_attributes,
|
||||
sign_blinding_factor,
|
||||
);
|
||||
|
||||
// zeta is a commitment to the serial number (i.e., a public value associated with the serial number)
|
||||
let blinded_serial_number = compute_zeta(params, serial_number);
|
||||
@@ -255,11 +259,11 @@ pub fn verify(
|
||||
) -> bool {
|
||||
let kappa = (verification_key.alpha
|
||||
+ public_attributes
|
||||
.iter()
|
||||
.zip(verification_key.beta.iter())
|
||||
.map(|(m_i, b_i)| b_i * m_i)
|
||||
.sum::<G2Projective>())
|
||||
.to_affine();
|
||||
.iter()
|
||||
.zip(verification_key.beta.iter())
|
||||
.map(|(m_i, b_i)| b_i * m_i)
|
||||
.sum::<G2Projective>())
|
||||
.to_affine();
|
||||
|
||||
check_bilinear_pairing(
|
||||
&sig.0.to_affine(),
|
||||
@@ -295,7 +299,7 @@ mod tests {
|
||||
serial_number,
|
||||
binding_number,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
let bytes = theta.to_bytes();
|
||||
assert_eq!(Theta::try_from(bytes.as_slice()).unwrap(), theta);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
aggregate_signature_shares, aggregate_verification_keys, blind_sign, CoconutError,
|
||||
elgamal_keygen, prepare_blind_sign, prove_credential, setup, Signature, SignatureShare,
|
||||
ttp_keygen, VerificationKey, verify_credential,
|
||||
aggregate_signature_shares, aggregate_verification_keys, blind_sign, elgamal_keygen,
|
||||
prepare_blind_sign, prove_credential, setup, ttp_keygen, verify_credential, CoconutError,
|
||||
Signature, SignatureShare, VerificationKey,
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -51,7 +51,18 @@ fn main() -> Result<(), CoconutError> {
|
||||
let unblinded_signatures: Vec<Signature> = blinded_signatures
|
||||
.into_iter()
|
||||
.zip(verification_keys.iter())
|
||||
.map(|(signature, verification_key)| signature.unblind(¶ms, &elgamal_keypair.private_key(), &verification_key, &private_attributes, &public_attributes, blind_sign_request.commitment_hash).unwrap())
|
||||
.map(|(signature, verification_key)| {
|
||||
signature
|
||||
.unblind(
|
||||
¶ms,
|
||||
&elgamal_keypair.private_key(),
|
||||
&verification_key,
|
||||
&private_attributes,
|
||||
&public_attributes,
|
||||
blind_sign_request.commitment_hash,
|
||||
)
|
||||
.unwrap()
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Aggregate signatures
|
||||
@@ -67,7 +78,8 @@ fn main() -> Result<(), CoconutError> {
|
||||
attributes.extend_from_slice(&public_attributes);
|
||||
|
||||
// Randomize credentials and generate any cryptographic material to verify them
|
||||
let signature = aggregate_signature_shares(¶ms, &verification_key, &attributes, &signature_shares)?;
|
||||
let signature =
|
||||
aggregate_signature_shares(¶ms, &verification_key, &attributes, &signature_shares)?;
|
||||
|
||||
// Generate cryptographic material to verify them
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@ use core::iter::Sum;
|
||||
use core::ops::Mul;
|
||||
use std::convert::TryInto;
|
||||
|
||||
use bls12_381::{G1Affine, G1Projective, G2Affine, G2Projective, Scalar};
|
||||
use bls12_381::hash_to_curve::{ExpandMsgXmd, HashToCurve, HashToField};
|
||||
use bls12_381::{G1Affine, G1Projective, G2Affine, G2Projective, Scalar};
|
||||
use ff::Field;
|
||||
|
||||
use crate::error::{CoconutError, Result};
|
||||
@@ -92,9 +92,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(CoconutError::Interpolation(
|
||||
|
||||
@@ -15,8 +15,10 @@ use crate::network_monitor::monitor::summary_producer::SummaryProducer;
|
||||
use crate::network_monitor::monitor::Monitor;
|
||||
use crate::network_monitor::tested_network::TestedNetwork;
|
||||
use crate::storage::NodeStatusStorage;
|
||||
use coconut_interface::{Credential, hash_to_scalar, Parameters};
|
||||
use credentials::bandwidth::{prepare_for_spending, BandwidthVoucherAttributes, BANDWIDTH_VALUE, TOTAL_ATTRIBUTES};
|
||||
use coconut_interface::{hash_to_scalar, Credential, Parameters};
|
||||
use credentials::bandwidth::{
|
||||
prepare_for_spending, BandwidthVoucherAttributes, BANDWIDTH_VALUE, TOTAL_ATTRIBUTES,
|
||||
};
|
||||
use credentials::obtain_aggregate_verification_key;
|
||||
use crypto::asymmetric::{encryption, identity};
|
||||
use futures::channel::mpsc;
|
||||
@@ -176,17 +178,21 @@ async fn TEMPORARY_obtain_bandwidth_credential(
|
||||
.expect("could not obtain aggregate verification key of ALL validators");
|
||||
|
||||
let params = Parameters::new(TOTAL_ATTRIBUTES).unwrap();
|
||||
let bandwidth_credential_attributes = BandwidthVoucherAttributes{
|
||||
serial_number : params.random_scalar(),
|
||||
binding_number : params.random_scalar(),
|
||||
voucher_value : hash_to_scalar(BANDWIDTH_VALUE.to_be_bytes()),
|
||||
voucher_info : hash_to_scalar(String::from("BandwidthVoucher").as_bytes()),
|
||||
let bandwidth_credential_attributes = BandwidthVoucherAttributes {
|
||||
serial_number: params.random_scalar(),
|
||||
binding_number: params.random_scalar(),
|
||||
voucher_value: hash_to_scalar(BANDWIDTH_VALUE.to_be_bytes()),
|
||||
voucher_info: hash_to_scalar(String::from("BandwidthVoucher").as_bytes()),
|
||||
};
|
||||
|
||||
let bandwidth_credential =
|
||||
credentials::bandwidth::obtain_signature(¶ms, &bandwidth_credential_attributes, &validators, &verification_key)
|
||||
.await
|
||||
.expect("failed to obtain bandwidth credential!");
|
||||
let bandwidth_credential = credentials::bandwidth::obtain_signature(
|
||||
¶ms,
|
||||
&bandwidth_credential_attributes,
|
||||
&validators,
|
||||
&verification_key,
|
||||
)
|
||||
.await
|
||||
.expect("failed to obtain bandwidth credential!");
|
||||
|
||||
prepare_for_spending(
|
||||
&identity.to_bytes(),
|
||||
|
||||
Reference in New Issue
Block a user