nips/704.md
2023-04-10 13:09:35 +03:00

4.3 KiB

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 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).

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 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)
  • part1' / part2' / ... / part8' is the public key hex string (of the peer) split in 8 chunks:
    • the reason for using the peer's (Bob) public key is to always arive at the same value even if prio state is lost
    • the reason for splitting the public key is that each level of the path can have a max value of 232-1
Example If Alice wants to build he dm parent key for Bob then she 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'

We notate the above derived direct message public key with dmpk. Then we can define paths of the form dmpk/<action>/index.

Action Name Value Path Derive keys for
receive 0 dmpk/0/<index> receiving direct messages
send 1 dmpk/1/<index> sending direct messages
republish 2 dmpk/2/<index> sending republish events
draft :market-order 4500 dmpk/4500/<index> sending NIP45 market orders

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:
 {
  "key": <the direct message parent key>,
  "send_index": <integer (optional), ...>,
  "receive_index": <integer (optional), ...>,
 }
  • publish a Parameterized Replaceable Event (NIP-33) having:
 {
  ...
  "kind": 35709,
  "content": <NIP-04 encrypted content of the JSON data>,
  "tags:" [
    "d": <sha256 of the shared secret as defined in NIP-04>
  ]
 }

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 both published the kind: 35709 event, they can start to publish and listen to events using the one-use-keys.