diff --git a/17.md b/17.md index ebf36f06..59d47f1e 100644 --- a/17.md +++ b/17.md @@ -25,39 +25,60 @@ Following [NIP-59](59.md), the **unsigned** chat messages must be sealed (`kind: ```js { "id": "", - "pubkey": wrapperPublicKey, + "pubkey": wrapperKey.public, "created_at": randomTimeUpTo2DaysInThePast, "kind": 1059, // gift wrap "tags": [ - ["p", receiverPublicKey, ""] // receiver + ["p", receiverIdentityKey.public, ""] // receiver ], "content": nip44.encrypt( { "id": "", - "pubkey": senderPublicKey, + "pubkey": senderIdentityKey.public, "created_at": randomTimeUpTo2DaysInThePast, "kind": 13, // seal "tags": [], // no tags "content": nip44.encrypt( unsignedMessageRumor, - nip44.compute_conversation_key(senderPrivateKey, receiverPublicKey) + nip44.compute_conversation_key(senderEncryptionKey.private, receiverEncryptionKey.public) ), - "sig": "" + "sig": "" }, - nip44.compute_conversation_key(wrapperPrivateKey, receiverPublicKey) + nip44.compute_conversation_key(wrapperKey.private, receiverEncryptionKey.public) ), - "sig": "" + "sig": "" } ``` `unsignedMessageRumor` is a rumor (an unsigned event, as per [NIP-59](59.md)), usually a `kind:14`, but could also be a different kind, see [Message Rumor Definitions](#message-rumor-definitions) below. -`wrapperPrivateKey` and `wrappedPublicKey` are a new keypair, generated randomly anew for each message sent. +`wrapperKey` is a new keypair, generated randomly anew for each message sent. Clients MUST verify if pubkey of the `kind:13` is the same pubkey as that of the `unsignedMessageRumor`, otherwise any sender can impersonate any other by simply changing the pubkey on the rumor. 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. +### Encryption Keys + +There is a difference between the keypairs used in `nip44.compute_conversation_key()` ("encryption key") and those used to sign the seal event ("identity key"). + +By default, these keypairs are the same, i.e. `receiverEncryptionKey == receiverIdentityKey` and `senderIdentityKey == senderEncryptionKey`, but when an event `kind:10044` is present that changes things: + +```js +{ + "kind": 10044, + "pubkey": receiverIdentityKey.public, + "tags": [ + ["n", receiverEncryptionKey.public] + ], + // other fields... +} +``` + +The existence of this event shows that the receiver wants to receive messages encrypted to a different key, so the sender should use that when calling `nip44.compute_conversation_key()` (both during encryption and decryption). + +When sending, `p`-tagging the receiver should still use their _identity key_; and when receiving messages the receiver should still assume the `"author"` field of the seal event contains the _identity 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. @@ -69,7 +90,6 @@ Kind `10050` indicates the user's preferred relays to receive DMs. The event MUS ["relay", "wss://inbox.nostr.wine"], ["relay", "wss://myrelay.nostr1.com"], ], - "content": "", // other fields... } ```