Skip to content
Merged
Show file tree
Hide file tree
Changes from 69 commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
816eca2
First draft of the new DM/Private Chat scheme
vitorpamplona Jul 28, 2023
089cc0e
Formatting fixes
vitorpamplona Jul 28, 2023
a81769c
Formatting improvents
vitorpamplona Jul 28, 2023
844df3c
Wording
vitorpamplona Jul 28, 2023
af957f0
Wording ++
vitorpamplona Jul 28, 2023
28837ce
Space formatting
vitorpamplona Jul 28, 2023
6d97939
More formatting
vitorpamplona Jul 28, 2023
277a53e
Typos
vitorpamplona Jul 28, 2023
49fb74b
Final consideration section
vitorpamplona Jul 28, 2023
8448eea
From must to can
vitorpamplona Jul 28, 2023
57269e8
Update 24.md
vitorpamplona Jul 28, 2023
a0e07c2
Update 24.md
vitorpamplona Jul 28, 2023
b81f5ad
Update 24.md
vitorpamplona Jul 28, 2023
1cf39bb
Update 24.md
vitorpamplona Jul 28, 2023
7ff1183
Update 24.md
vitorpamplona Jul 28, 2023
20e4e24
Update 24.md
vitorpamplona Jul 28, 2023
fac8c89
Update 24.md
vitorpamplona Jul 28, 2023
a98f593
typo
vitorpamplona Jul 28, 2023
a5a4fd8
Update 24.md
vitorpamplona Jul 28, 2023
858e09e
adding staab as an author
vitorpamplona Jul 28, 2023
0df23b1
Removes extra backsticks
vitorpamplona Jul 28, 2023
3c567ca
Update 24.md
vitorpamplona Jul 28, 2023
2ff42e1
Merge branch 'sealed-dms' of https://github.com/vitorpamplona/nips in…
vitorpamplona Jul 28, 2023
179839e
Improved explanations
vitorpamplona Jul 28, 2023
ce0f556
Formatting
vitorpamplona Jul 28, 2023
695696e
Update 24.md
vitorpamplona Jul 28, 2023
080ed36
Adds quotes to example
vitorpamplona Jul 28, 2023
8e9e62c
Deletes the DM Step by Step example
vitorpamplona Jul 28, 2023
91bd6b1
Trying to fix number sequence formatting
vitorpamplona Jul 28, 2023
06de8fa
Formatting
vitorpamplona Jul 28, 2023
cc18c1a
Fixing the Sender's message
vitorpamplona Jul 28, 2023
ebc512a
Fixing the Group example and improving the Secret algorithm
vitorpamplona Jul 29, 2023
3ae2e3b
Formatting
vitorpamplona Jul 29, 2023
83f110d
Adds Kotlin snippet
vitorpamplona Jul 29, 2023
18272d3
Improved kotlin snippet
vitorpamplona Jul 29, 2023
53e4112
Adds a test case from Amethyst
vitorpamplona Jul 30, 2023
f23eb1c
Refining claims.
vitorpamplona Jul 30, 2023
640238d
Update 24.md
vitorpamplona Jul 31, 2023
1b75bda
Update 24.md
vitorpamplona Jul 31, 2023
6b8a9d7
Adds Coracle's test case
vitorpamplona Jul 31, 2023
2f50d0c
Update 24.md
vitorpamplona Aug 10, 2023
eb9f241
Simplifying
vitorpamplona Aug 17, 2023
5ec54df
Simplifying more
vitorpamplona Aug 17, 2023
d2f7be3
wording improvements
vitorpamplona Aug 17, 2023
944a261
wording
vitorpamplona Aug 17, 2023
5351585
typos
vitorpamplona Aug 17, 2023
87a1305
refining algorithm
vitorpamplona Aug 17, 2023
f23150a
wording
vitorpamplona Aug 17, 2023
0cd38aa
Numbering
vitorpamplona Aug 17, 2023
769886d
typo
vitorpamplona Aug 17, 2023
1c640ad
Adjusts readme
vitorpamplona Aug 17, 2023
8e78704
Update 24.md
vitorpamplona Aug 17, 2023
79349e2
Merge remote-tracking branch 'upstream/master' into sealed-dms
vitorpamplona Dec 16, 2023
3a1a487
Minor improvements to the text.
vitorpamplona Dec 17, 2023
6b7ccba
Removes last underline
vitorpamplona Dec 17, 2023
be79146
Additional refinements to the text.
vitorpamplona Dec 17, 2023
293b233
Simplifying the example and algorithm descripton
vitorpamplona Dec 17, 2023
d584f06
Removing the claim about trust minimized.
vitorpamplona Dec 17, 2023
8dbf007
Simplifying and adding an exemple with the NIP-44v2
vitorpamplona Dec 21, 2023
2d8db9d
Additional simplifications
vitorpamplona Dec 21, 2023
e20e730
Merge remote-tracking branch 'upstream/master' into sealed-dms
vitorpamplona Jan 9, 2024
904fe23
clean up
vitorpamplona Jan 9, 2024
58c8d68
Improves formatting
vitorpamplona Jan 9, 2024
90ff3af
Fixes name on readme
vitorpamplona Jan 9, 2024
6538252
minor tweaks
vitorpamplona Jan 9, 2024
26f1a5c
Improvements to the completeness of the spec.
vitorpamplona Jan 9, 2024
21e8c58
Merge remote-tracking branch 'upstream/master' into sealed-dms
vitorpamplona Mar 6, 2024
abcaa5e
- Added inbox relays language
vitorpamplona Mar 6, 2024
c0b1255
Better wording for NIP-65 inbox.
vitorpamplona Mar 6, 2024
e489766
Fix NIP-65
vitorpamplona Mar 6, 2024
0ada23a
Update 17.md
vitorpamplona Mar 6, 2024
de4d5fd
Adds a relay list type to identify which relays to use for DMs.
vitorpamplona Mar 6, 2024
de96226
Merge branch 'sealed-dms' of https://github.com/vitorpamplona/nips in…
vitorpamplona Mar 6, 2024
7a9cba1
Adds kind 10050 to readme
vitorpamplona Mar 6, 2024
4e80c36
Adds the NIP65 recomendation to keep the relay list small.
vitorpamplona Mar 6, 2024
c5ad9bf
Uses `relay` instead of `r`
vitorpamplona Mar 6, 2024
2efc95c
Reduces the mumbo jumbo in the text.
vitorpamplona Mar 6, 2024
8c029aa
Reducing the amount of relays in 10050
vitorpamplona Mar 7, 2024
80cb611
Adjustments to the text to remove the emphasis on groups.
vitorpamplona Mar 19, 2024
75e93a6
Removes Group DMs from the name of NIP-17
vitorpamplona Mar 19, 2024
c296cd6
Adjust redirections from NIP-04 to NIP-17
vitorpamplona Mar 19, 2024
acdbea3
Final adjustments
vitorpamplona Mar 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions 17.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
NIP-17
======

