Skip to main content

cashu/nuts/nut01/
secret_key.rs

1use core::fmt;
2use core::ops::Deref;
3use core::str::FromStr;
4
5use bitcoin::hashes::sha256::Hash as Sha256Hash;
6use bitcoin::hashes::Hash;
7use bitcoin::secp256k1;
8use bitcoin::secp256k1::rand::rngs::OsRng;
9use bitcoin::secp256k1::schnorr::Signature;
10use bitcoin::secp256k1::{Keypair, Message, Scalar};
11use serde::de::Visitor;
12use serde::{Deserialize, Deserializer, Serialize};
13
14use super::{Error, PublicKey};
15use crate::SECP256K1;
16
17/// SecretKey
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct SecretKey {
20    inner: secp256k1::SecretKey,
21}
22
23impl Deref for SecretKey {
24    type Target = secp256k1::SecretKey;
25
26    fn deref(&self) -> &Self::Target {
27        &self.inner
28    }
29}
30
31impl From<secp256k1::SecretKey> for SecretKey {
32    fn from(inner: secp256k1::SecretKey) -> Self {
33        Self { inner }
34    }
35}
36
37impl fmt::Display for SecretKey {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        write!(f, "{}", self.to_secret_hex())
40    }
41}
42
43impl SecretKey {
44    /// Parse from `bytes`
45    pub fn from_slice(slice: &[u8]) -> Result<Self, Error> {
46        Ok(Self {
47            inner: secp256k1::SecretKey::from_slice(slice)?,
48        })
49    }
50
51    /// Parse from `hex` string
52    pub fn from_hex<S>(hex: S) -> Result<Self, Error>
53    where
54        S: AsRef<str>,
55    {
56        Ok(Self {
57            inner: secp256k1::SecretKey::from_str(hex.as_ref())?,
58        })
59    }
60
61    /// Generate random secret key
62    pub fn generate() -> Self {
63        let (secret_key, _) = SECP256K1.generate_keypair(&mut OsRng);
64        Self { inner: secret_key }
65    }
66
67    /// Get secret key as `hex` string
68    pub fn to_secret_hex(&self) -> String {
69        self.inner.display_secret().to_string()
70    }
71
72    /// Get secret key as `bytes`
73    pub fn as_secret_bytes(&self) -> &[u8] {
74        self.inner.as_ref()
75    }
76
77    /// Get secret key as `bytes`
78    pub fn to_secret_bytes(&self) -> [u8; 32] {
79        self.inner.secret_bytes()
80    }
81
82    /// Schnorr Signature on Message
83    pub fn sign(&self, msg: &[u8]) -> Result<Signature, Error> {
84        let hash: Sha256Hash = Sha256Hash::hash(msg);
85        let msg = Message::from_digest_slice(hash.as_ref())?;
86        Ok(SECP256K1.sign_schnorr(&msg, &Keypair::from_secret_key(&SECP256K1, &self.inner)))
87    }
88
89    /// Get public key
90    pub fn public_key(&self) -> PublicKey {
91        self.inner.public_key(&SECP256K1).into()
92    }
93
94    /// [`SecretKey`] to [`Scalar`]
95    #[inline]
96    pub fn to_scalar(self) -> Scalar {
97        Scalar::from(self.inner)
98    }
99
100    /// [`SecretKey`] as [`Scalar`]
101    #[inline]
102    pub fn as_scalar(&self) -> Scalar {
103        Scalar::from(self.inner)
104    }
105}
106
107impl FromStr for SecretKey {
108    type Err = Error;
109
110    /// Try to parse [SecretKey] from `hex` or `bech32`
111    fn from_str(secret_key: &str) -> Result<Self, Self::Err> {
112        Self::from_hex(secret_key)
113    }
114}
115
116impl Serialize for SecretKey {
117    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
118        match serializer.is_human_readable() {
119            // For human-readable formats like JSON, serialize as hex string
120            true => serializer.serialize_str(&self.to_secret_hex()),
121            // For binary formats like CBOR, use the bytes serialization
122            false => serializer.serialize_bytes(self.as_secret_bytes()),
123        }
124    }
125}
126
127impl<'de> Deserialize<'de> for SecretKey {
128    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
129        match deserializer.is_human_readable() {
130            // For human-readable formats like JSON, deserialize from hex string
131            true => {
132                let secret_key: String = String::deserialize(deserializer)?;
133                SecretKey::from_hex(secret_key).map_err(serde::de::Error::custom)
134            }
135            // For binary formats like CBOR, use the bytes deserialization
136            false => {
137                struct SecretKeyVisitor;
138
139                impl Visitor<'_> for SecretKeyVisitor {
140                    type Value = SecretKey;
141
142                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
143                        formatter.write_str("a byte array")
144                    }
145
146                    fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
147                    where
148                        E: serde::de::Error,
149                    {
150                        SecretKey::from_slice(value).map_err(serde::de::Error::custom)
151                    }
152                }
153
154                deserializer.deserialize_bytes(SecretKeyVisitor)
155            }
156        }
157    }
158}
159
160impl Drop for SecretKey {
161    fn drop(&mut self) {
162        self.inner.non_secure_erase();
163        tracing::trace!("Secret Key dropped.");
164    }
165}