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 below2³²
. - For
j
in0, 1, ...
:- Let
p
be the 2-byte encoding ofi
followed by the 4-byte encoding of(j * d) mod 2³²
, each with the most significant byte first. - Let
c
be the byte-wisexor
ofp
andk[0:6]
. - Construct the beacon event, with
A
as thepubkey
andc
as thecontent
. - If the resulting
id
matches the required prefix, break out of the loop.
- Let
- 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.