Private Direct Messages and Group DMs
-------------------------------------

`draft` `optional`

This NIP defines an encrypted direct messaging scheme for 2+ participants using [NIP-44](44.md) encryption and [NIP-59](59.md) seals and gift wraps.

## Direct Message Kind

`kind:14` is defined as a chat message. It is designed to be a Rumor in [NIP-59](59.md) and thus MUST never be signed. If it is signed, the message becomes **fully public**. This event kind requires [NIP-59](59.md) encapsulation to make it private.

```js
{
"id": "<usual hash>",
  "pubkey": "<sender-pubkey>",
"created_at": now(),
  "kind": 14,
  "tags": [
    ["p", "<receiver-1-pubkey>", "<relay-url>"],
    ["p", "<receiver-2-pubkey>", "<relay-url>"],
    ["e", "<kind-14-id>", "<relay-url>", "reply"] // if this is a reply
["subject", "<conversation-title>"],
    ...
  ],
  "content": "<message-in-plain-text>",
}
```

The content MUST follow the same plaintext rules of `kind:1`. Tags that mention, quote and assemble threading structures MUST follow [NIP-10](10.md). Fields `id` and `created_at` are required.

The set of `pubkey` + `p` tags defines a group chat. Clients SHOULD render messages of the same group in a continuous thread. If a new `p` tag is added or the current one is removed, a new group is created.

