This update revises the NIP to focus on encrypted binary attachments for private messaging, clarifying the scope, specifications, and security considerations. Changes include rewording sections, updating examples, and emphasizing the use of encryption in attachments.
Wallet applications can register deeplinks in mobile systems to make it possible to create a linking UX that doesn't require the user scanning a QR code or pasting some code.
`nostrnwc://connect` and `nostrnwc+{app_name}://connect` can be registered by wallet apps and queried by apps that want to receive an NWC pairing code.
All URI parameters, MUST be URI-encoded.
URI parameters:
* `appicon` -- URL to an icon of the client that wants to create a connection.
* `appname` -- Name of the client that wants to create a connection.
* `callback` -- URI schema the wallet should open with the connection string
Once a connection has been created by the wallet, it should be returned to the client by opening the callback with the following parameters
title: Encrypted Binary Attachments for DMs and MLS
author: Jonathan Borden (jonathan@loxation.com)
status: Draft
type: Standards Track
created: 2025-08-23
license: CC0-1.0
---
## Abstract
This NIP profile standardizes encrypted binary attachments (images, audio, video, documents) for private Nostr messaging only: NIP‑17 direct messages and MLS groups. It defines:
- A normalized JSON structure for NIP‑17 DMs (keys live only inside the DM ciphertext)
- An MLS profile that derives per‑attachment AEAD key/nonce via the MLS exporter
- A per‑attachment AEAD scheme (AES‑256‑GCM) with normative sizes
- Integrity requirements (SHA‑256 over ciphertext)
- HTTP storage guidance (presigned upload/finalize), optionally compatible with NIP‑96 and NIP‑98
Public, unencrypted tags (attach/eattach) are explicitly out of scope for this profile.
## Motivation
Clients and servers need a consistent, interoperable, privacy‑preserving mechanism for sharing files in private contexts. This document scopes the solution to encrypted‑only delivery via NIP‑17 (1:1) and MLS (1:group), which matches our deployment and avoids ambiguity and leakage associated with public note tags.
## Rationale
- Keep symmetric keys in encrypted channels only (DM content or MLS exporter). Never in public tags or relay‑visible metadata.
- Use per‑attachment AEAD to avoid key reuse and enable granular sharing and revocation.
- Compute integrity over ciphertext so clients can verify prior to decryption and rendering.
- Keep events lightweight; store bytes off‑relay at canonical HTTPS URLs.
## Definitions
- **Attachment**: A binary resource referenced by a message.
- **Ciphertext attachment**: Uploaded bytes are encrypted; clients decrypt locally to render.
- **Per‑attachment key**: A random 32‑byte AES‑256 key generated uniquely per attachment (DMs). For MLS, the key is derived via the exporter.
## Specification
### 1. Cipher and integrity
- AEAD: AES‑256‑GCM
- key: 32 bytes (base64) [DMs only; MLS derives]
- iv/nonce: 12 bytes (base64)
- tag: 16 bytes (base64)
- Integrity: sha256 MUST be computed over ciphertext and verified before decrypt/render.
### 2. NIP‑17 direct messages (DMs)
Attachment parameters MUST live inside the DM’s encrypted content (not tags). The DM plaintext embeds a normalized JSON array of attachment objects:
```json
{
"type": "message",
"text": "optional user text",
"attachments": [
{
"url": "https://storage.example/enc/blob",
"ct": "image/jpeg",
"size": 23011,
"sha256": "<hex_of_ciphertext>",
"fn": "photo.jpg",
"enc": {
"mode": "dm",
"algo": "A256GCM",
"k": "<b64-32-bytes>",
"iv": "<b64-12-bytes>",
"t": "<b64-16-bytes>"
},
"alt": "a cat",
"blurhash": "..."
}
]
}
```
Receiver processing:
1) Decrypt the DM per NIP‑17.
2) Fetch the ciphertext bytes from `url`.
3) Verify `sha256` over ciphertext.
4) Decrypt with `enc.k/iv/t`.
5) Render using `ct`, `fn`, `alt`, and optional hints (e.g., `blurhash`).
Notes:
- The `size` field SHOULD reflect ciphertext length.
- Clients SHOULD cache both ciphertext and decrypted plaintext for efficient re‑rendering.
### 3. MLS group attachments
For MLS application messages, the attachment AEAD key and nonce are derived via the MLS exporter; no symmetric key material is placed in relay‑visible metadata.
Where `ctx` is a stable, mutually known identifier for this attachment (e.g., server `blobId` or a message‑scoped `attachmentId`). Publishers MUST include enough metadata for receivers to compute the same `ctx`.
Attachment metadata embedded in or adjacent to the MLS application message SHOULD include:
1) Use MLS state for `group_id`/`epoch` to derive key and nonce with the exporter and `ctx`.
2) Fetch ciphertext, verify `sha256`, then decrypt with derived key/nonce and verify auth tag `t`.
### 4. Out of scope
- Public note tags for unencrypted or encrypted media (attach/eattach).
- NIP‑92 “imeta” and NIP‑94 file‑metadata records for public media.
This profile targets encrypted attachments delivered via NIP‑17 and MLS only.
### 5. Storage and transport
- Storage: Off‑relay HTTP object storage with presigned upload + finalize flows that return canonical download URLs and server‑computed metadata (size/checksum). These flows are compatible with NIP‑96 where applicable.
- Auth: Publishers and storage providers MAY require NIP‑98 (HTTP Auth) for upload/finalize/download.
- Alternate device transports (e.g., BLE/Noise) MAY carry the same JSON payloads; this does not change the on‑wire format for Nostr DMs or MLS.
### 6. Client behavior
- Verify `sha256` over ciphertext before decrypt/render.
- Verify GCM auth tag during decryption.
- Show filename/thumbnail; respect accessibility fields like `alt`.
- Cache intelligently; apply quotas and safe‑content policies when fetching.
### 7. Security considerations
- Do not place keys, IVs, or tags in public tags or content.
- Do not include encryption material in NIP‑92 `imeta` or any relay‑visible metadata.
- Treat URL‑based key delivery or external key references as non‑confidential; this profile forbids such patterns.
- Ensure unique IVs per key; per‑attachment keys simplify this, but libraries MUST still generate fresh IVs.