From 0f88df16eeb50d389d0702af0d659d0d35df9d15 Mon Sep 17 00:00:00 2001 From: "Dave St.Germain" Date: Sat, 11 Mar 2023 19:35:54 -0500 Subject: [PATCH] Initial draft of NIP-59: improved direct messages --- 59.md | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 59.md diff --git a/59.md b/59.md new file mode 100644 index 00000000..4009d52e --- /dev/null +++ b/59.md @@ -0,0 +1,123 @@ +NIP-59 +====== + +Improved Direct Messages +------------------------- + +`draft` `optional` `author:davestgermain` `depends:4` + + +In order to improve the security of kind=4 encrypted direct messages, we'll translate the ideas from the [SimpleX Messaging Protocol](https://github.com/simplex-chat/simplexmq/blob/stable/protocol/overview-tjr.md#simplex-messaging-protocol) to nostr. Briefly, each side of the conversation creates an ephemeral "conversation key" and negotiates a secure location to continue the conversation. This allows for minimal metadata to be revealed. + + +## Conversation Negotiation + +Alice (public key `b5a448349c963a6cffbd57e6de0466bbe5584e14959e2f7aa4a8c295db52be7d`) wants to have a DM conversation with Bob (public key `18d95d3b888e273c70aafd7fff2ea7f3ddc356171ded0fe5c452a6ff1848e08e`). + +Her client will create a request that contains pointers to a relay and event kind where she will listen to responses from Bob: + +```json +{ + "id":"33eee9317f2ccadcddd5e217212c8334b44af71268b44671c02d455a5c266a5f", + "pubkey":"b5a448349c963a6cffbd57e6de0466bbe5584e14959e2f7aa4a8c295db52be7d", + "created_at":1678579922, + "kind":20004, + "tags":[ + ["r","wss://relayalice.com"], + ["p","18d95d3b888e273c70aafd7fff2ea7f3ddc356171ded0fe5c452a6ff1848e08e"] + ], + "content":"ad7aac0a2e19a7e53022a358ba4124b88260bcfc7856167878d906e980ed2315", + ... +} +``` + +The `content` is a random token which will be used to create a "conversation key" as follows: `sha256((token + bob_public_key)` + +Next, the client will generate an ephemeral private key and create a standard kind=4 DM, with the content being the jsonified request above: +```json +{ + "id": "c7ed1bba951da4a6cdfd8457ac94b738e3a46543a6436ec4fe65c2ee1193e14f", + "pubkey": "fd3598ae6877ec6d03c5e87e29679c714fdbcadaefac80e8cbefacab05a0197c", + "created_at": 1678579922, + "kind": 4, + "tags": [ + [ + "p", + "18d95d3b888e273c70aafd7fff2ea7f3ddc356171ded0fe5c452a6ff1848e08e" + ], + [ + "expiration", + "1678666322" + ] + ], + "content": "J9iKwHsqIQwWjnRSqGYDgYp1viVn4prThldxIQKkwz8G+MqtMme5VsqaNRrCX9s30P4HWrwaWzytCIt2OdjbWl3ZvcSnxvPG/pyIz7QQnofRCHOnhXu5Z/obEOcHaPf0VAY6qRHvfLsBayTmZk1xLsBtIu5dhYMD+iwcFQBbuoR0S11frY1S6T1jiPx1CZAMm6varR1sVMk7+vF1RILAQZaL35XhM/Yb/t2hCMLoV7efWyh+PStcdE7yW8CwSXmk4Ay68eBBi3iAiCQwmKfKzlqTBvbQ1sVOmQNFa5IS3UgqB2XN8w7a1dFWwCPavE7E3IVjNtL/C/KwPdBvmUu6k+km50VEG5s/lwEbLpR4CicRI5VNTlcLWaFZrssZ1sclBNPgFnBfShnxUBLjKXW6MR++ICAH+FQRTEO9bc3QA/lYgRczvDIwuAArnos9O9KxonWMmUo/yBKYVks2PsEMhy8z31Xqwt1zJWcVkWcCPrvpp5bF4BQL3ufgRbzQm5AVw9erH/AQ8h5s7rDCEKtG48e5G2vmT8gptns1QKkUJXa0NnuKema4ZBV6kvcSW+WM41FgK7QZW7pM47xexHzmBvlCOGxaCuxxgjedxJh8o9Ggzct3ZGXhkM41C0emZcm2nFHP6Ti9PBRsr0+66JKaEosXHUcok4z7Ia+Q3giSAdM=?iv=UwzRKNdpKJLm6vG1LaN6eA==", + ... +} + +``` + +Only the recipient metadata (Bob's pubkey) is revealed to the public, in this first message of the negotiation. + +Bob's client will see a DM from an unknown contact, will decrypt and validate that the request is addressed to him (the "p" tag is his public key). The client should present Bob with a prompt, displaying the sender's information, the requested relay and kind. If the requested kind is an ephemeral event (as shown in this example), the client can indicate that the chat with Alice would (may?) not be saved on the relay. + +If Bob accepts the request, his client would first create another ephemeral private key and repeat the process described above, with his own conversation request to Alice, pointed to a relay of his choosing: + + +```json +{ + "id":"d114e1153a24d630553e9b4ff072885bca9c825720620cf63c528e404c6527b6", + "pubkey":"18d95d3b888e273c70aafd7fff2ea7f3ddc356171ded0fe5c452a6ff1848e08e", + "created_at":1678580292, + "kind":20044, + "tags":[ + ["r","wss://relaybob.com"], + ["p","b5a448349c963a6cffbd57e6de0466bbe5584e14959e2f7aa4a8c295db52be7d"] + ], + "content":"9a97e6513003ebe9c8050b0000012137f3cf8a100c87d6f21bddac8e48895118", + ... +} +``` + +This event will be jsonified and addressed to the conversation key defined in Alice's first request: + +```json +{ + "id": "2637d2f047439d9c2e101f873b1b60eaf445ac1da19eab2d4ecc64dc15348f8d", + "pubkey": "0d4684b3d8ecd52a2c276e505e872059f5bc98bf79ca28cff0d1e4a625a9c8f7", + "created_at": 1678580443, + "kind": 20004, + "tags": [ + [ + "expiration", + "1678666843" + ] + ], + "content": "5YgtDICQSjv+pFsoLaiy/z7h98h9SBrzkzW2tBV8rdSRK1weXxRnnY00OB7pdiSgucQeKb38cbW8A2JXV3gtAkxe/cx71BitAB3anrNNkK8MdPZgCQ3jO7L79bxwfoRZs8ZQCsPkK0K2dxrysDQU3F9xNsvstXUCmR0nllTXIxq2+Pw//7hKd1m8caOMHri2kfToGPM+GGMHRzx/OEYZIqbgyOkX1vYepolz1gnyn9SfhDH3NdjtBoC14fArQecFRIyWmtjEGQm1FYXvdGUHB4Llt9I+5GURfSGT/upnueB+SmncGCxEYwhVE4bK5yQc32ahOGiTJtRel+kSgOqtKbCZqVJuCiOuR8ECtbLzFeI8n9iud36w+Y2wVRNMxfvczM+qkOn8uYNXdXfMNx1CHbKFAHzpNmtj15H70lmaxU4lGHbg2y74n6MJC/8gnXkt4erlzYW4ojnXiql21gdBx7DCsXLrUFCCuHzERUXlIwpgulrZPnhAgw6tPN1aOTpX4PTwGp6ZvrVy9+qmwj/U/phtB9aPqIHrcWR2gd5GSDloNajufWJ5dc5/9i347gv/2aCeSNg0gP1CONNTll7wf74XQ/ETVkVVbJlMixBk4PEgw2lw9k+7IF6oMCOqwy1mCES50sgCUu1RWLy3/2v/knGkd7jd/qT1MBAcf7pP7uM=?iv=dZEsPTXaTCAppUxjQ/rWKA==", + ... +} +``` + +His client will send this event to `wss://relayalice.com`, where Alice's client will already be subscribed to events. + +After Alice's client validates the request and connects to `wss://relaybob.com`, the conversation can continue between the two ephemeral keys, with Bob sending events as pubkey `0d4684b3d8ecd52a2c276e505e872059f5bc98bf79ca28cff0d1e4a625a9c8f7` to `wss://relayalice.com`, and Alice sending replies as `a2ab458e92c7c2434062cf94036168fce5ca4236294b48b4911ee765e1448f1b` to `wss://relaybob.com`. + +An example message from Alice to Bob (with content `Hello Bob!` looks like this: + +```json +{ + "id":"441d5493d227ebe2ed98a4564226e28c8ee99b35c678bf4930837c01ef82dec0", + "pubkey":"a2ab458e92c7c2434062cf94036168fce5ca4236294b48b4911ee765e1448f1b", + "created_at": 1678581213, + "kind": 20044, + "tags":[ + ["expiration","1678667613"] + ], + "content":"seceIcxeEPIiYrEP9IdG4w==?iv=7SEISW2DyH7PQYj/rwnoFw==", + ... +} +``` + +Clients SHOULD connect to at least two relays – since the sender and recipient channels should be on separate connections. + +The conversation kind MAY be any ephemeral event, or kind=4. As long as the clients agree to the requested destination, the conversation should proceed as normal. +