NIP-704 ====== Key derivation for Encrypted Direct Messages ----------------------------------- `draft` `optional` `author:motorina0` This NIP defines a way for two clients to derive `one-use-only` keys for sending and recieving `kind:4` events. ## Motivation The content of `Direct Messages` [NIP-04](https://github.com/nostr-protocol/nips/blob/master/04.md) is encrypted, but everyone can see who is chatting with whom. This is far from ideal from a privacy perspective. This NIP describes a way to obfuscate DM communications from the "general public", it does not deal with the relay tracking of clients (for that see [NIP XXX](xxx)). ## Suggestion For the maximum of privacy the two participants of a `Direct Message` exchange SHOULD use a different public key for **each** `kind:4` event. This means that each participant has to: - build a `direct message parent key` from which it will derive keys to send and keys to receive (listen for) `kind:4` events - share this `direct message parent key` with its DM peer Each client has a `master` key (denoted with `m`). This key can be the profile `nsec...`, but it is not mandatory. ## Derive the direct message parent key A client must generate multiple `direct message parent keys`, one for each peer that it is communicating with. The [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) structure to be used is: ``` m / purpose' / conin_type'`/ part1' / part2' / ... / part8' ``` - this NIP defines the `purpose` `25709'` (`dm` -> `0x646d` -> `25709`) for deriving `Direct Messages` related keys - nostr `coin_type'` is `1237'` (see [NIP-06](https://github.com/nostr-protocol/nips/blob/master/06.md)) - `part1' / part2' / ... / part8'` is the public key hex string (of the peer) split in 8 chunks: - the reason for splitting is that each level of the path can have a max value of 232-1 - the reason for using the peer's (`Bob`) public key is to always arive at the same value even if prio state is lost When client `Alice` wants to build its `dm parent key` for `Bob` it has to: - get the public key of `Bob` (in hex). Eg: `3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d`. - split the public key hex string in 8 chunks: - `3bf0c63f`, `cb934634`, `07af97a5`, `e5ee64fa`, `883d107e`, `f9e55847`, `2c4eb9aa`, `aefa459d` - derive the `dm parent key`: `m/25709'/1237'/3bf0c63f'/cb934634'/.../aefa459d'` dm//index send, receive, marketplace ## Exchange the `direct message parent key` If `Alice` wants to signal `Bob` that she is ready to use this NIP (for more privacy) she must: - build a JSON data of the form: ```json { "key": , "send_index": , "receive_index": , } ``` - publish a `Parameterized Replaceable Event` ([NIP-33](https://github.com/nostr-protocol/nips/blob/master/33.md)) having: ```json { ... "kind": 35709, "content": , "tags:" [ "d": ] } ``` > **Note** the reason for using `sha256(shared_secret)` for the `d` tag is so that outside observers do not even know that `Alice` and `Bob` have started to communicate. Any other value for the `d` tag would reveal that the message is intended for `Bob.` After both `Alice` and `Bob` have published the `kind: 35709` event, they can start to publish and listen to events using the `one-use-keys`.