signal_bridge/
nostr_identity.rs

1//! Nostr identity derivation from Signal Protocol keys
2//!
3//! This module handles deriving Nostr keypairs from Signal Protocol identity keys
4//! using HKDF, ensuring deterministic key generation.
5
6use crate::SignalBridgeError;
7use hkdf::Hkdf;
8use libsignal_protocol::{IdentityKey, IdentityKeyPair};
9use nostr::{Keys, PublicKey, SecretKey};
10use sha2::Sha256;
11
12/// Nostr identity derivation utilities
13pub struct NostrIdentity;
14
15impl NostrIdentity {
16    /// Derives complete Nostr keypair from Signal Protocol identity
17    ///
18    /// # Arguments
19    /// * `identity_key_pair` - Signal Protocol identity key pair
20    ///
21    /// # Returns
22    /// Nostr Keys containing both secret and public keys
23    pub fn derive_from_signal_identity(
24        identity_key_pair: &IdentityKeyPair,
25    ) -> Result<Keys, SignalBridgeError> {
26        let identity_public_key = identity_key_pair.identity_key();
27
28        let hk = Hkdf::<Sha256>::new(None, &identity_public_key.serialize());
29        let mut derived_key = [0u8; 32];
30        hk.expand(b"radix_relay_nostr_derivation", &mut derived_key)
31            .map_err(|_| SignalBridgeError::KeyDerivation("HKDF expansion failed".to_string()))?;
32
33        let secret_key = SecretKey::from_slice(&derived_key)
34            .map_err(|e| SignalBridgeError::KeyDerivation(format!("Invalid secret key: {}", e)))?;
35
36        Ok(Keys::new(secret_key))
37    }
38
39    /// Derives Nostr public key from peer's Signal Protocol identity
40    ///
41    /// # Arguments
42    /// * `peer_identity` - Peer's Signal Protocol identity key
43    ///
44    /// # Returns
45    /// Nostr public key derived using HKDF
46    pub fn derive_public_key_from_peer_identity(
47        peer_identity: &IdentityKey,
48    ) -> Result<PublicKey, SignalBridgeError> {
49        let hk = Hkdf::<Sha256>::new(None, &peer_identity.serialize());
50        let mut derived_key = [0u8; 32];
51        hk.expand(b"radix_relay_nostr_derivation", &mut derived_key)
52            .map_err(|_| SignalBridgeError::KeyDerivation("HKDF expansion failed".to_string()))?;
53
54        let secret_key = SecretKey::from_slice(&derived_key)
55            .map_err(|e| SignalBridgeError::KeyDerivation(format!("Invalid secret key: {}", e)))?;
56
57        let full_keys = Keys::new(secret_key);
58        Ok(full_keys.public_key())
59    }
60}