radrootsd

JSON-RPC bridge for Radroots event publishing
git clone https://radroots.dev/git/radrootsd.git
Log | Files | Refs | README | LICENSE

protocol.rs (1988B)


      1 #![forbid(unsafe_code)]
      2 
      3 use crate::host_nostr::{Keys, PublicKey};
      4 use nostr::nips::nip46::NostrConnectMessage;
      5 use nostr::{Event, EventBuilder};
      6 
      7 /// Encrypts and locally signs a NIP-46 transport message.
      8 ///
      9 /// The completed event is returned for transport-only publication. NIP-46
     10 /// kind 24133 is protocol traffic, not a generic Radroots product-authoring
     11 /// surface.
     12 pub(crate) fn sign_nip46_message(
     13     sender_keys: &Keys,
     14     receiver_pubkey: PublicKey,
     15     message: NostrConnectMessage,
     16 ) -> Result<Event, nostr::event::builder::Error> {
     17     EventBuilder::nostr_connect(sender_keys, receiver_pubkey, message)?.sign_with_keys(sender_keys)
     18 }
     19 
     20 #[cfg(test)]
     21 mod tests {
     22     use crate::host_nostr::{Keys, Kind};
     23     use nostr::JsonUtil;
     24     use nostr::nips::{nip44, nip46::NostrConnectRequest};
     25 
     26     use super::sign_nip46_message;
     27 
     28     #[test]
     29     fn signed_nip46_message_is_bound_to_sender_and_receiver() {
     30         let sender = Keys::generate();
     31         let receiver = Keys::generate();
     32         let message = nostr::nips::nip46::NostrConnectMessage::request(&NostrConnectRequest::Ping);
     33         let request_id = message.id().to_owned();
     34 
     35         let event = sign_nip46_message(&sender, receiver.public_key(), message)
     36             .expect("signed NIP-46 message");
     37 
     38         assert_eq!(event.kind, Kind::NostrConnect);
     39         assert_eq!(event.pubkey, sender.public_key());
     40         assert!(
     41             event
     42                 .tags
     43                 .iter()
     44                 .any(|tag| { tag.as_slice() == ["p".to_owned(), receiver.public_key().to_hex()] })
     45         );
     46         assert!(event.verify().is_ok());
     47 
     48         let plaintext = nip44::decrypt(receiver.secret_key(), &sender.public_key(), &event.content)
     49             .expect("decrypt NIP-46 message");
     50         let decrypted = nostr::nips::nip46::NostrConnectMessage::from_json(plaintext)
     51             .expect("parse NIP-46 message");
     52         assert!(decrypted.is_request());
     53         assert_eq!(decrypted.id(), request_id);
     54     }
     55 }