From df30012430c88d49fb5b124992b04d5c61b6338b Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Wed, 24 Apr 2024 15:31:45 -0400 Subject: [PATCH] NIP-17 (old 24) Sealed Gift-Wrapped Messages for Private DMs and Small Group Chats (#686) --- 04.md | 2 +- 11.md | 2 +- 17.md | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 9 ++-- 4 files changed, 162 insertions(+), 5 deletions(-) create mode 100644 17.md diff --git a/04.md b/04.md index dc232b40..a561a2f8 100644 --- a/04.md +++ b/04.md @@ -1,4 +1,4 @@ -> __Warning__ `unrecommended`: deprecated in favor of [NIP-44](44.md) +> __Warning__ `unrecommended`: deprecated in favor of [NIP-17](17.md) NIP-04 ====== diff --git a/11.md b/11.md index 45102d7e..a50038a0 100644 --- a/11.md +++ b/11.md @@ -37,7 +37,7 @@ Detailed plain-text information about the relay may be contained in the `descrip ### Pubkey -An administrative contact may be listed with a `pubkey`, in the same format as Nostr events (32-byte hex for a `secp256k1` public key). If a contact is listed, this provides clients with a recommended address to send encrypted direct messages (See `NIP-04`) to a system administrator. Expected uses of this address are to report abuse or illegal content, file bug reports, or request other technical assistance. +An administrative contact may be listed with a `pubkey`, in the same format as Nostr events (32-byte hex for a `secp256k1` public key). If a contact is listed, this provides clients with a recommended address to send encrypted direct messages (See [NIP-17](17.md)) to a system administrator. Expected uses of this address are to report abuse or illegal content, file bug reports, or request other technical assistance. Relay operators have no obligation to respond to direct messages. diff --git a/17.md b/17.md new file mode 100644 index 00000000..cc04a888 --- /dev/null +++ b/17.md @@ -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": "", +  "pubkey": "", + "created_at": now(), +  "kind": 14, +  "tags": [ +    ["p", "", ""], +    ["p", "", ""], +    ["e", "", "", "reply"] // if this is a reply + ["subject", ""], +    ... +  ], +  "content": "", +} +``` + +`.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": "", +  "pubkey": randomPublicKey, +  "created_at": randomTimeUpTo2DaysInThePast(), + "kind": 1059, // gift wrap +  "tags": [ +    ["p", receiverPublicKey, ""] // receiver +  ], +  "content": nip44Encrypt( +    { + "id": "", +      "pubkey": senderPublicKey, +      "created_at": randomTimeUpTo2DaysInThePast(), +      "kind": 13, // seal +      "tags": [], // no tags +      "content": nip44Encrypt(unsignedKind14, senderPrivateKey, receiverPublicKey), +      "sig": "" +    }, +    randomPrivateKey, receiverPublicKey +  ), +  "sig": "" +} +``` + +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. + +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. + +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" +} +``` diff --git a/README.md b/README.md index 5fcdaf76..619c9846 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos - [NIP-01: Basic protocol flow description](01.md) - [NIP-02: Follow List](02.md) - [NIP-03: OpenTimestamps Attestations for Events](03.md) -- [NIP-04: Encrypted Direct Message](04.md) --- **unrecommended**: deprecated in favor of [NIP-44](44.md) +- [NIP-04: Encrypted Direct Message](04.md) --- **unrecommended**: deprecated in favor of [NIP-17](17.md) - [NIP-05: Mapping Nostr keys to DNS-based internet identifiers](05.md) - [NIP-06: Basic key derivation from mnemonic seed phrase](06.md) - [NIP-07: `window.nostr` capability for web browsers](07.md) @@ -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](17.md) - [NIP-18: Reposts](18.md) - [NIP-19: bech32-encoded entities](19.md) - [NIP-21: `nostr:` URI scheme](21.md) @@ -99,6 +100,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) | @@ -138,6 +140,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | `10009` | User groups | [51](51.md), [29](29.md) | | `10015` | Interests list | [51](51.md) | | `10030` | User emoji list | [51](51.md) | +| `10050` | Relay list to receive DMs | [17](17.md) | | `10096` | File storage server list | [96](96.md) | | `13194` | Wallet Info | [47](47.md) | | `21000` | Lightning Pub RPC | [Lightning.Pub][lnpub] | @@ -247,10 +250,10 @@ Please update these lists when proposing NIPs introducing new event kinds. | `price` | price | currency, frequency | [99](99.md) | | `proxy` | external ID | protocol | [48](48.md) | | `published_at` | unix timestamp (string) | -- | [23](23.md) | -| `relay` | relay url | -- | [42](42.md) | +| `relay` | relay url | -- | [42](42.md), [17](17.md) | | `relays` | relay list | -- | [57](57.md) | | `server` | file storage server url | -- | [96](96.md) | -| `subject` | subject | -- | [14](14.md) | +| `subject` | subject | -- | [14](14.md), [17](17.md) | | `summary` | article summary | -- | [23](23.md) | | `thumb` | badge thumbnail | dimensions in pixels | [58](58.md) | | `title` | article title | -- | [23](23.md) |