From 5461eb0dad80fe30dab9ea820c3ac9491936a2a6 Mon Sep 17 00:00:00 2001 From: thesimplekid Date: Wed, 27 Mar 2024 20:18:08 +0000 Subject: [PATCH] feat(NUT12): BlindedSignature and Proof DLEQ --- crates/cashu/src/dhke.rs | 5 ++--- crates/cashu/src/nuts/mod.rs | 2 +- crates/cashu/src/nuts/nut00.rs | 8 ++++---- crates/cashu/src/nuts/nut12.rs | 37 ++++++++++++++++++++++++---------- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/crates/cashu/src/dhke.rs b/crates/cashu/src/dhke.rs index 5e7159ba..a1512e74 100644 --- a/crates/cashu/src/dhke.rs +++ b/crates/cashu/src/dhke.rs @@ -134,10 +134,10 @@ mod wallet { #[cfg(feature = "nut12")] { let dleq = if let Some(dleq) = blinded_signature.dleq { - Some(DleqProof { + Some(ProofDleq { e: dleq.e, s: dleq.s, - r: Some(r), + r, }) } else { None @@ -391,7 +391,6 @@ mod tests { let sec = SecretKey::new(ScalarPrimitive::ONE); let (blinded_message, _r) = blind_message(message.as_bytes(), Some(sec)).unwrap(); - // A let bob_sec = SecretKey::new(ScalarPrimitive::ONE); diff --git a/crates/cashu/src/nuts/mod.rs b/crates/cashu/src/nuts/mod.rs index 6a23a458..23b1a50d 100644 --- a/crates/cashu/src/nuts/mod.rs +++ b/crates/cashu/src/nuts/mod.rs @@ -48,6 +48,6 @@ pub use nut10::{Kind, Secret as Nut10Secret, SecretData}; #[cfg(feature = "nut11")] pub use nut11::{P2PKConditions, SigFlag, Signatures, SigningKey, VerifyingKey}; #[cfg(feature = "nut12")] -pub use nut12::DleqProof; +pub use nut12::{BlindedSignatureDleq, ProofDleq}; pub type Proofs = Vec; diff --git a/crates/cashu/src/nuts/nut00.rs b/crates/cashu/src/nuts/nut00.rs index 8ecc17ed..a8b54892 100644 --- a/crates/cashu/src/nuts/nut00.rs +++ b/crates/cashu/src/nuts/nut00.rs @@ -8,7 +8,7 @@ use std::str::FromStr; use serde::{Deserialize, Serialize}; #[cfg(feature = "nut12")] -use super::DleqProof; +use super::{BlindedSignatureDleq, ProofDleq}; use super::{Id, Proofs, PublicKey}; use crate::error::Error; #[cfg(feature = "nut11")] @@ -27,7 +27,7 @@ pub struct BlindedMessage { /// Keyset Id #[serde(rename = "id")] pub keyset_id: Id, - /// encrypted secret message (B_) + /// Blinded secret message (B_) #[serde(rename = "B_")] pub b: PublicKey, /// Witness @@ -424,7 +424,7 @@ pub struct BlindedSignature { pub c: PublicKey, /// DLEQ Proof #[cfg(feature = "nut12")] - pub dleq: Option, + pub dleq: Option, } /// Proofs [NUT-00] @@ -450,7 +450,7 @@ pub struct Proof { pub witness: Option, /// DLEQ Proof #[cfg(feature = "nut12")] - pub dleq: Option, + pub dleq: Option, } impl Proof { diff --git a/crates/cashu/src/nuts/nut12.rs b/crates/cashu/src/nuts/nut12.rs index 437ef745..7e5d8d2d 100644 --- a/crates/cashu/src/nuts/nut12.rs +++ b/crates/cashu/src/nuts/nut12.rs @@ -26,11 +26,16 @@ pub enum Error { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct DleqProof { +pub struct BlindedSignatureDleq { pub e: SecretKey, pub s: SecretKey, - #[serde(skip_serializing_if = "Option::is_none")] - pub r: Option, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct ProofDleq { + pub e: SecretKey, + pub s: SecretKey, + pub r: SecretKey, } fn verify_dleq( @@ -74,7 +79,7 @@ fn calculate_dleq( blinded_signature: k256::PublicKey, blinded_message: &k256::PublicKey, mint_secretkey: &k256::SecretKey, -) -> Result { +) -> Result { // Random nonce let r: k256::SecretKey = SecretKey::random().into(); @@ -95,10 +100,9 @@ fn calculate_dleq( let s: k256::SecretKey = k256::SecretKey::new(s.into()); - Ok(DleqProof { + Ok(BlindedSignatureDleq { e: e_sk.into(), s: s.into(), - r: None, }) } @@ -106,11 +110,7 @@ impl Proof { pub fn verify_dleq(&self, mint_pubkey: &PublicKey) -> Result<(), Error> { let (e, s, blinding_factor): (k256::SecretKey, k256::SecretKey, k256::SecretKey) = if let Some(dleq) = self.dleq.clone() { - if let Some(r) = dleq.r { - (dleq.e.into(), dleq.s.into(), r.into()) - } else { - return Err(Error::IncompleteDleqProof); - } + (dleq.e.into(), dleq.s.into(), dleq.r.into()) } else { return Err(Error::MissingDleqProof); }; @@ -224,4 +224,19 @@ mod tests { blinded.verify_dleq(&mint_key, &blinded_secret).unwrap() } + + #[test] + fn test_proof_dleq() { + let proof = r#"{"amount": 1,"id": "00882760bfa2eb41","secret": "daf4dd00a2b68a0858a80450f52c8a7d2ccf87d375e43e216e0c571f089f63e9","C": "024369d2d22a80ecf78f3937da9d5f30c1b9f74f0c32684d583cca0fa6a61cdcfc","dleq": {"e": "b31e58ac6527f34975ffab13e70a48b6d2b0d35abc4b03f0151f09ee1a9763d4","s": "8fbae004c59e754d71df67e392b6ae4e29293113ddc2ec86592a0431d16306d8","r": "a6d13fcd7a18442e6076f5e1e7c887ad5de40a019824bdfa9fe740d302e8d861"}}"#; + + let proof: Proof = serde_json::from_str(proof).unwrap(); + + // A + let a: PublicKey = PublicKey::from_str( + "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + ) + .unwrap(); + + assert!(proof.verify_dleq(&a).is_ok()); + } }