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": [,,...]` `` 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" + `. `` is the pubkey to use together with the key for the secret beacon to derive a shared secret as described below. `` 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 `` 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 ``. 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.