Why NIP-17?
NIP-17 improves on NIP-04 by:- Metadata Privacy: Random timestamps and throwaway keys hide sender identity
- No Plaintext Tags: Recipient info is encrypted in the seal layer
- Self-Copies: Retrieve your own sent messages from relays
- Multiple Recipients: Support for group messaging (future)
NIP-04 vs NIP-17 Comparison
Three-Layer Encryption
NIP-17 uses a “gift wrap” protocol with three nested layers:1. Rumor (Kind 14)
The innermost layer containing the actual message. It’s unsigned and includes:2. Seal (Kind 13)
The middle layer that encrypts the rumor with NIP-44 using the sender’s real key:3. Gift Wrap (Kind 1059)
The outermost layer that hides the sender identity:Only the gift wrap (kind 1059) is published to relays. The seal and rumor are nested inside.
Implementation
Building Gift-Wrapped Messages
Building with Self-Copy
To retrieve your own sent messages, create two gift wraps from the same rumor:Both wraps share the same rumor with the recipient’s pubkey in the
p tag. This is per the NIP-17 spec.Unwrapping Received Messages
UserMessagesScreen
The main DM interface is implemented inUserMessagesScreen.tsx:
Features
- NIP-17 Subscription: Listens for kind 1059 events addressed to your pubkey
- Automatic Decryption: Unwraps messages as they arrive
- Optimistic Updates: Shows sent messages immediately
- Read Receipts: Checkmarks for sent/delivered status
- Token Detection: Extracts and displays Cashu tokens inline
Subscribing to DMs
Unwrapping and Filtering
Sending Messages
useNostrDirectMessage Hook
For sending DMs from anywhere in the app:Hook API
Relay Selection
The hook publishes to multiple relays for reliability:Message Components
Text Messages
Cashu Token Messages
Sovran automatically detects and displays Cashu tokens in messages:NIP-44 Encryption
NIP-17 uses NIP-44 for encryption (not NIP-04):- Authenticated encryption: Prevents tampering
- Nonce handling: Better randomness management
- Standard compliance: Uses established crypto primitives
Metadata Privacy
Random Timestamps
Timestamps are randomized within a 2-day window to prevent timing analysis:Throwaway Keys
Each gift wrap uses a fresh random keypair:- ✅ Recipient pubkey (from
ptag) - ❌ Sender pubkey (hidden by throwaway key)
- ❌ Message content (encrypted)
- ❌ Timestamp (randomized)
Best Practices
Always publish self-copies
Always publish self-copies
Handle decryption failures
Handle decryption failures
Filter by conversation
Filter by conversation
Deduplicate messages
Deduplicate messages
Migration from NIP-04
Sovran still reads legacy NIP-04 DMs but never sends them:Related Documentation
Identity & Keys
NIP-06 key derivation for message signing
Contacts
Contact lists populated from DM activity
User Profiles
Profile metadata for message senders
Cashu Tokens
Sending ecash via direct messages