diff --git a/nym-api/nym-api-requests/src/coconut/models.rs b/nym-api/nym-api-requests/src/coconut/models.rs index 109fcbb2c9..0db4b4a9f1 100644 --- a/nym-api/nym-api-requests/src/coconut/models.rs +++ b/nym-api/nym-api-requests/src/coconut/models.rs @@ -135,7 +135,7 @@ pub struct FreePassRequest { // secp256k1 key associated with the admin account pub cosmos_pubkey: cosmrs::crypto::PublicKey, - pub inner_sign_request: BlindSignRequest, + pub inner_sign_request: WithdrawalRequest, // we need to include a nonce here to prevent replay attacks // (and not making the nym-api store the serial numbers of all issued credential) @@ -145,36 +145,33 @@ pub struct FreePassRequest { /// to prove the possession of the cosmos key/address pub nonce_signature: cosmrs::crypto::secp256k1::Signature, - pub public_attributes_plain: Vec, + pub ecash_pubkey: PublicKeyUser, + + pub expiration_date: u64, } impl FreePassRequest { pub fn new( cosmos_pubkey: cosmrs::crypto::PublicKey, - inner_sign_request: BlindSignRequest, + inner_sign_request: WithdrawalRequest, used_nonce: [u8; 16], nonce_signature: cosmrs::crypto::secp256k1::Signature, - public_attributes_plain: Vec, + ecash_pubkey: PublicKeyUser, + expiration_date: u64, ) -> Self { FreePassRequest { cosmos_pubkey, inner_sign_request, used_nonce, nonce_signature, - public_attributes_plain, + ecash_pubkey, + expiration_date, } } pub fn tendermint_pubkey(&self) -> tendermint::PublicKey { self.cosmos_pubkey.into() } - - pub fn public_attributes_hashed(&self) -> Vec { - self.public_attributes_plain - .iter() - .map(hash_to_scalar) - .collect() - } } #[derive(Serialize, Deserialize)] diff --git a/nym-api/src/coconut/api_routes/mod.rs b/nym-api/src/coconut/api_routes/mod.rs index d661f88a31..54b4e8658c 100644 --- a/nym-api/src/coconut/api_routes/mod.rs +++ b/nym-api/src/coconut/api_routes/mod.rs @@ -30,48 +30,6 @@ use time::OffsetDateTime; mod helpers; -fn validate_freepass_public_attributes(res: &FreePassRequest) -> Result<()> { - let public_attributes = &res.public_attributes_plain; - - if public_attributes.len() != IssuanceBandwidthCredential::PUBLIC_ATTRIBUTES as usize { - return Err(CoconutError::InvalidFreePassAttributes { - got: public_attributes.len(), - expected: IssuanceBandwidthCredential::PUBLIC_ATTRIBUTES as usize, - }); - } - - // SAFETY: we just ensured correct number of attributes - let expiry_raw = public_attributes.first().unwrap(); - let type_raw = public_attributes.get(1).unwrap(); - - let parsed_type = type_raw.parse::()?; - if parsed_type != CredentialType::FreePass { - return Err(CoconutError::InvalidFreePassTypeAttribute { got: parsed_type }); - } - - let expiry_timestamp: i64 = expiry_raw - .parse() - .map_err(|source| CoconutError::ExpiryDateParsingFailure { source })?; - - let expiry_date = OffsetDateTime::from_unix_timestamp(expiry_timestamp).map_err(|source| { - CoconutError::InvalidExpiryDate { - unix_timestamp: expiry_timestamp, - source, - } - })?; - let now = OffsetDateTime::now_utc(); - - if expiry_date > now + MAX_FREE_PASS_VALIDITY { - return Err(CoconutError::TooLongFreePass { expiry_date }); - } - - if expiry_date < now { - return Err(CoconutError::FreePassExpiryInThePast { expiry_date }); - } - - Ok(()) -} - #[get("/free-pass-nonce")] pub async fn get_current_free_pass_nonce( state: &RocketState, @@ -94,7 +52,16 @@ pub async fn post_free_pass( debug!("Received free pass sign request"); trace!("body: {:?}", freepass_request_body); - validate_freepass_public_attributes(&freepass_request_body)?; + //check expiration date validity + if freepass_request_body.expiration_date > freepass_exp_date_timestamp() { + return Err(CoconutError::TooLongFreePass { + expiry_date: OffsetDateTime::from_unix_timestamp( + //safety : expiration date is a unix timestamp so these unwraps will not fail for 290 million years + freepass_request_body.expiration_date.try_into().unwrap(), + ) + .unwrap(), + }); + } // grab the admin of the bandwidth contract let Some(authorised_admin) = state.get_bandwidth_contract_admin().await? else { @@ -161,8 +128,10 @@ pub async fn post_free_pass( // produce the partial signature debug!("producing the partial credential"); - let blinded_signature = - blind_sign(freepass_request_body.deref(), signing_key.keys.secret_key())?; + let blinded_signature = blind_sign( + freepass_request_body.deref(), + &signing_key.keys.secret_key(), + )?; // update the number of issued free passes state.storage.increment_issued_freepasses().await?; diff --git a/nym-api/src/coconut/helpers.rs b/nym-api/src/coconut/helpers.rs index bb1692a321..47ed2fa3b6 100644 --- a/nym-api/src/coconut/helpers.rs +++ b/nym-api/src/coconut/helpers.rs @@ -51,12 +51,16 @@ impl CredentialRequest for BlindSignRequestBody { } impl CredentialRequest for FreePassRequest { - fn blind_sign_request(&self) -> &BlindSignRequest { + fn withdrawal_request(&self) -> &WithdrawalRequest { &self.inner_sign_request } - fn public_attributes(&self) -> Vec { - self.public_attributes_hashed() + fn expiration_date(&self) -> u64 { + self.expiration_date + } + + fn ecash_pubkey(&self) -> PublicKeyUser { + self.ecash_pubkey.clone() } }