nips/92.md
2023-03-08 06:13:44 +00:00

3.6 KiB

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:

"nip92": [<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.

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.