5.2 KiB
NIP-704
More private 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. Privacy wise this is far from ideal.
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 derivingDirect Messages
related keys - nostr
coin_type'
is1237'
(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
- the reason for using the peer's (
Example
If Alice wants to build hedm 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: -
- derive the
dm parent key
:m/25709'/1237'/3bf0c63f'/cb934634'/.../aefa459d'
3bf0c63f
, cb934634
, 07af97a5
, e5ee64fa
, 883d107e
, f9e55847
, 2c4eb9aa
, 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 |
---|---|---|---|
send | 0 |
dmpk/0/<index> |
sending direct messages |
receive | 1 |
dmpk/1/<index> |
receiving direct messages |
draft : republish |
2 |
dmpk/2/<index> |
sending republish events |
draft : market-order |
4500 |
dmpk/4500/<index> |
sending NIP45 market orders |
The client (creator of the dmpk
) must:
- use a new send key (
dmpk/0/<index>
) for each event it signs. It starts from0
and increments after an event is signed. - create filters for the public keys it expects to receive messages to (
dmpk/1/<index>
). It is recommended to listen for the next10
keys and increment the index once a key is used (see BIP-44 address gap logic).
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 (dmpk)>,
"send_index": <integer (optional), the index of the last key used to sign an event>,
"receive_index": <integer (optional), the index of the last key an event was received to>,
}
Note
send_index
andreceive_index
are optional, but they help the client a lot in knowing what the state is. Alternatively (when an account is retored) the client would have to scan the public keys until unused ones are found (similar to BIP-44 address gap logic).
- 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 thed
tag is so that outside observers do not even know thatAlice
andBob
have started to communicate. Any other value for thed
tag would reveal that the message is intended forBob
.
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
.