Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NIP-92: Rendezvous Beacons #333

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions 92.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
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](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.