nostr_types/types/
key_signer.rs

1use crate::{
2    ContentEncryptionAlgorithm, EncryptedPrivateKey, Error, Event, ExportableSigner, Id,
3    KeySecurity, LockableSigner, PreEvent, PrivateKey, PublicKey, Signature, Signer, SignerExt,
4};
5use async_trait::async_trait;
6use serde::de::Error as DeError;
7use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
8use serde::ser::{Serialize, SerializeSeq, Serializer};
9use std::fmt;
10use std::sync::RwLock;
11
12/// Signer with a local private key (and public key)
13pub struct KeySigner {
14    public_key: PublicKey,
15    encrypted_private_key: RwLock<EncryptedPrivateKey>,
16    private_key: RwLock<Option<PrivateKey>>,
17}
18
19impl fmt::Debug for KeySigner {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
21        f.debug_struct("KeySigner")
22            .field(
23                "encrypted_private_key",
24                &*self.encrypted_private_key.read().unwrap(),
25            )
26            .field("public_key", &self.public_key)
27            .finish()
28    }
29}
30
31impl KeySigner {
32    /// Create a Signer from an `EncryptedPrivateKey`
33    pub fn from_locked_parts(epk: EncryptedPrivateKey, pk: PublicKey) -> Self {
34        Self {
35            public_key: pk,
36            encrypted_private_key: RwLock::new(epk),
37            private_key: RwLock::new(None),
38        }
39    }
40
41    /// Create a Signer from a `PrivateKey`
42    pub fn from_private_key(privk: PrivateKey, password: &str, log_n: u8) -> Result<Self, Error> {
43        let epk = privk.export_encrypted(password, log_n)?;
44        Ok(Self {
45            public_key: privk.public_key(),
46            encrypted_private_key: RwLock::new(epk),
47            private_key: RwLock::new(Some(privk)),
48        })
49    }
50
51    /// Create a Signer from an `EncryptedPrivateKey` and a password to unlock it
52    pub fn from_encrypted_private_key(epk: EncryptedPrivateKey, pass: &str) -> Result<Self, Error> {
53        let priv_key = epk.decrypt(pass)?;
54        let pub_key = priv_key.public_key();
55        Ok(Self {
56            encrypted_private_key: RwLock::new(epk),
57            public_key: pub_key,
58            private_key: RwLock::new(Some(priv_key)),
59        })
60    }
61
62    /// Create a Signer by generating a new `PrivateKey`
63    pub fn generate(password: &str, log_n: u8) -> Result<Self, Error> {
64        let privk = PrivateKey::generate();
65        let epk = privk.export_encrypted(password, log_n)?;
66        Ok(Self {
67            public_key: privk.public_key(),
68            encrypted_private_key: RwLock::new(epk),
69            private_key: RwLock::new(Some(privk)),
70        })
71    }
72}
73
74#[async_trait]
75impl Signer for KeySigner {
76    fn public_key(&self) -> PublicKey {
77        self.public_key
78    }
79
80    fn encrypted_private_key(&self) -> Option<EncryptedPrivateKey> {
81        Some(self.encrypted_private_key.read().unwrap().clone())
82    }
83
84    async fn sign_event(&self, input: PreEvent) -> Result<Event, Error> {
85        // Verify the pubkey matches
86        if input.pubkey != self.public_key() {
87            return Err(Error::InvalidPrivateKey);
88        }
89
90        // Generate Id
91        let id = input.hash()?;
92
93        // Generate Signature
94        let signature = self.sign_id(id).await?;
95
96        Ok(Event {
97            id,
98            pubkey: input.pubkey,
99            created_at: input.created_at,
100            kind: input.kind,
101            tags: input.tags,
102            content: input.content,
103            sig: signature,
104        })
105    }
106
107    async fn encrypt(
108        &self,
109        other: &PublicKey,
110        plaintext: &str,
111        algo: ContentEncryptionAlgorithm,
112    ) -> Result<String, Error> {
113        match &*self.private_key.read().unwrap() {
114            Some(pk) => pk.encrypt(other, plaintext, algo),
115            None => Err(Error::SignerIsLocked),
116        }
117    }
118
119    async fn decrypt(&self, other: &PublicKey, ciphertext: &str) -> Result<String, Error> {
120        match &*self.private_key.read().unwrap() {
121            Some(pk) => pk.decrypt(other, ciphertext),
122            None => Err(Error::SignerIsLocked),
123        }
124    }
125
126    fn key_security(&self) -> Result<KeySecurity, Error> {
127        match &*self.private_key.read().unwrap() {
128            Some(pk) => Ok(pk.key_security()),
129            None => Err(Error::SignerIsLocked),
130        }
131    }
132}
133
134#[async_trait]
135impl SignerExt for KeySigner {
136    async fn sign_id(&self, id: Id) -> Result<Signature, Error> {
137        let Some(pk) = self.private_key.read().unwrap().clone() else {
138            return Err(Error::SignerIsLocked);
139        };
140        pk.sign_id(id).await
141    }
142
143    async fn sign(&self, message: &[u8]) -> Result<Signature, Error> {
144        let Some(pk) = self.private_key.read().unwrap().clone() else {
145            return Err(Error::SignerIsLocked);
146        };
147        pk.sign(message).await
148    }
149
150    async fn nip44_conversation_key(&self, other: &PublicKey) -> Result<[u8; 32], Error> {
151        let xpub = other.as_xonly_public_key();
152        match &*self.private_key.read().unwrap() {
153            Some(pk) => Ok(nip44::get_conversation_key(pk.as_secret_key(), xpub)),
154            None => Err(Error::SignerIsLocked),
155        }
156    }
157}
158
159impl LockableSigner for KeySigner {
160    fn is_locked(&self) -> bool {
161        self.private_key.read().unwrap().is_none()
162    }
163
164    fn unlock(&self, password: &str) -> Result<(), Error> {
165        if !self.is_locked() {
166            return Ok(());
167        }
168
169        let private_key = self
170            .encrypted_private_key
171            .read()
172            .unwrap()
173            .decrypt(password)?;
174
175        *self.private_key.write().unwrap() = Some(private_key);
176
177        Ok(())
178    }
179
180    fn lock(&self) {
181        *self.private_key.write().unwrap() = None;
182    }
183
184    fn change_passphrase(&self, old: &str, new: &str, log_n: u8) -> Result<(), Error> {
185        let private_key = self.encrypted_private_key.read().unwrap().decrypt(old)?;
186        *self.encrypted_private_key.write().unwrap() = private_key.export_encrypted(new, log_n)?;
187        *self.private_key.write().unwrap() = Some(private_key);
188        Ok(())
189    }
190
191    fn upgrade(&self, pass: &str, log_n: u8) -> Result<(), Error> {
192        let private_key = self.encrypted_private_key.read().unwrap().decrypt(pass)?;
193        *self.encrypted_private_key.write().unwrap() = private_key.export_encrypted(pass, log_n)?;
194        Ok(())
195    }
196}
197
198#[async_trait]
199impl ExportableSigner for KeySigner {
200    async fn export_private_key_in_hex(
201        &self,
202        pass: &str,
203        log_n: u8,
204    ) -> Result<(String, bool), Error> {
205        if let Some(ref mut pk) = *self.private_key.write().unwrap() {
206            // Test password and check key security
207            let pkcheck = self.encrypted_private_key.read().unwrap().decrypt(pass)?;
208
209            // side effect: this may downgrade the key security of self.private_key
210            let output = pk.as_hex_string();
211
212            // If key security changed, re-export
213            let mut downgraded = false;
214            if pk.key_security() != pkcheck.key_security() {
215                downgraded = true;
216                *self.encrypted_private_key.write().unwrap() = pk.export_encrypted(pass, log_n)?;
217            }
218            Ok((output, downgraded))
219        } else {
220            Err(Error::SignerIsLocked)
221        }
222    }
223
224    async fn export_private_key_in_bech32(
225        &self,
226        pass: &str,
227        log_n: u8,
228    ) -> Result<(String, bool), Error> {
229        if let Some(ref mut pk) = *self.private_key.write().unwrap() {
230            // Test password and check key security
231            let pkcheck = self.encrypted_private_key.read().unwrap().decrypt(pass)?;
232
233            // side effect: this may downgrade the key security of self.private_key
234            let output = pk.as_bech32_string();
235
236            // If key security changed, re-export
237            let mut downgraded = false;
238            if pk.key_security() != pkcheck.key_security() {
239                downgraded = true;
240                *self.encrypted_private_key.write().unwrap() = pk.export_encrypted(pass, log_n)?;
241            }
242
243            Ok((output, downgraded))
244        } else {
245            Err(Error::SignerIsLocked)
246        }
247    }
248}
249
250impl Serialize for KeySigner {
251    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
252    where
253        S: Serializer,
254    {
255        let mut seq = serializer.serialize_seq(Some(2))?;
256        seq.serialize_element(&self.public_key)?;
257        seq.serialize_element(&*self.encrypted_private_key.read().unwrap())?;
258        seq.end()
259    }
260}
261
262impl<'de> Deserialize<'de> for KeySigner {
263    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
264    where
265        D: Deserializer<'de>,
266    {
267        deserializer.deserialize_seq(KeySignerVisitor)
268    }
269}
270
271struct KeySignerVisitor;
272
273impl<'de> Visitor<'de> for KeySignerVisitor {
274    type Value = KeySigner;
275
276    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
277        write!(f, "a key signer structure as a sequence")
278    }
279
280    fn visit_seq<A>(self, mut access: A) -> Result<KeySigner, A::Error>
281    where
282        A: SeqAccess<'de>,
283    {
284        let public_key = access
285            .next_element::<PublicKey>()?
286            .ok_or_else(|| DeError::custom("Missing or invalid pubkey"))?;
287        let epk = access
288            .next_element::<EncryptedPrivateKey>()?
289            .ok_or_else(|| DeError::custom("Missing or invalid epk"))?;
290
291        Ok(KeySigner {
292            public_key,
293            encrypted_private_key: RwLock::new(epk),
294            private_key: RwLock::new(None),
295        })
296    }
297}
298
299#[cfg(test)]
300mod test {
301    use super::*;
302
303    #[test]
304    fn test_key_signer_serde() {
305        let ks = KeySigner::generate("password", 16).unwrap();
306        let s = serde_json::to_string(&ks).unwrap();
307        println!("{s}");
308        let ks2: KeySigner = serde_json::from_str(&s).unwrap();
309        assert_eq!(ks.public_key, ks2.public_key);
310        assert_eq!(
311            *ks.encrypted_private_key.read().unwrap(),
312            *ks2.encrypted_private_key.read().unwrap()
313        );
314    }
315}