diff --git a/92.md b/92.md new file mode 100644 index 00000000..28e9e39f --- /dev/null +++ b/92.md @@ -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: + +`"bip92": [,,...]` + +`` 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.