From 40472cecb3ed03108f76c77239f4a69188e12df7 Mon Sep 17 00:00:00 2001 From: thesimplekid Date: Sat, 9 Sep 2023 07:53:01 +0100 Subject: [PATCH] `cashu` improve: add secret type --- crates/cashu/src/dhke.rs | 10 +++++----- crates/cashu/src/lib.rs | 1 + crates/cashu/src/nuts/nut00.rs | 18 ++++++++---------- crates/cashu/src/secret.rs | 34 ++++++++++++++++++++++++++++++++++ crates/cashu/src/utils.rs | 9 --------- 5 files changed, 48 insertions(+), 24 deletions(-) create mode 100644 crates/cashu/src/secret.rs diff --git a/crates/cashu/src/dhke.rs b/crates/cashu/src/dhke.rs index da75cc42..cb1625ab 100644 --- a/crates/cashu/src/dhke.rs +++ b/crates/cashu/src/dhke.rs @@ -11,6 +11,7 @@ use k256::ProjectivePoint; use k256::{Scalar, SecretKey}; use crate::error; +use crate::secret::Secret; #[cfg(feature = "wallet")] use crate::nuts::nut00::{BlindedSignature, Proof, Proofs}; @@ -81,7 +82,7 @@ pub fn unblind_message( pub fn construct_proofs( promises: Vec, rs: Vec, - secrets: Vec, + secrets: Vec, keys: &Keys, ) -> Result { let mut proofs = vec![]; @@ -127,7 +128,7 @@ pub fn sign_message( pub fn verify_message( a: SecretKey, unblinded_message: k256::PublicKey, - msg: &str, + msg: Secret, ) -> Result<(), error::mint::Error> { // Y let y = hash_to_curve(msg.as_bytes()); @@ -148,7 +149,6 @@ mod tests { use k256::elliptic_curve::scalar::ScalarPrimitive; use super::*; - use crate::utils::generate_secret; #[test] fn test_hash_to_curve() { @@ -259,7 +259,7 @@ mod tests { // let alice_sec = SecretKey::random(&mut rand::thread_rng()); - let x = generate_secret(); + let x = Secret::new(); // Y let y = hash_to_curve(x.as_bytes()); @@ -273,6 +273,6 @@ mod tests { // C let c = unblind_message(signed.into(), blinded.1, bob_pub.into()).unwrap(); - assert!(verify_message(bob_sec, c.into(), &x).is_ok()); + assert!(verify_message(bob_sec, c.into(), x).is_ok()); } } diff --git a/crates/cashu/src/lib.rs b/crates/cashu/src/lib.rs index 035a4252..ee9c0090 100644 --- a/crates/cashu/src/lib.rs +++ b/crates/cashu/src/lib.rs @@ -3,6 +3,7 @@ pub mod amount; pub mod dhke; pub mod error; pub mod nuts; +pub mod secret; pub mod serde_utils; pub mod types; pub mod utils; diff --git a/crates/cashu/src/nuts/nut00.rs b/crates/cashu/src/nuts/nut00.rs index 8da8032e..80934d58 100644 --- a/crates/cashu/src/nuts/nut00.rs +++ b/crates/cashu/src/nuts/nut00.rs @@ -3,8 +3,8 @@ use url::Url; -use crate::serde_utils::serde_url; use crate::Amount; +use crate::{secret::Secret, serde_utils::serde_url}; use serde::{Deserialize, Serialize}; use super::nut01::PublicKey; @@ -32,7 +32,7 @@ pub mod wallet { use crate::nuts::nut00::BlindedMessage; use crate::nuts::nut00::Proofs; use crate::nuts::nut01; - use crate::utils::generate_secret; + use crate::secret::Secret; use crate::Amount; use crate::{dhke::blind_message, utils::split_amount}; @@ -44,7 +44,7 @@ pub mod wallet { /// Blinded messages pub blinded_messages: Vec, /// Secrets - pub secrets: Vec, + pub secrets: Vec, /// Rs pub rs: Vec, /// Amounts @@ -57,7 +57,7 @@ pub mod wallet { let mut blinded_messages = BlindedMessages::default(); for amount in split_amount(amount) { - let secret = generate_secret(); + let secret = Secret::new(); let (blinded, r) = blind_message(secret.as_bytes(), None)?; let blinded_message = BlindedMessage { amount, b: blinded }; @@ -84,7 +84,7 @@ pub mod wallet { .max(1); for _i in 0..count { - let secret = generate_secret(); + let secret = Secret::new(); let (blinded, r) = blind_message(secret.as_bytes(), None)?; let blinded_message = BlindedMessage { @@ -195,8 +195,7 @@ pub struct Proof { /// Amount in satoshi pub amount: Amount, /// Secret message - // #[serde(with = "crate::serde_utils::bytes_base64")] - pub secret: String, + pub secret: Secret, /// Unblinded signature #[serde(rename = "C")] pub c: PublicKey, @@ -221,7 +220,7 @@ impl From for mint::Proof { pub mod mint { use serde::{Deserialize, Serialize}; - use crate::Amount; + use crate::{secret::Secret, Amount}; use super::PublicKey; @@ -231,8 +230,7 @@ pub mod mint { /// Amount in satoshi pub amount: Option, /// Secret message - // #[serde(with = "crate::serde_utils::bytes_base64")] - pub secret: String, + pub secret: Secret, /// Unblinded signature #[serde(rename = "C")] pub c: Option, diff --git a/crates/cashu/src/secret.rs b/crates/cashu/src/secret.rs new file mode 100644 index 00000000..8824a5a3 --- /dev/null +++ b/crates/cashu/src/secret.rs @@ -0,0 +1,34 @@ +// MIT License +// Copyright (c) 2023 Clark Moody +// https://github.com/clarkmoody/cashu-rs/blob/master/src/secret.rs + +use serde::{Deserialize, Serialize}; + +/// The secret data that allows spending ecash +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] +#[serde(transparent)] +pub struct Secret(String); + +impl Secret { + const BIT_LENGTH: usize = 128; + + /// Create secret value + pub fn new() -> Self { + use base64::{engine::general_purpose::URL_SAFE, Engine as _}; + use rand::RngCore; + + let mut rng = rand::thread_rng(); + + let mut random_bytes = [0u8; Self::BIT_LENGTH / 8]; + + // Generate random bytes + rng.fill_bytes(&mut random_bytes); + // The secret string is Base64-encoded + let secret = URL_SAFE.encode(random_bytes); + Self(secret) + } + + pub fn as_bytes(&self) -> &[u8] { + self.0.as_bytes() + } +} diff --git a/crates/cashu/src/utils.rs b/crates/cashu/src/utils.rs index 8c98177b..33717133 100644 --- a/crates/cashu/src/utils.rs +++ b/crates/cashu/src/utils.rs @@ -1,6 +1,5 @@ //! Utils -use base64::{engine::general_purpose, Engine as _}; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::Hash; use rand::prelude::*; @@ -29,14 +28,6 @@ pub fn extract_url_from_error(error: &str) -> Option { None } -/// Generate Secret Message -pub fn generate_secret() -> String { - let mut rng = rand::thread_rng(); - let mut secret = [0u8; 32]; - rng.fill_bytes(&mut secret); - general_purpose::STANDARD.encode(secret) -} - pub fn random_hash() -> Vec { let mut rng = rand::thread_rng(); let mut random_bytes = [0u8; Sha256::LEN];