Skip to main content

vector_core/crypto/
signer.rs

1//! GuardedSigner — NostrSigner backed by a GuardedKey vault.
2//!
3//! Any client using nostr-sdk needs a signer. This implementation reads the
4//! secret key from the memory-hardened vault on every operation — the key
5//! exists in plaintext only for microseconds during signing.
6
7use nostr_sdk::prelude::*;
8
9/// A `NostrSigner` backed by the `MY_SECRET_KEY` vault.
10///
11/// The secret key is never stored in this struct — it's fetched from the
12/// GuardedKey vault on every operation and zeroized immediately after use.
13#[derive(Debug)]
14pub struct GuardedSigner {
15    public_key: PublicKey,
16}
17
18impl GuardedSigner {
19    pub fn new(public_key: PublicKey) -> Self {
20        Self { public_key }
21    }
22
23    fn temp_keys(&self) -> Result<Keys, SignerError> {
24        crate::state::MY_SECRET_KEY.to_keys()
25            .ok_or_else(|| SignerError::from("Secret key not available"))
26    }
27}
28
29impl NostrSigner for GuardedSigner {
30    fn backend(&self) -> SignerBackend<'_> {
31        SignerBackend::Keys
32    }
33
34    fn get_public_key(&self) -> BoxedFuture<'_, Result<PublicKey, SignerError>> {
35        let pk = self.public_key;
36        Box::pin(async move { Ok(pk) })
37    }
38
39    fn sign_event(&self, unsigned: UnsignedEvent) -> BoxedFuture<'_, Result<Event, SignerError>> {
40        let keys = self.temp_keys();
41        Box::pin(async move {
42            let keys = keys?;
43            unsigned.sign_with_keys(&keys).map_err(SignerError::backend)
44        })
45    }
46
47    fn nip04_encrypt<'a>(
48        &'a self, public_key: &'a PublicKey, content: &'a str,
49    ) -> BoxedFuture<'a, Result<String, SignerError>> {
50        let keys = self.temp_keys();
51        Box::pin(async move { let keys = keys?; keys.nip04_encrypt(public_key, content).await })
52    }
53
54    fn nip04_decrypt<'a>(
55        &'a self, public_key: &'a PublicKey, encrypted_content: &'a str,
56    ) -> BoxedFuture<'a, Result<String, SignerError>> {
57        let keys = self.temp_keys();
58        Box::pin(async move { let keys = keys?; keys.nip04_decrypt(public_key, encrypted_content).await })
59    }
60
61    fn nip44_encrypt<'a>(
62        &'a self, public_key: &'a PublicKey, content: &'a str,
63    ) -> BoxedFuture<'a, Result<String, SignerError>> {
64        let keys = self.temp_keys();
65        Box::pin(async move { let keys = keys?; keys.nip44_encrypt(public_key, content).await })
66    }
67
68    fn nip44_decrypt<'a>(
69        &'a self, public_key: &'a PublicKey, payload: &'a str,
70    ) -> BoxedFuture<'a, Result<String, SignerError>> {
71        let keys = self.temp_keys();
72        Box::pin(async move { let keys = keys?; keys.nip44_decrypt(public_key, payload).await })
73    }
74}