mirror of
https://github.com/nostr-protocol/nips.git
synced 2026-08-08 23:34:40 +00:00
decoupling identity and encryption keys in NIP-17.
This commit is contained in:
@@ -25,39 +25,60 @@ Following [NIP-59](59.md), the **unsigned** chat messages must be sealed (`kind:
|
||||
```js
|
||||
{
|
||||
"id": "<usual hash>",
|
||||
"pubkey": wrapperPublicKey,
|
||||
"pubkey": wrapperKey.public,
|
||||
"created_at": randomTimeUpTo2DaysInThePast,
|
||||
"kind": 1059, // gift wrap
|
||||
"tags": [
|
||||
["p", receiverPublicKey, "<relay-url>"] // receiver
|
||||
["p", receiverIdentityKey.public, "<relay-url>"] // receiver
|
||||
],
|
||||
"content": nip44.encrypt(
|
||||
{
|
||||
"id": "<usual hash>",
|
||||
"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": "<signed by senderPrivateKey>"
|
||||
"sig": "<signed by senderIdentity.private>"
|
||||
},
|
||||
nip44.compute_conversation_key(wrapperPrivateKey, receiverPublicKey)
|
||||
nip44.compute_conversation_key(wrapperKey.private, receiverEncryptionKey.public)
|
||||
),
|
||||
"sig": "<signed by randomPrivateKey>"
|
||||
"sig": "<signed by wrapperKey.private>"
|
||||
}
|
||||
```
|
||||
|
||||
`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...
|
||||
}
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user