From 36242fa2571ead3c09ceed3dcfa9701049e88ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 6 Feb 2024 17:58:21 +0000 Subject: [PATCH] serde for 'IssuanceBandwidthCredential' --- .../src/coconut/bandwidth/freepass.rs | 4 +- .../src/coconut/bandwidth/issuance.rs | 9 +++- .../src/coconut/bandwidth/voucher.rs | 4 +- common/credentials/src/coconut/utils.rs | 45 ++++++++----------- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/common/credentials/src/coconut/bandwidth/freepass.rs b/common/credentials/src/coconut/bandwidth/freepass.rs index d0e17ba55b..5783a8c25d 100644 --- a/common/credentials/src/coconut/bandwidth/freepass.rs +++ b/common/credentials/src/coconut/bandwidth/freepass.rs @@ -1,6 +1,7 @@ // Copyright 2024 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::coconut::utils::scalar_serde_helper; use nym_coconut_interface::{hash_to_scalar, Attribute, PublicAttribute}; use serde::{Deserialize, Serialize}; use time::{Duration, OffsetDateTime, Time}; @@ -29,13 +30,14 @@ impl FreePassIssuedData { } } -#[derive(Zeroize, ZeroizeOnDrop)] +#[derive(Zeroize, ZeroizeOnDrop, Serialize, Deserialize)] pub struct FreePassIssuanceData { /// the plain validity value of this credential expressed as unix timestamp #[zeroize(skip)] expiry_date: OffsetDateTime, // the expiry date, as unix timestamp, hashed into a scalar + #[serde(with = "scalar_serde_helper")] expiry_date_prehashed: PublicAttribute, } diff --git a/common/credentials/src/coconut/bandwidth/issuance.rs b/common/credentials/src/coconut/bandwidth/issuance.rs index ba694d37f8..36d540c493 100644 --- a/common/credentials/src/coconut/bandwidth/issuance.rs +++ b/common/credentials/src/coconut/bandwidth/issuance.rs @@ -7,6 +7,7 @@ use crate::coconut::bandwidth::voucher::BandwidthVoucherIssuanceData; use crate::coconut::bandwidth::{ bandwidth_voucher_params, CredentialSigningData, CredentialSpendingData, CredentialType, }; +use crate::coconut::utils::scalar_serde_helper; use crate::error::Error; use nym_coconut_interface::{ aggregate_signature_shares, hash_to_scalar, prepare_blind_sign, prove_bandwidth_credential, @@ -15,10 +16,11 @@ use nym_coconut_interface::{ }; use nym_crypto::asymmetric::{encryption, identity}; use nym_validator_client::nyxd::{Coin, Hash}; +use serde::{Deserialize, Serialize}; use time::OffsetDateTime; use zeroize::{Zeroize, ZeroizeOnDrop}; -#[derive(Zeroize, ZeroizeOnDrop)] +#[derive(Zeroize, ZeroizeOnDrop, Serialize, Deserialize)] pub enum BandwidthCredentialIssuanceDataVariant { Voucher(BandwidthVoucherIssuanceData), FreePass(FreePassIssuanceData), @@ -66,19 +68,22 @@ impl BandwidthCredentialIssuanceDataVariant { } // all types of bandwidth credentials contain serial number and binding number -#[derive(Zeroize, ZeroizeOnDrop)] +#[derive(Zeroize, ZeroizeOnDrop, Serialize, Deserialize)] pub struct IssuanceBandwidthCredential { // private attributes /// a random secret value generated by the client used for double-spending detection + #[serde(with = "scalar_serde_helper")] serial_number: PrivateAttribute, /// a random secret value generated by the client used to bind multiple credentials together + #[serde(with = "scalar_serde_helper")] binding_number: PrivateAttribute, /// data specific to given bandwidth credential, for example a value for bandwidth voucher and expiry date for the free pass variant_data: BandwidthCredentialIssuanceDataVariant, /// type of the bandwdith credential hashed onto a scalar + #[serde(with = "scalar_serde_helper")] type_prehashed: PublicAttribute, } diff --git a/common/credentials/src/coconut/bandwidth/voucher.rs b/common/credentials/src/coconut/bandwidth/voucher.rs index cce7726b60..06f88d2414 100644 --- a/common/credentials/src/coconut/bandwidth/voucher.rs +++ b/common/credentials/src/coconut/bandwidth/voucher.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::coconut::bandwidth::CredentialSigningData; +use crate::coconut::utils::scalar_serde_helper; use crate::error::Error; use nym_api_requests::coconut::BlindSignRequestBody; use nym_coconut_interface::{ @@ -34,7 +35,7 @@ impl BandwidthVoucherIssuedData { } } -#[derive(Zeroize, ZeroizeOnDrop)] +#[derive(Zeroize, ZeroizeOnDrop, Serialize, Deserialize)] pub struct BandwidthVoucherIssuanceData { /// the plain value (e.g., bandwidth) encoded in this voucher // note: for legacy reasons we're only using the value of the coin and ignoring the denom @@ -42,6 +43,7 @@ pub struct BandwidthVoucherIssuanceData { value: Coin, // note: as mentioned above, we're only hashing the value of the coin! + #[serde(with = "scalar_serde_helper")] value_prehashed: PublicAttribute, /// the hash of the deposit transaction diff --git a/common/credentials/src/coconut/utils.rs b/common/credentials/src/coconut/utils.rs index b1247881ff..2a59d0fc2d 100644 --- a/common/credentials/src/coconut/utils.rs +++ b/common/credentials/src/coconut/utils.rs @@ -75,31 +75,24 @@ pub async fn obtain_aggregate_signature( voucher.aggregate_signature_shares(&verification_key, &shares) } -// TODO: better type flow -#[allow(clippy::too_many_arguments)] -pub fn prepare_credential_for_spending( - params: &Parameters, - voucher_value: u64, - voucher_info: String, - serial_number: &Attribute, - binding_number: &Attribute, - epoch_id: u64, - signature: &Signature, - verification_key: &VerificationKey, -) -> Result { - let theta = prove_bandwidth_credential( - params, - verification_key, - signature, - serial_number, - binding_number, - )?; +pub(crate) mod scalar_serde_helper { + use bls12_381::Scalar; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + use zeroize::Zeroizing; - Ok(Credential::new( - IssuanceBandwidthCredential::ENCODED_ATTRIBUTES, - theta, - voucher_value, - voucher_info, - epoch_id, - )) + pub fn serialize(scalar: &Scalar, serializer: S) -> Result { + scalar.to_bytes().serialize(serializer) + } + + pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result { + let b = <[u8; 32]>::deserialize(deserializer)?; + + // make sure the bytes get zeroed + let bytes = Zeroizing::new(b); + + let maybe_scalar: Option = Scalar::from_bytes(&bytes).into(); + maybe_scalar.ok_or(serde::de::Error::custom( + "did not construct a valid bls12-381 scalar out of the provided bytes", + )) + } }