explicit aliases for ExpirationDate and TicketType

This commit is contained in:
Jędrzej Stuczyński
2024-07-25 12:57:09 +01:00
parent ab2a1c3fe5
commit aea962b546
14 changed files with 125 additions and 132 deletions
+5 -2
View File
@@ -6,13 +6,16 @@ use time::{Duration, PrimitiveDateTime, Time};
pub use time::{Date, OffsetDateTime};
pub trait EcashTime {
fn ecash_unix_timestamp(&self) -> u64 {
fn ecash_unix_timestamp(&self) -> u32 {
let ts = self.ecash_datetime().unix_timestamp();
// just panic on pre-1970 timestamps...
assert!(ts > 0);
ts as u64
// and on anything in 22nd century...
assert!(ts <= u32::MAX as i64);
ts as u32
}
fn ecash_date(&self) -> Date {
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
/// Specifies the maximum validity of the issued ticketbooks.
pub const TICKETBOOK_VALIDITY_DAYS: u64 = 7;
pub const TICKETBOOK_VALIDITY_DAYS: u32 = 7;
/// Specifies the number of tickets in each issued ticketbook.
pub const TICKETBOOK_SIZE: u64 = 50;
@@ -9,9 +9,9 @@ pub const PUBLIC_ATTRIBUTES_LEN: usize = 2; //expiration date and ticket type
pub const PRIVATE_ATTRIBUTES_LEN: usize = 2; //user and wallet secret
pub const ATTRIBUTES_LEN: usize = PUBLIC_ATTRIBUTES_LEN + PRIVATE_ATTRIBUTES_LEN; // number of attributes encoded in a single zk-nym credential
pub const CRED_VALIDITY_PERIOD_DAYS: u64 = TICKETBOOK_VALIDITY_DAYS;
pub const CRED_VALIDITY_PERIOD_DAYS: u32 = TICKETBOOK_VALIDITY_DAYS;
pub(crate) const SECONDS_PER_DAY: u64 = 86400;
pub(crate) const SECONDS_PER_DAY: u32 = 86400;
/// Total number of tickets in each issued ticket book.
pub const NB_TICKETS: u64 = TICKETBOOK_SIZE;
@@ -2,8 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
use crate::utils::try_deserialize_g1_projective;
use crate::CompactEcashError;
use bls12_381::G1Projective;
use crate::{CompactEcashError, EncodedDate, EncodedTicketType};
use bls12_381::{G1Projective, Scalar};
use group::Curve;
use std::any::{type_name, Any};
@@ -35,3 +35,27 @@ pub(crate) fn recover_g1_tuple<T: Any>(
Ok((first, second))
}
pub(crate) fn date_scalar(date: EncodedDate) -> Scalar {
Scalar::from(date as u64)
}
// TODO: this will not work for **all** scalars,
// but timestamps have extremely (relatively speaking) limited range,
// so this should be fine
pub(crate) fn scalar_date(scalar: &Scalar) -> EncodedDate {
let b = scalar.to_bytes();
u64::from_le_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]) as EncodedDate
}
pub(crate) fn type_scalar(t_type: EncodedTicketType) -> Scalar {
Scalar::from(t_type as u64)
}
// TODO: this will not work for **all** scalars,
// but ticket types have extremely (relatively speaking) limited range,
// so this should be fine
pub(crate) fn scalar_type(scalar: &Scalar) -> EncodedTicketType {
let b = scalar.to_bytes();
u64::from_le_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]) as EncodedTicketType
}
@@ -42,6 +42,8 @@ mod traits;
pub mod utils;
pub type Attribute = Scalar;
pub type EncodedTicketType = u8;
pub type EncodedDate = u32;
pub fn ecash_parameters() -> &'static setup::Parameters {
static ECASH_PARAMS: OnceLock<setup::Parameters> = OnceLock::new();
@@ -1,23 +1,19 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use core::iter::Sum;
use core::ops::Mul;
use bls12_381::{G2Prepared, G2Projective, Scalar};
use group::Curve;
use itertools::Itertools;
use crate::common_types::{PartialSignature, Signature, SignatureShare, SignerIndex};
use crate::error::{CompactEcashError, Result};
use crate::scheme::expiration_date_signatures::scalar_date;
use crate::helpers::{scalar_date, scalar_type};
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
use crate::scheme::withdrawal::RequestInfo;
use crate::scheme::{PartialWallet, Wallet, WalletSignatures};
use crate::utils::{
check_bilinear_pairing, perform_lagrangian_interpolation_at_origin, scalar_type,
};
use crate::utils::{check_bilinear_pairing, perform_lagrangian_interpolation_at_origin};
use crate::{ecash_group_parameters, Attribute};
use bls12_381::{G2Prepared, G2Projective, Scalar};
use core::iter::Sum;
use core::ops::Mul;
use group::Curve;
use itertools::Itertools;
pub(crate) trait Aggregatable: Sized {
fn aggregate(aggregatable: &[Self], indices: Option<&[SignerIndex]>) -> Result<Self>;
@@ -2,11 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
use crate::common_types::{Signature, SignerIndex};
use crate::constants;
use crate::error::{CompactEcashError, Result};
use crate::helpers::date_scalar;
use crate::scheme::keygen::{SecretKeyAuth, VerificationKeyAuth};
use crate::utils::generate_lagrangian_coefficients_at_origin;
use crate::utils::{batch_verify_signatures, hash_g1};
use crate::{constants, EncodedDate};
use bls12_381::{G1Projective, Scalar};
use itertools::Itertools;
use serde::{Deserialize, Serialize};
@@ -19,8 +20,8 @@ pub type PartialExpirationDateSignature = ExpirationDateSignature;
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct AnnotatedExpirationDateSignature {
pub signature: ExpirationDateSignature,
pub expiration_timestamp: u64,
pub spending_timestamp: u64,
pub expiration_timestamp: EncodedDate,
pub spending_timestamp: EncodedDate,
}
impl Borrow<ExpirationDateSignature> for AnnotatedExpirationDateSignature {
@@ -66,17 +67,17 @@ where
/// The validity period is determined by the constant `CRED_VALIDITY_PERIOD` in the `constants` module.
pub fn sign_expiration_date(
sk_auth: &SecretKeyAuth,
expiration_unix_timestamp: u64,
expiration_unix_timestamp: EncodedDate,
) -> Result<Vec<AnnotatedExpirationDateSignature>> {
if sk_auth.ys.len() < 3 {
return Err(CompactEcashError::KeyTooShort);
}
let m0: Scalar = Scalar::from(expiration_unix_timestamp);
let m0: Scalar = date_scalar(expiration_unix_timestamp);
let m2: Scalar = constants::TYPE_EXP;
let partial_s_exponent = sk_auth.x + sk_auth.ys[0] * m0 + sk_auth.ys[2] * m2;
let sign_expiration = |offset: u64| {
let sign_expiration = |offset: u32| {
// we produce tuples of (assuming CRED_VALIDITY_PERIOD_DAYS = 30):
// (expiration, expiration - 29)
// (expiration, expiration - 28)
@@ -84,7 +85,7 @@ pub fn sign_expiration_date(
// (expiration, expiration)
let spending_unix_timestamp = expiration_unix_timestamp
- ((constants::CRED_VALIDITY_PERIOD_DAYS - offset - 1) * constants::SECONDS_PER_DAY);
let m1: Scalar = Scalar::from(spending_unix_timestamp);
let m1: Scalar = date_scalar(spending_unix_timestamp);
// Compute the hash
let h = hash_g1([m0.to_bytes(), m1.to_bytes()].concat());
// Sign the attributes by performing scalar-point multiplications and accumulating the result
@@ -136,22 +137,22 @@ pub fn sign_expiration_date(
pub fn verify_valid_dates_signatures<B>(
vk: &VerificationKeyAuth,
signatures: &[B],
expiration_date: u64,
expiration_date: EncodedDate,
) -> Result<()>
where
B: Borrow<ExpirationDateSignature>,
{
let m0: Scalar = Scalar::from(expiration_date);
let m0: Scalar = date_scalar(expiration_date);
let m2: Scalar = constants::TYPE_EXP;
let partially_signed = vk.alpha + vk.beta_g2[0] * m0 + vk.beta_g2[2] * m2;
let mut pairing_terms = Vec::with_capacity(signatures.len());
for (i, sig) in signatures.iter().enumerate() {
let l = i as u64;
let l = i as u32;
let valid_date = expiration_date
- ((constants::CRED_VALIDITY_PERIOD_DAYS - l - 1) * constants::SECONDS_PER_DAY);
let m1: Scalar = Scalar::from(valid_date);
let m1: Scalar = date_scalar(valid_date);
// Compute the hash
let h = hash_g1([m0.to_bytes(), m1.to_bytes()].concat());
@@ -199,7 +200,7 @@ where
///
fn _aggregate_expiration_signatures<B>(
vk: &VerificationKeyAuth,
expiration_date: u64,
expiration_date: EncodedDate,
signatures_shares: &[ExpirationDateSignatureShare<B>],
validate_shares: bool,
) -> Result<Vec<ExpirationDateSignature>>
@@ -244,12 +245,12 @@ where
let mut aggregated_date_signatures: Vec<ExpirationDateSignature> =
Vec::with_capacity(constants::CRED_VALIDITY_PERIOD_DAYS as usize);
let m0: Scalar = Scalar::from(expiration_date);
let m0: Scalar = date_scalar(expiration_date);
for l in 0..constants::CRED_VALIDITY_PERIOD_DAYS {
let valid_date = expiration_date
- ((constants::CRED_VALIDITY_PERIOD_DAYS - l - 1) * constants::SECONDS_PER_DAY);
let m1: Scalar = Scalar::from(valid_date);
let m1: Scalar = date_scalar(valid_date);
// Compute the hash
let h = hash_g1([m0.to_bytes(), m1.to_bytes()].concat());
@@ -299,7 +300,7 @@ where
///
pub fn aggregate_expiration_signatures<B>(
vk: &VerificationKeyAuth,
expiration_date: u64,
expiration_date: EncodedDate,
signatures_shares: &[ExpirationDateSignatureShare<B>],
) -> Result<Vec<ExpirationDateSignature>>
where
@@ -314,7 +315,7 @@ where
/// It further annotates the result with timestamp information
pub fn aggregate_annotated_expiration_signatures(
vk: &VerificationKeyAuth,
expiration_date: u64,
expiration_date: EncodedDate,
signatures_shares: &[ExpirationDateSignatureShare<AnnotatedExpirationDateSignature>],
) -> Result<Vec<AnnotatedExpirationDateSignature>> {
// it's sufficient to just verify the first share as if the rest of them don't match,
@@ -332,7 +333,7 @@ pub fn aggregate_annotated_expiration_signatures(
return Err(CompactEcashError::ExpirationDateSignatureVerification);
}
let l = i as u64;
let l = i as u32;
let expected_spending = sig.expiration_timestamp
- ((constants::CRED_VALIDITY_PERIOD_DAYS - l - 1) * constants::SECONDS_PER_DAY);
@@ -361,7 +362,7 @@ pub fn aggregate_annotated_expiration_signatures(
/// It is expected the caller has already pre-validated them via manual calls to `verify_valid_dates_signatures`
pub fn unchecked_aggregate_expiration_signatures(
vk: &VerificationKeyAuth,
expiration_date: u64,
expiration_date: EncodedDate,
signatures_shares: &[ExpirationDateSignatureShare],
) -> Result<Vec<ExpirationDateSignature>> {
_aggregate_expiration_signatures(vk, expiration_date, signatures_shares, false)
@@ -383,13 +384,13 @@ pub fn unchecked_aggregate_expiration_signatures(
/// If a valid index is found, returns `Ok(index)`. If no valid index is found
/// (i.e., `spend_date` is earlier than `expiration_date - 30`), returns `Err(InvalidDateError)`.
///
pub fn find_index(spend_date: u64, expiration_date: u64) -> Result<usize> {
pub fn find_index(spend_date: EncodedDate, expiration_date: EncodedDate) -> Result<usize> {
let start_date =
expiration_date - ((constants::CRED_VALIDITY_PERIOD_DAYS - 1) * constants::SECONDS_PER_DAY);
if spend_date >= start_date {
let index_a = ((spend_date - start_date) / constants::SECONDS_PER_DAY) as usize;
if index_a as u64 >= constants::CRED_VALIDITY_PERIOD_DAYS {
if index_a as u32 >= constants::CRED_VALIDITY_PERIOD_DAYS {
Err(CompactEcashError::SpendDateTooLate)
} else {
Ok(index_a)
@@ -399,18 +400,6 @@ pub fn find_index(spend_date: u64, expiration_date: u64) -> Result<usize> {
}
}
pub fn date_scalar(date: u64) -> Scalar {
Scalar::from(date)
}
// TODO: this will not work for **all** scalars,
// but timestamps have extremely (relatively speaking) limited range,
// so this should be fine
pub fn scalar_date(scalar: &Scalar) -> u64 {
let b = scalar.to_bytes();
u64::from_le_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]])
}
#[cfg(test)]
mod tests {
use super::*;
@@ -54,7 +54,6 @@ pub fn identify(
#[cfg(test)]
mod tests {
use crate::scheme::expiration_date_signatures::date_scalar;
use crate::scheme::identify::{identify, IdentifyResult};
use crate::scheme::keygen::{PublicKeyUser, SecretKeyAuth, SecretKeyUser};
use crate::setup::Parameters;
@@ -165,12 +164,12 @@ mod tests {
.unwrap();
assert!(payment1
.spend_verify(&verification_key, &pay_info1, date_scalar(spend_date))
.spend_verify(&verification_key, &pay_info1, spend_date)
.is_ok());
let payment2 = payment1.clone();
assert!(payment2
.spend_verify(&verification_key, &pay_info1, date_scalar(spend_date))
.spend_verify(&verification_key, &pay_info1, spend_date)
.is_ok());
let identify_result = identify(&payment1, &payment2, pay_info1, pay_info1);
@@ -275,7 +274,7 @@ mod tests {
.unwrap();
assert!(payment1
.spend_verify(&verification_key, &pay_info1, date_scalar(spend_date))
.spend_verify(&verification_key, &pay_info1, spend_date)
.is_ok());
let pay_info2 = PayInfo {
@@ -295,7 +294,7 @@ mod tests {
.unwrap();
assert!(payment2
.spend_verify(&verification_key, &pay_info2, date_scalar(spend_date))
.spend_verify(&verification_key, &pay_info2, spend_date)
.is_ok());
let identify_result = identify(&payment1, &payment2, pay_info1, pay_info2);
@@ -411,7 +410,7 @@ mod tests {
.unwrap();
assert!(payment1
.spend_verify(&verification_key, &pay_info1, date_scalar(spend_date))
.spend_verify(&verification_key, &pay_info1, spend_date)
.is_ok());
// let's reverse the spending counter in the wallet to create a double spending payment
@@ -435,7 +434,7 @@ mod tests {
.unwrap();
assert!(payment2
.spend_verify(&verification_key, &pay_info2, date_scalar(spend_date))
.spend_verify(&verification_key, &pay_info2, spend_date)
.is_ok());
let identify_result = identify(&payment1, &payment2, pay_info1, pay_info2);
@@ -555,7 +554,7 @@ mod tests {
.unwrap();
assert!(payment1
.spend_verify(&verification_key, &pay_info1, date_scalar(spend_date))
.spend_verify(&verification_key, &pay_info1, spend_date)
.is_ok());
// let's reverse the spending counter in the wallet to create a double spending payment
@@ -97,10 +97,6 @@ impl SecretKeyAuth {
self.ys.len()
}
pub(crate) fn get_y_by_idx(&self, i: usize) -> Option<&Scalar> {
self.ys.get(i)
}
pub fn verification_key(&self) -> VerificationKeyAuth {
let params = ecash_group_parameters();
let g1 = params.gen1();
@@ -3,17 +3,18 @@
use crate::common_types::{Signature, SignerIndex};
use crate::error::{CompactEcashError, Result};
use crate::helpers::{date_scalar, type_scalar};
use crate::proofs::proof_spend::{SpendInstance, SpendProof, SpendWitness};
use crate::scheme::coin_indices_signatures::CoinIndexSignature;
use crate::scheme::expiration_date_signatures::{date_scalar, find_index, ExpirationDateSignature};
use crate::scheme::expiration_date_signatures::{find_index, ExpirationDateSignature};
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
use crate::scheme::setup::{GroupParameters, Parameters};
use crate::traits::Bytable;
use crate::utils::{
batch_verify_signatures, check_bilinear_pairing, hash_to_scalar, try_deserialize_scalar,
};
use crate::Base58;
use crate::{constants, ecash_group_parameters};
use crate::{Base58, EncodedDate, EncodedTicketType};
use bls12_381::{G1Projective, G2Prepared, G2Projective, Scalar};
use group::Curve;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
@@ -228,7 +229,7 @@ impl Wallet {
spend_value: u64,
valid_dates_signatures: &[ExpirationDateSignature],
coin_indices_signatures: &[CoinIndexSignature],
spend_date_timestamp: u64,
spend_date_timestamp: EncodedDate,
) -> Result<Payment> {
self.check_remaining_allowance(params, spend_value)?;
@@ -269,8 +270,8 @@ pub struct WalletSignatures {
#[zeroize(skip)]
sig: Signature,
v: Scalar,
expiration_date_timestamp: u64,
t_type: u64,
expiration_date_timestamp: EncodedDate,
t_type: EncodedTicketType,
}
impl WalletSignatures {
@@ -314,8 +315,8 @@ pub fn compute_pay_info_hash(pay_info: &PayInfo, k: u64) -> Scalar {
}
impl WalletSignatures {
// signature size (96) + secret size (32) + expiration size (8) + t_type (8)
pub const SERIALISED_SIZE: usize = 144;
// signature size (96) + secret size (32) + expiration size (4) + t_type (1)
pub const SERIALISED_SIZE: usize = 133;
pub fn signature(&self) -> &Signature {
&self.sig
@@ -335,8 +336,8 @@ impl WalletSignatures {
let mut bytes = [0u8; Self::SERIALISED_SIZE];
bytes[0..96].copy_from_slice(&self.sig.to_bytes());
bytes[96..128].copy_from_slice(&self.v.to_bytes());
bytes[128..136].copy_from_slice(&self.expiration_date_timestamp.to_be_bytes());
bytes[136..144].copy_from_slice(&self.t_type.to_be_bytes());
bytes[128..132].copy_from_slice(&self.expiration_date_timestamp.to_be_bytes());
bytes[132] = self.t_type;
bytes
}
@@ -356,15 +357,12 @@ impl WalletSignatures {
let v_bytes: &[u8; 32] = &bytes[96..128].try_into().unwrap();
#[allow(clippy::unwrap_used)]
let expiration_date_bytes = bytes[128..136].try_into().unwrap();
#[allow(clippy::unwrap_used)]
let t_type_bytes = bytes[136..].try_into().unwrap();
let expiration_date_bytes = bytes[128..132].try_into().unwrap();
let sig = Signature::try_from(sig_bytes.as_slice())?;
let v = Scalar::from_bytes(v_bytes).unwrap();
let expiration_date_timestamp = u64::from_be_bytes(expiration_date_bytes);
let t_type = u64::from_be_bytes(t_type_bytes);
let expiration_date_timestamp = EncodedDate::from_be_bytes(expiration_date_bytes);
let t_type = bytes[132];
Ok(WalletSignatures {
sig,
@@ -401,7 +399,7 @@ impl WalletSignatures {
spend_value: u64,
valid_dates_signatures: &[BE],
coin_indices_signatures: &[BI],
spend_date_timestamp: u64,
spend_date_timestamp: EncodedDate,
) -> Result<Payment>
where
BI: Borrow<CoinIndexSignature>,
@@ -596,7 +594,7 @@ fn pseudorandom_f_g_v(params: &GroupParameters, v: &Scalar, l: u64) -> Result<G1
/// * `params` - A reference to the group parameters required for the computation.
/// * `verification_key` - The global verification key of the signing authorities.
/// * `attributes` - A slice of private attributes associated with the wallet.
/// * `blinding_factor` - The blinding factor used used to randomise the wallet's signature.
/// * `blinding_factor` - The blinding factor used to randomise the wallet's signature.
///
/// # Returns
///
@@ -689,7 +687,7 @@ pub struct Payment {
pub aa: Vec<G1Projective>,
pub spend_value: u64,
pub cc: G1Projective,
pub t_type: u64,
pub t_type: EncodedTicketType,
pub zk_proof: SpendProof,
}
@@ -720,7 +718,7 @@ impl Payment {
return Err(CompactEcashError::SpendSignaturesValidity);
}
let kappa_type = self.kappa + verification_key.beta_g2[3] * Scalar::from(self.t_type);
let kappa_type = self.kappa + verification_key.beta_g2[3] * type_scalar(self.t_type);
if !check_bilinear_pairing(
&self.sig.h.to_affine(),
&G2Prepared::from(kappa_type.to_affine()),
@@ -950,7 +948,7 @@ impl Payment {
&self,
verification_key: &VerificationKeyAuth,
pay_info: &PayInfo,
spend_date: Scalar,
spend_date: EncodedDate,
) -> Result<()> {
// check if all serial numbers are different
self.no_duplicate_serial_numbers()?;
@@ -959,7 +957,7 @@ impl Payment {
// Verify whether the payment signature and kappa are correct
self.check_signature_validity(verification_key)?;
// Verify whether the expiration date signature and kappa_e are correct
self.check_exp_signature_validity(verification_key, spend_date)?;
self.check_exp_signature_validity(verification_key, date_scalar(spend_date))?;
// Verify whether the coin indices signatures and kappa_k are correct
self.batch_check_coin_index_signatures(verification_key)?;
@@ -3,6 +3,7 @@
use crate::common_types::{BlindedSignature, Signature, SignerIndex};
use crate::error::{CompactEcashError, Result};
use crate::helpers::{date_scalar, type_scalar};
use crate::proofs::proof_withdrawal::{
WithdrawalReqInstance, WithdrawalReqProof, WithdrawalReqWitness,
};
@@ -10,7 +11,7 @@ use crate::scheme::keygen::{PublicKeyUser, SecretKeyAuth, SecretKeyUser, Verific
use crate::scheme::setup::GroupParameters;
use crate::scheme::PartialWallet;
use crate::utils::{check_bilinear_pairing, hash_g1};
use crate::{constants, ecash_group_parameters, Attribute};
use crate::{constants, ecash_group_parameters, Attribute, EncodedDate, EncodedTicketType};
use bls12_381::{multi_miller_loop, G1Projective, G2Prepared, G2Projective, Scalar};
use group::{Curve, Group, GroupEncoding};
use serde::{Deserialize, Serialize};
@@ -141,28 +142,25 @@ fn compute_private_attribute_commitments(
/// openings for private attributes, `v`, and the expiration date.
pub fn withdrawal_request(
sk_user: &SecretKeyUser,
expiration_date: u64,
t_type: u64,
expiration_date: EncodedDate,
t_type: EncodedTicketType,
) -> Result<(WithdrawalRequest, RequestInfo)> {
let params = ecash_group_parameters();
// Generate random and unique wallet secret
let v = params.random_scalar();
let joined_commitment_opening = params.random_scalar();
let gamma = params.gammas();
let expiration_date = date_scalar(expiration_date);
let t_type = type_scalar(t_type);
// Compute joined commitment for all attributes (public and private)
//SAFETY: params is static with length 3
#[allow(clippy::unwrap_used)]
let joined_commitment: G1Projective = params.gen1() * joined_commitment_opening
+ params.gamma_idx(0).unwrap() * sk_user.sk
+ params.gamma_idx(1).unwrap() * v;
let joined_commitment =
params.gen1() * joined_commitment_opening + gamma[0] * sk_user.sk + gamma[1] * v;
// Compute commitment hash h
#[allow(clippy::unwrap_used)]
let joined_commitment_hash = hash_g1(
(joined_commitment
+ params.gamma_idx(2).unwrap() * Scalar::from(expiration_date)
+ params.gamma_idx(3).unwrap() * Scalar::from(t_type))
.to_bytes(),
);
let joined_commitment_hash =
hash_g1((joined_commitment + gamma[2] * expiration_date + gamma[3] * t_type).to_bytes());
// Compute Pedersen commitments for private attributes (wallet secret and user's secret)
let private_attributes = vec![sk_user.sk, v];
@@ -199,8 +197,8 @@ pub fn withdrawal_request(
joined_commitment_opening,
private_attributes_openings: private_attributes_openings.clone(),
wallet_secret: v,
expiration_date: Scalar::from(expiration_date),
t_type: Scalar::from(t_type),
expiration_date,
t_type,
},
))
}
@@ -222,18 +220,17 @@ pub fn withdrawal_request(
pub fn request_verify(
req: &WithdrawalRequest,
pk_user: PublicKeyUser,
expiration_date: u64,
t_type: u64,
expiration_date: EncodedDate,
t_type: EncodedTicketType,
) -> Result<()> {
let params = ecash_group_parameters();
// Verify the joined commitment hash
//SAFETY: params is static with length 3
#[allow(clippy::unwrap_used)]
let gamma = params.gammas();
let expiration_date = date_scalar(expiration_date);
let t_type = type_scalar(t_type);
let expected_commitment_hash = hash_g1(
(req.joined_commitment
+ params.gamma_idx(2).unwrap() * Scalar::from(expiration_date)
+ params.gamma_idx(3).unwrap() * Scalar::from(t_type))
.to_bytes(),
(req.joined_commitment + gamma[2] * expiration_date + gamma[3] * t_type).to_bytes(),
);
if req.joined_commitment_hash != expected_commitment_hash {
return Err(CompactEcashError::WithdrawalRequestVerification);
@@ -270,13 +267,10 @@ pub fn request_verify(
/// authentication secret key index is out of bounds.
fn sign_expiration_date(
joined_commitment_hash: &G1Projective,
expiration_date: u64,
expiration_date: EncodedDate,
sk_auth: &SecretKeyAuth,
) -> G1Projective {
//SAFETY : this fn assumes a long enough key
#[allow(clippy::unwrap_used)]
let yi = sk_auth.get_y_by_idx(2).unwrap();
joined_commitment_hash * (yi * Scalar::from(expiration_date))
joined_commitment_hash * (sk_auth.ys[2] * date_scalar(expiration_date))
}
/// Signs a transaction type using a joined commitment hash and a secret key.
@@ -296,13 +290,10 @@ fn sign_expiration_date(
/// The resulting G1Projective point representing the signed ticket type.
fn sign_t_type(
joined_commitment_hash: &G1Projective,
t_type: u64,
t_type: EncodedTicketType,
sk_auth: &SecretKeyAuth,
) -> G1Projective {
//SAFETY : this fn assumes a long enough key
#[allow(clippy::unwrap_used)]
let yi = sk_auth.get_y_by_idx(3).unwrap();
joined_commitment_hash * (yi * Scalar::from(t_type))
joined_commitment_hash * (sk_auth.ys[3] * type_scalar(t_type))
}
/// Issues a blinded signature for a withdrawal request, after verifying its integrity.
@@ -327,8 +318,8 @@ pub fn issue(
sk_auth: &SecretKeyAuth,
pk_user: PublicKeyUser,
withdrawal_req: &WithdrawalRequest,
expiration_date: u64,
t_type: u64,
expiration_date: EncodedDate,
t_type: EncodedTicketType,
) -> Result<BlindedSignature> {
// Verify the withdrawal request
request_verify(withdrawal_req, pk_user, expiration_date, t_type)?;
@@ -5,7 +5,6 @@
mod tests {
use crate::error::Result;
use crate::scheme::aggregation::{aggregate_verification_keys, aggregate_wallets};
use crate::scheme::expiration_date_signatures::date_scalar;
use crate::scheme::keygen::{
generate_keypair_user, ttp_keygen, SecretKeyAuth, VerificationKeyAuth,
};
@@ -125,7 +124,7 @@ mod tests {
)?;
assert!(payment
.spend_verify(&verification_key, &pay_info, date_scalar(spend_date))
.spend_verify(&verification_key, &pay_info, spend_date)
.is_ok());
let payment_bytes = payment.to_bytes();
@@ -15,12 +15,13 @@ use crate::scheme::Payment;
use crate::setup::Parameters;
use crate::{
aggregate_verification_keys, aggregate_wallets, constants, generate_keypair_user, issue,
issue_verify, withdrawal_request, PartialWallet, PayInfo, VerificationKeyAuth,
issue_verify, withdrawal_request, EncodedDate, EncodedTicketType, PartialWallet, PayInfo,
VerificationKeyAuth,
};
use itertools::izip;
pub fn generate_expiration_date_signatures(
expiration_date: u64,
expiration_date: EncodedDate,
secret_keys_authorities: &[&SecretKeyAuth],
verification_keys_auth: &[VerificationKeyAuth],
verification_key: &VerificationKeyAuth,
@@ -82,8 +83,8 @@ pub fn generate_coin_indices_signatures(
pub fn payment_from_keys_and_expiration_date(
ecash_keypairs: &Vec<KeyPairAuth>,
indices: &[SignerIndex],
expiration_date: u64,
t_type: u64,
expiration_date: EncodedDate,
t_type: EncodedTicketType,
) -> Result<(Payment, PayInfo)> {
let total_coins = 32;
let params = Parameters::new(total_coins);
@@ -402,8 +402,3 @@ mod tests {
assert_ne!(hash_to_scalar(msg1), hash_to_scalar(msg2));
}
}
pub fn scalar_type(scalar: &Scalar) -> u64 {
let b = scalar.to_bytes();
u64::from_le_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]])
}