NIP-04
Encrypted Direct Message
final unrecommended
optional relay
A special event with kind 4, meaning “encrypted
direct message”. It is supposed to have the following
attributes:
content MUST be equal to the
base64-encoded, aes-256-cbc encrypted string of anything a user
wants to write, encrypted using a shared cipher generated by
combining the recipient’s public-key with the sender’s
private-key; this appended by the base64-encoded initialization
vector as if it was a querystring parameter named “iv”. The format
is the following:
"content": "<encrypted_text>?iv=<initialization_vector>".
tags MUST contain an entry
identifying the receiver of the message (such that relays may
naturally forward this event to them), in the form
["p", "<pubkey, as a hex string>"].
tags MAY contain an entry
identifying the previous message in a conversation or a message we
are explicitly replying to (such that contextual, more organized
conversations may happen), in the form
["e", "<event_id>"].
Note: By default in the libsecp256k1
ECDH implementation, the secret is the SHA256 hash of the shared
point (both X and Y coordinates). In Nostr, only the X coordinate
of the shared point is used as the secret and it is NOT hashed. If
using libsecp256k1, a custom function that copies the X coordinate
must be passed as the hashfp argument in
secp256k1_ecdh. See here.
Code sample for generating such an event in JavaScript:
import crypto from 'crypto'
import * as secp from '@noble/secp256k1'
let sharedPoint = secp.getSharedSecret(ourPrivateKey, '02' + theirPublicKey)
let sharedX = sharedPoint.slice(1, 33)
let iv = crypto.randomFillSync(new Uint8Array(16))
var cipher = crypto.createCipheriv(
'aes-256-cbc',
Buffer.from(sharedX),
iv
)
let encryptedMessage = cipher.update(text, 'utf8', 'base64')
encryptedMessage += cipher.final('base64')
let ivBase64 = Buffer.from(iv.buffer).toString('base64')
let event = {
pubkey: ourPubKey,
created_at: Math.floor(Date.now() / 1000),
kind: 4,
tags: [['p', theirPublicKey]],
content: encryptedMessage + '?iv=' + ivBase64
}
Security Warning
This standard does not go anywhere near what is considered the
state-of-the-art in encrypted communication between peers, and it
leaks metadata in the events, therefore it must not be used for
anything you really need to keep secret, and only with relays that
use AUTH to restrict who can fetch your
kind:4 events.
Client Implementation Warning
Clients should not search and replace public key or
note references from the .content. If processed like
a regular text note (where @npub... is replaced with
#[0] with a ["p", "..."] tag) the tags
are leaked and the mentioned user will receive the message in
their inbox.
Warning
unrecommended: superseded by the Marmot Protocol