An optional `subject` tag defines the current name/topic of the conversation. Any member can change the topic by simply submitting a new `subject` to an existing `pubkey` + `p`-tags group. There is no need to send `subject` in every message. The newest `subject` in the thread is the subject of the conversation.

The use of other tags is highly encouraged (e.g. `content-warning` ([NIP-36](36.md)) if the content is NSFW).

## Encrypting and Broadcasting

Following [NIP-59](59.md), the unsigned `kind:14` chat message must be sealed (`kind:13`) and then gift wrapped (`kind:1059`) to each receiver and the sender individually:

```js
{
"id": "<usual hash>",
  "pubkey": randomPublicKey,
  "created_at": randomTimeUpTo2DaysInThePast(),
"kind": 1059, // gift wrap
  "tags": [
    ["p", receiverPublicKey, "<relay-url>"] // receiver
  ],
  "content": nip44Encrypt(
    {
"id": "<usual hash>",
      "pubkey": senderPublicKey,
      "created_at": randomTimeUpTo2DaysInThePast(),
      "kind": 13, // seal
      "tags": [], // no tags
      "content": nip44Encrypt(unsignedKind14, senderPrivateKey, receiverPublicKey),
      "sig": "<signed by senderPrivateKey>"
    },
    randomPrivateKey, receiverPublicKey
  ),
  "sig": "<signed by randomPrivateKey>"
}
```

The encryption algorithm MUST use the latest version of [NIP-44](44.md).

Clients MUST verify if pubkey of the `kind:13` is the same pubkey on the `kind:14`, otherwise any sender can impersonate others by simply changing the pubkey on `kind:14`.

Clients SHOULD randomize `created_at` in up to two days in the past in both the seal and the wrap to make sure grouping by `created_at` doesn't reveal the group's metadata.

The gift wrap's `p`-tag can be the receiver's main pubkey or an alias key created to receive DMs without exposing the receiver's identity.

Clients SHOULD only broadcast giftwrap events to the private `inbox` relays of each recipient's [NIP-65](65.md), falling back to `read` relays.

Clients CAN offer disappearing messages to their own users by not creating a GiftWrap to the sender's public key or by setting an `expiration` tag in the gift wrap of each receiver.

## Benefits & Limitations

It offers the following privacy and security features:

1. **No Metadata Leak**: Participant identities, each message's real date and time, event kinds, and other event tags are all hidden from the public. Senders and receivers cannot be linked with public information alone.
2. **No Public Group Identifiers**: There is no public central queue, channel or otherwise converging identifier to correlate or count all messages in the same group.
3. **No Moderation**: There are no group admins: no invitations or bans.
4. **No Shared Secrets**: No secret must be known to all members that can leak or be mistakenly shared
5. **Fully Recoverable**: Messages can be fully recoverable by any client with the user's private key
6. **Optional Forward Secrecy**: Users and clients can opt-in for "disappearing messages".
7. **Uses Public Relays**: Messages can flow through public relays without loss of privacy. Private relays can increase privacy further, but they are not required.
8. **Cold Storage**: Users can unilaterally opt-in to sharing their messages with a separate key that is exclusive for DM backup and recovery.

The main limitation of this approach is having to send a separate encrypted event to each receiver. Group chats with more than 100 participants should find a more suitable messaging scheme.

----

## Examples

This example sends the message `Hola, que tal?` from `nsec1w8udu59ydjvedgs3yv5qccshcj8k05fh3l60k9x57asjrqdpa00qkmr89m` to `nsec12ywtkplvyq5t6twdqwwygavp5lm4fhuang89c943nf2z92eez43szvn4dt`.

The two final GiftWraps, one to the receiver and the other to the sender, are:

