Skip to main content

Nostr values and cryptography

This family establishes the trust boundary for keys, identifiers, events, and encrypted payloads. Parse once, keep the validated value, and preserve exact raw tag arrays—including trailing empty fields.

NIP-19 identifiers

Nip19Identifier parses and encodes the key, event, profile, and relay-hint forms used by Softchat. Mixed-case Bech32 is rejected. Unknown TLVs are retained where the typed representation supports them, so a read/write round trip does not silently discard extensions.

let identifier = Nip19Identifier::parse(encoded)?;
let canonical = identifier.encode()?;

Author a NIP-01 event

The caller supplies createdAt; the SDK never hides a clock in signing. Signing computes the canonical event ID from [0, pubkey, created_at, kind, tags, content] and produces a verified immutable event.

let draft = NostrEventDraft::new(
1_700_000_000,
NostrEventKind::SHORT_TEXT_NOTE,
vec![NostrTag::new([
"p".to_owned(),
recipient.to_hex(),
String::new(),
String::new(),
])?],
"hello",
)?;
let event = identity.sign_event(draft)?;
let received = SignedNostrEvent::from_json(&event.to_json()?)?;

Verify before use

Parsing a signed event checks canonical lowercase hex, the 512-KiB bound, portable kind and timestamp bounds, the recomputed event ID, and its Schnorr signature. A parsed event is authenticated; raw JSON is not.

NIP-44 v2

Encrypt UTF-8 with the sender identity and the validated recipient public key. The immutable result includes the algorithm, sender public key, and NIP-44 payload. Decryption maps authentication, padding, and decoding failures to one redacted error.

let encrypted = alice.encrypt_utf8(&bob_public, plaintext)?;
let plaintext = bob.decrypt_utf8(&encrypted)?;

The three accepted payload sizes show fixed crossing/crypto cost and scaling. Each card includes the frozen old-library comparison when an equivalent baseline exists.

Readers accept both legacy and current extended-length encodings. Writers remain compatible with released clients. Never expose distinct failures that could become a padding or authentication oracle.