-
Notifications
You must be signed in to change notification settings - Fork 721
NIP-17 (old 24) Sealed Gift-Wrapped Messages for Private DMs and Small Group Chats #686
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all 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 089cc0e
Formatting fixes
vitorpamplona a81769c
Formatting improvents
vitorpamplona 844df3c
Wording
vitorpamplona af957f0
Wording ++
vitorpamplona 28837ce
Space formatting
vitorpamplona 6d97939
More formatting
vitorpamplona 277a53e
Typos
vitorpamplona 49fb74b
Final consideration section
vitorpamplona 8448eea
From must to can
vitorpamplona 57269e8
Update 24.md
vitorpamplona a0e07c2
Update 24.md
vitorpamplona b81f5ad
Update 24.md
vitorpamplona 1cf39bb
Update 24.md
vitorpamplona 7ff1183
Update 24.md
vitorpamplona 20e4e24
Update 24.md
vitorpamplona fac8c89
Update 24.md
vitorpamplona a98f593
typo
vitorpamplona a5a4fd8
Update 24.md
vitorpamplona 858e09e
adding staab as an author
vitorpamplona 0df23b1
Removes extra backsticks
vitorpamplona 3c567ca
Update 24.md
vitorpamplona 2ff42e1
Merge branch 'sealed-dms' of https://github.com/vitorpamplona/nips in…
vitorpamplona 179839e
Improved explanations
vitorpamplona ce0f556
Formatting
vitorpamplona 695696e
Update 24.md
vitorpamplona 080ed36
Adds quotes to example
vitorpamplona 8e9e62c
Deletes the DM Step by Step example
vitorpamplona 91bd6b1
Trying to fix number sequence formatting
vitorpamplona 06de8fa
Formatting
vitorpamplona cc18c1a
Fixing the Sender's message
vitorpamplona ebc512a
Fixing the Group example and improving the Secret algorithm
vitorpamplona 3ae2e3b
Formatting
vitorpamplona 83f110d
Adds Kotlin snippet
vitorpamplona 18272d3
Improved kotlin snippet
vitorpamplona 53e4112
Adds a test case from Amethyst
vitorpamplona f23eb1c
Refining claims.
vitorpamplona 640238d
Update 24.md
vitorpamplona 1b75bda
Update 24.md
vitorpamplona 6b8a9d7
Adds Coracle's test case
vitorpamplona 2f50d0c
Update 24.md
vitorpamplona eb9f241
Simplifying
vitorpamplona 5ec54df
Simplifying more
vitorpamplona d2f7be3
wording improvements
vitorpamplona 944a261
wording
vitorpamplona 5351585
typos
vitorpamplona 87a1305
refining algorithm
vitorpamplona f23150a
wording
vitorpamplona 0cd38aa
Numbering
vitorpamplona 769886d
typo
vitorpamplona 1c640ad
Adjusts readme
vitorpamplona 8e78704
Update 24.md
vitorpamplona 79349e2
Merge remote-tracking branch 'upstream/master' into sealed-dms
vitorpamplona 3a1a487
Minor improvements to the text.
vitorpamplona 6b7ccba
Removes last underline
vitorpamplona be79146
Additional refinements to the text.
vitorpamplona 293b233
Simplifying the example and algorithm descripton
vitorpamplona d584f06
Removing the claim about trust minimized.
vitorpamplona 8dbf007
Simplifying and adding an exemple with the NIP-44v2
vitorpamplona 2d8db9d
Additional simplifications
vitorpamplona e20e730
Merge remote-tracking branch 'upstream/master' into sealed-dms
vitorpamplona 904fe23
clean up
vitorpamplona 58c8d68
Improves formatting
vitorpamplona 90ff3af
Fixes name on readme
vitorpamplona 6538252
minor tweaks
vitorpamplona 26f1a5c
Improvements to the completeness of the spec.
vitorpamplona 21e8c58
Merge remote-tracking branch 'upstream/master' into sealed-dms
vitorpamplona abcaa5e
- Added inbox relays language
vitorpamplona c0b1255
Better wording for NIP-65 inbox.
vitorpamplona e489766
Fix NIP-65
vitorpamplona 0ada23a
Update 17.md
vitorpamplona de4d5fd
Adds a relay list type to identify which relays to use for DMs.
vitorpamplona de96226
Merge branch 'sealed-dms' of https://github.com/vitorpamplona/nips in…
vitorpamplona 7a9cba1
Adds kind 10050 to readme
vitorpamplona 4e80c36
Adds the NIP65 recomendation to keep the relay list small.
vitorpamplona c5ad9bf
Uses `relay` instead of `r`
vitorpamplona 2efc95c
Reduces the mumbo jumbo in the text.
vitorpamplona 8c029aa
Reducing the amount of relays in 10050
vitorpamplona 80cb611
Adjustments to the text to remove the emphasis on groups.
vitorpamplona 75e93a6
Removes Group DMs from the name of NIP-17
vitorpamplona c296cd6
Adjust redirections from NIP-04 to NIP-17
vitorpamplona acdbea3
Final adjustments
vitorpamplona File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,154 @@ | ||
| NIP-17 | ||
| ====== | ||
|
|
||
| Private Direct Messages | ||
| ----------------------- | ||
|
|
||
| `draft` `optional` | ||
|
|
||
| This NIP defines an encrypted direct messaging scheme using [NIP-44](44.md) encryption and [NIP-59](59.md) seals and gift wraps. | ||
|
|
||
| ## Direct Message Kind | ||
|
|
||
| Kind `14` is a chat message. `p` tags identify one or more receivers of the message. | ||
|
|
||
| ```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>", | ||
| } | ||
| ``` | ||
|
|
||
| `.content` MUST be plain text. Fields `id` and `created_at` are required. | ||
|
|
||
| Tags that mention, quote and assemble threading structures MUST follow [NIP-10](10.md). | ||
|
|
||
| Kind `14`s MUST never be signed. If it is signed, the message might leak to relays and become **fully public**. | ||
|
|
||
| ## Chat Rooms | ||
|
|
||
| The set of `pubkey` + `p` tags defines a chat room. If a new `p` tag is added or a current one is removed, a new room is created with clean message history. | ||
|
|
||
| Clients SHOULD render messages of the same room in a continuous thread. | ||
|
|
||
| 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 room. There is no need to send `subject` in every message. The newest `subject` in the thread is the subject of the conversation. | ||
|
|
||
| ## Encrypting | ||
|
|
||
| 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 gift wrap to make sure grouping by `created_at` doesn't reveal any metadata. | ||
vitorpamplona marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| 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 CAN offer disappearing messages by setting an `expiration` tag in the gift wrap of each receiver or by not generating a gift wrap to the sender's public key | ||
|
|
||
| ## Publishing | ||
|
|
||
| Kind `10050` indicates the user's preferred relays to receive DMs. The event MUST include a list of `relay` tags with relay URIs. | ||
|
|
||
| ```js | ||
| { | ||
| "kind": 10050, | ||
| "tags": [ | ||
| ["relay", "wss://inbox.nostr.wine"], | ||
| ["relay", "wss://myrelay.nostr1.com"], | ||
| ], | ||
| "content": "", | ||
| //...other fields | ||
| } | ||
| ``` | ||
|
|
||
| Clients SHOULD publish kind `14` events to the `10050`-listed relays, falling back to `read` relays of [NIP-65](65.md) if `kind:10050` is not available. | ||
vitorpamplona marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Clients SHOULD guide users to keep `kind:10050` lists small (1-3 relays) and SHOULD spread it to as many relays as viable. | ||
|
|
||
| ## Benefits & Limitations | ||
|
|
||
| This NIP 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" | ||
| } | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.