feat: add NIP-04 and NIP-44 encrypt/decrypt RPC endpoints for iframe apps

Backend: identity.nostr-encrypt-nip04, identity.nostr-decrypt-nip04,
identity.nostr-encrypt-nip44, identity.nostr-decrypt-nip44 endpoints
with auto-resolve to default identity. Frontend: appLauncher routes
nip04.* and nip44.* postMessage calls to backend RPC.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-12 23:50:56 +00:00
co-authored by Claude Opus 4.6
parent 398e94b5d3
commit 3383b43a75
6 changed files with 170 additions and 2 deletions
+49
View File
@@ -288,6 +288,55 @@ impl IdentityManager {
Ok(sig.to_string())
}
/// Load the Nostr secret key for an identity, returning the parsed Keys.
async fn load_nostr_keys(&self, id: &str) -> Result<nostr_sdk::Keys> {
let file_path = self.identities_dir.join(format!("{}.json", id));
if !file_path.exists() {
return Err(anyhow::anyhow!("Identity not found: {}", id));
}
let data = fs::read(&file_path).await.context("Failed to read identity file")?;
let file: IdentityFile = serde_json::from_slice(&data).context("Failed to parse identity file")?;
let secret_hex = file.nostr_secret_hex
.ok_or_else(|| anyhow::anyhow!("No Nostr key for this identity"))?;
nostr_sdk::Keys::parse(&secret_hex).context("Invalid Nostr secret key")
}
/// NIP-04 encrypt plaintext for a peer pubkey.
pub async fn nostr_encrypt_nip04(&self, id: &str, peer_pubkey_hex: &str, plaintext: &str) -> Result<String> {
let keys = self.load_nostr_keys(id).await?;
let peer_pk = nostr_sdk::PublicKey::from_hex(peer_pubkey_hex)
.context("Invalid peer pubkey hex")?;
nostr_sdk::nips::nip04::encrypt(keys.secret_key(), &peer_pk, plaintext)
.context("NIP-04 encryption failed")
}
/// NIP-04 decrypt ciphertext from a peer pubkey.
pub async fn nostr_decrypt_nip04(&self, id: &str, peer_pubkey_hex: &str, ciphertext: &str) -> Result<String> {
let keys = self.load_nostr_keys(id).await?;
let peer_pk = nostr_sdk::PublicKey::from_hex(peer_pubkey_hex)
.context("Invalid peer pubkey hex")?;
nostr_sdk::nips::nip04::decrypt(keys.secret_key(), &peer_pk, ciphertext)
.context("NIP-04 decryption failed")
}
/// NIP-44 encrypt plaintext for a peer pubkey.
pub async fn nostr_encrypt_nip44(&self, id: &str, peer_pubkey_hex: &str, plaintext: &str) -> Result<String> {
let keys = self.load_nostr_keys(id).await?;
let peer_pk = nostr_sdk::PublicKey::from_hex(peer_pubkey_hex)
.context("Invalid peer pubkey hex")?;
nostr_sdk::nips::nip44::encrypt(keys.secret_key(), &peer_pk, plaintext, nostr_sdk::nips::nip44::Version::V2)
.context("NIP-44 encryption failed")
}
/// NIP-44 decrypt ciphertext from a peer pubkey.
pub async fn nostr_decrypt_nip44(&self, id: &str, peer_pubkey_hex: &str, ciphertext: &str) -> Result<String> {
let keys = self.load_nostr_keys(id).await?;
let peer_pk = nostr_sdk::PublicKey::from_hex(peer_pubkey_hex)
.context("Invalid peer pubkey hex")?;
nostr_sdk::nips::nip44::decrypt(keys.secret_key(), &peer_pk, ciphertext)
.context("NIP-44 decryption failed")
}
// --- internal helpers ---
}