```json
{
"id":"2886780f7349afc1344047524540ee716f7bdc1b64191699855662330bf235d8",
"pubkey":"8f8a7ec43b77d25799281207e1a47f7a654755055788f7482653f9c9661c6d51",
"created_at":1703128320,
"kind":1059,
"tags":[
[ "p", "918e2da906df4ccd12c8ac672d8335add131a4cf9d27ce42b3bb3625755f0788"]
],
"content":"AsqzdlMsG304G8h08bE67dhAR1gFTzTckUUyuvndZ8LrGCvwI4pgC3d6hyAK0Wo9gtkLqSr2rT2RyHlE5wRqbCOlQ8WvJEKwqwIJwT5PO3l2RxvGCHDbd1b1o40ZgIVwwLCfOWJ86I5upXe8K5AgpxYTOM1BD+SbgI5jOMA8tgpRoitJedVSvBZsmwAxXM7o7sbOON4MXHzOqOZpALpS2zgBDXSAaYAsTdEM4qqFeik+zTk3+L6NYuftGidqVluicwSGS2viYWr5OiJ1zrj1ERhYSGLpQnPKrqDaDi7R1KrHGFGyLgkJveY/45y0rv9aVIw9IWF11u53cf2CP7akACel2WvZdl1htEwFu/v9cFXD06fNVZjfx3OssKM/uHPE9XvZttQboAvP5UoK6lv9o3d+0GM4/3zP+yO3C0NExz1ZgFmbGFz703YJzM+zpKCOXaZyzPjADXp8qBBeVc5lmJqiCL4solZpxA1865yPigPAZcc9acSUlg23J1dptFK4n3Tl5HfSHP+oZ/QS/SHWbVFCtq7ZMQSRxLgEitfglTNz9P1CnpMwmW/Y4Gm5zdkv0JrdUVrn2UO9ARdHlPsW5ARgDmzaxnJypkfoHXNfxGGXWRk0sKLbz/ipnaQP/eFJv/ibNuSfqL6E4BnN/tHJSHYEaTQ/PdrA2i9laG3vJti3kAl5Ih87ct0w/tzYfp4SRPhEF1zzue9G/16eJEMzwmhQ5Ec7jJVcVGa4RltqnuF8unUu3iSRTQ+/MNNUkK6Mk+YuaJJs6Fjw6tRHuWi57SdKKv7GGkr0zlBUU2Dyo1MwpAqzsCcCTeQSv+8qt4wLf4uhU9Br7F/L0ZY9bFgh6iLDCdB+4iABXyZwT7Ufn762195hrSHcU4Okt0Zns9EeiBOFxnmpXEslYkYBpXw70GmymQfJlFOfoEp93QKCMS2DAEVeI51dJV1e+6t3pCSsQN69Vg6jUCsm1TMxSs2VX4BRbq562+VffchvW2BB4gMjsvHVUSRl8i5/ZSDlfzSPXcSGALLHBRzy+gn0oXXJ/447VHYZJDL3Ig8+QW5oFMgnWYhuwI5QSLEyflUrfSz+Pdwn/5eyjybXKJftePBD9Q+8NQ8zulU5sqvsMeIx/bBUx0fmOXsS3vjqCXW5IjkmSUV7q54GewZqTQBlcx+90xh/LSUxXex7UwZwRnifvyCbZ+zwNTHNb12chYeNjMV7kAIr3cGQv8vlOMM8ajyaZ5KVy7HpSXQjz4PGT2/nXbL5jKt8Lx0erGXsSsazkdoYDG3U",
"sig":"a3c6ce632b145c0869423c1afaff4a6d764a9b64dedaf15f170b944ead67227518a72e455567ca1c2a0d187832cecbde7ed478395ec4c95dd3e71749ed66c480"
}
```

