diff --git a/crates/buzz-core/src/observer.rs b/crates/buzz-core/src/observer.rs index 8347bda054..1d358d48d2 100644 --- a/crates/buzz-core/src/observer.rs +++ b/crates/buzz-core/src/observer.rs @@ -21,8 +21,8 @@ pub const OBSERVER_FRAME_CONTROL: &str = "control"; pub const NIP44_MIN_CONTENT_LEN: usize = 132; /// Maximum NIP-44 v2 ciphertext length. pub const NIP44_MAX_CONTENT_LEN: usize = 87_472; -/// Maximum observer plaintext JSON size accepted by helpers. -pub const OBSERVER_MAX_PLAINTEXT_LEN: usize = 65_535; +/// Maximum observer plaintext JSON size accepted by the NIP-44 v2 codec. +pub const OBSERVER_MAX_PLAINTEXT_LEN: usize = 65_536 - 128; /// Errors returned by observer payload encryption/decryption helpers. #[derive(Debug, Error)] @@ -115,6 +115,12 @@ mod tests { use super::*; use nostr::{EventBuilder, Kind, Tag}; + const NIP44_V2_MAX_PLAINTEXT_LEN: usize = 65_536 - 128; + + fn json_string_with_serialized_len(len: usize) -> String { + "x".repeat(len - 2) + } + #[test] fn observer_payload_round_trips_with_nip44() { let sender = Keys::generate(); @@ -156,4 +162,32 @@ mod tests { Err(ObserverPayloadError::InvalidCiphertextLength(_)) )); } + + #[test] + fn observer_payload_accepts_largest_nip44_plaintext() { + let sender = Keys::generate(); + let recipient = Keys::generate(); + let payload = json_string_with_serialized_len(NIP44_V2_MAX_PLAINTEXT_LEN); + + encrypt_observer_payload(&sender, &recipient.public_key(), &payload) + .expect("encrypt maximum-size NIP-44 plaintext"); + } + + #[test] + fn observer_payload_rejects_plaintext_above_nip44_limit_before_encrypting() { + let sender = Keys::generate(); + let recipient = Keys::generate(); + let payload = json_string_with_serialized_len(NIP44_V2_MAX_PLAINTEXT_LEN + 1); + + let error = encrypt_observer_payload(&sender, &recipient.public_key(), &payload) + .expect_err("reject plaintext above the NIP-44 limit"); + + match error { + ObserverPayloadError::PlaintextTooLarge { max, got } => { + assert_eq!(max, NIP44_V2_MAX_PLAINTEXT_LEN); + assert_eq!(got, NIP44_V2_MAX_PLAINTEXT_LEN + 1); + } + other => panic!("expected PlaintextTooLarge, got {other:?}"), + } + } }