nips/92.md

100 lines
3.6 KiB
Markdown
Raw Normal View History

2023-03-07 16:19:38 -05:00
NIP-92
==========================
Rendezvous Beacons
------------------
`draft` `optional` `author:shafemtol`
A rendezvous beacon is used to anonymously deliver a secret event to a recipient
without prior communication between sender and recipient. Apart from its
timestamp, a rendezvous beacon is indistinguishable from any other rendezvous
beacon of the same kind on the same relay.
A stored rendezvous beacon has kind `9992`, while an ephemeral rendezvous beacon
has kind `29992`.
`pubkey` MUST be a unique public key with no publicly known relation to any
other event.
`content` MUST be the 8-character base64 encoded string of a 6-byte combined
hash/nonce, generated as described below.
For stored beacons, `tags` SHOULD contain a `NIP-40` `expiration` tag with a
value of `created_at` plus exactly `10000000` (ten million) seconds and no other
tags. It is not recommended to use stored rendezvous beacons on relays that do
not support `NIP-40`.
For ephemeral beacons, `tags` SHOULD be an empty list.
`created_at` SHOULD be approximately the time the event is submitted to the
relay.
Public User Metadata
--------------------
In order for the sender to know how to reach the recipient, the recipient needs
to publish some parameters in their `set_metadata` event, with the following
attribute:
`"bip92": [<subprefix>,<recipient_pubkey>,<relays>...]`
`<subprefix>` MUST be either an empty string or a single hexadecimal character.
In order to match the recipient's subscription filter, the `id` of the beacon
MUST have a prefix that matches `"0000" + <subprefix>`.
`<recipient_pubkey>` is the pubkey to use together with the key for the secret
beacon to derive a shared secret as described below.
`<relays>` are the remaining items in the list, specifying the relays where the
recipient expects to receive a beacon.
Beacon Generation
-----------------
- Generate a random keypair `a, A`.
- Derive the shared secret `S` as described below.
- Let `k = bytes(tagged_hash("NIP0092/beacon", bytes(x(S))))`.
- Let `i` be the 0-indexed position in `<relays>` where the secret event is to
be found.
- Let `d` be a random odd positive integer below `2³²`.
- For `j` in `0, 1, ...`:
- Let `p` be the 2-byte encoding of `i` followed by the 4-byte encoding of
`(j * d) mod 2³²`, each with the most significant byte first.
- Let `c` be the byte-wise `xor` of `p` and `k[0:6]`.
- Construct the beacon event, with `A` as the `pubkey` and `c` as the
`content`.
- If the resulting `id` matches the required prefix, break out of the loop.
- Sign the beacon event using `a` and deliver it to one of the relays listed in
`<relays>`.
Shared Secret Derivation
------------------------
Given the keypair `a, A` of the beacon (`A` being its `pubkey`) and the keypair
`b, B` of the recipient (`B` being their `recipient_pubkey`), the shared
secret is simply the point `S` resulting from ECDH operation, that is, `S =
a⋅B`, or equivalently, `S = b⋅A`. The shared secret is used in subsequent
derivations as `tagged_hash(tag, bytes(x(S)))`, with the functions as defined in
[BIP-340](https://bips.xyz/340).
Secret Event Delivery
---------------------
The secret event to be delivered to the recipient is given the rendezvous
keypair `r, R` (`R` being the `pubkey`), calculated as follows:
- `t = bytes(tagged_hash("NIP0092/tweak", bytes(x(S))))`
- `r = (a + t) mod n`
- `R = A + t⋅G`
The sender is able to derive `r` and uses this to construct and sign the secret
event.
From the beacon, the recipient derives the shared secret and is thus able to
learn `R`. The recipient uses `R` to find the secret event on the relay
indicated in the beacon.