```json
{
"id":"162b0611a1911cfcb30f8a5502792b346e535a45658b3a31ae5c178465509721",
"pubkey":"626be2af274b29ea4816ad672ee452b7cf96bbb4836815a55699ae402183f512",
"created_at":1702711587,
"kind":1059,
"tags":[
[ "p", "44900586091b284416a0c001f677f9c49f7639a55c3f1e2ec130a8e1a7998e1b"]
],
"content":"AsTClTzr0gzXXji7uye5UB6LYrx3HDjWGdkNaBS6BAX9CpHa+Vvtt5oI2xJrmWLen+Fo2NBOFazvl285Gb3HSM82gVycrzx1HUAaQDUG6HI7XBEGqBhQMUNwNMiN2dnilBMFC3Yc8ehCJT/gkbiNKOpwd2rFibMFRMDKai2mq2lBtPJF18oszKOjA+XlOJV8JRbmcAanTbEK5nA/GnG3eGUiUzhiYBoHomj3vztYYxc0QYHOx0WxiHY8dsC6jPsXC7f6k4P+Hv5ZiyTfzvjkSJOckel1lZuE5SfeZ0nduqTlxREGeBJ8amOykgEIKdH2VZBZB+qtOMc7ez9dz4wffGwBDA7912NFS2dPBr6txHNxBUkDZKFbuD5wijvonZDvfWq43tZspO4NutSokZB99uEiRH8NAUdGTiNb25m9JcDhVfdmABqTg5fIwwTwlem5aXIy8b66lmqqz2LBzJtnJDu36bDwkILph3kmvaKPD8qJXmPQ4yGpxIbYSTCohgt2/I0TKJNmqNvSN+IVoUuC7ZOfUV9lOV8Ri0AMfSr2YsdZ9ofV5o82ClZWlWiSWZwy6ypa7CuT1PEGHzywB4CZ5ucpO60Z7hnBQxHLiAQIO/QhiBp1rmrdQZFN6PUEjFDloykoeHe345Yqy9Ke95HIKUCS9yJurD+nZjjgOxZjoFCsB1hQAwINTIS3FbYOibZnQwv8PXvcSOqVZxC9U0+WuagK7IwxzhGZY3vLRrX01oujiRrevB4xbW7Oxi/Agp7CQGlJXCgmRE8Rhm+Vj2s+wc/4VLNZRHDcwtfejogjrjdi8p6nfUyqoQRRPARzRGUnnCbh+LqhigT6gQf3sVilnydMRScEc0/YYNLWnaw9nbyBa7wFBAiGbJwO40k39wj+xT6HTSbSUgFZzopxroO3f/o4+ubx2+IL3fkev22mEN38+dFmYF3zE+hpE7jVxrJpC3EP9PLoFgFPKCuctMnjXmeHoiGs756N5r1Mm1ffZu4H19MSuALJlxQR7VXE/LzxRXDuaB2u9days/6muP6gbGX1ASxbJd/ou8+viHmSC/ioHzNjItVCPaJjDyc6bv+gs1NPCt0qZ69G+JmgHW/PsMMeL4n5bh74g0fJSHqiI9ewEmOG/8bedSREv2XXtKV39STxPweceIOh0k23s3N6+wvuSUAJE7u1LkDo14cobtZ/MCw/QhimYPd1u5HnEJvRhPxz0nVPz0QqL/YQeOkAYk7uzgeb2yPzJ6DBtnTnGDkglekhVzQBFRJdk740LEj6swkJ",
"sig":"c94e74533b482aa8eeeb54ae72a5303e0b21f62909ca43c8ef06b0357412d6f8a92f96e1a205102753777fd25321a58fba3fb384eee114bd53ce6c06a1c22bab"
}
```
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
- [NIP-13: Proof of Work](13.md)
- [NIP-14: Subject tag in text events](14.md)
- [NIP-15: Nostr Marketplace (for resilient marketplaces)](15.md)
- [NIP-17: Private Direct Messages and Group DMs](17.md)
- [NIP-18: Reposts](18.md)
- [NIP-19: bech32-encoded entities](19.md)
- [NIP-21: `nostr:` URI scheme](21.md)
Expand Down Expand Up @@ -98,6 +99,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `11` | Group Thread | [29](29.md) |
| `12` | Group Thread Reply | [29](29.md) |
| `13` | Seal | [59](59.md) |
| `14` | Direct Message | [17](17.md) |
| `16` | Generic Repost | [18](18.md) |
| `40` | Channel Creation | [28](28.md) |
| `41` | Channel Metadata | [28](28.md) |
Expand Down