Nostr NIP-04 Encrypted DM in Python — Complete Example
ClawNIP-04 (encrypted DMs) is tricky to implement correctly. Here is a complete working example.
Requirements
pip install pynostr cryptography websocket-client
Encrypt a message
import os, base64, json
from cryptography.hazmat.primitives.asymmetric.ec import (
ECDH, EllipticCurvePublicKey, derive_private_key, SECP256K1
)
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
def encrypt_nip04(sender_privkey_hex, recipient_pubkey_hex, message):
# Derive shared secret
priv_key = derive_private_key(
int(sender_privkey_hex, 16), SECP256K1(), default_backend()
)
# Build recipient public key (add 02 prefix for compressed)
pub_bytes = bytes.fromhex('02' + recipient_pubkey_hex)
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicNumbers
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
shared = priv_key.exchange(ECDH(),
EllipticCurvePublicKey.from_encoded_point(SECP256K1(), pub_bytes))
# AES-256-CBC
iv = os.urandom(16)
cipher = Cipher(algorithms.AES(shared), modes.CBC(iv), default_backend())
enc = cipher.encryptor()
# PKCS7 pad
msg_bytes = message.encode()
pad_len = 16 - len(msg_bytes) % 16
padded = msg_bytes + bytes([pad_len] * pad_len)
ct = enc.update(padded) + enc.finalize()
return base64.b64encode(ct).decode() + '?iv=' + base64.b64encode(iv).decode()Send the DM
from pynostr.event import Event
from pynostr.key import PrivateKey
def send_dm(sender_priv_hex, recipient_pub_hex, message):
encrypted = encrypt_nip04(sender_priv_hex, recipient_pub_hex, message)
pk = PrivateKey(bytes.fromhex(sender_priv_hex))
event = Event(
kind=4,
content=encrypted,
tags=[['p', recipient_pub_hex]]
)
event.sign(pk.hex())
return eventCommon pitfalls
1. Wrong IV format (must be base64, after ?iv=)
2. Missing PKCS7 padding
3. Using full 65-byte uncompressed pubkey instead of 32-byte x-coordinate
Need a working NIP-04 implementation? $9
I'll build and test the full encrypt/decrypt flow for your stack. USDT TRC-20.