Author: Ryan Shea
Initial Draft: Oct 10, 2022
Last Updated: Aug 3, 2023
This is a protocol for privately and discretely sending a cryptocurrency payment to a recipient without requiring interaction with the recipient or requiring the recipient to maintain a notification service.
- Make two "identity" public keys to be used for public key derivations (a root public key and a Diffie-Hellman public key)
- Register the pair of identity public keys in a decentralized public directory
- Map personal identifiers to the keys using web channels (domains, usernames, emails, etc.)
- Perform a diffie-hellman key exchange with every source public key in the directory
- Derive all of your potential recieve addresses
- Monitor all of your potential receive addresses
- Optional: publish an endpoint where you can get receive hints about incoming transactions
- Use a personal identifier of the intended recipient to lookup their source public keys
- Perform a diffie-hellman key exchange with your private key and the recipient's public key to determine a shared secret
- Use the shared secret to determine the recipient's single-use public key
- Send the transaction to the recipient's single-use public key
Symbol | Description |
---|---|
G | Elliptic curve base point |
i | Transaction index # |
ar | Alice's Root Private Key |
br | Bob's Root Private Key |
adh | Alice's Diffie-Hellman Private Key |
bdh | Bob's Diffie-Hellman Private Key |
Symbol | Description | Formula |
---|---|---|
Ar | Alice's Root Public Key | Ar = ar * G |
Br | Bob's Root Public Key | Br = br * G |
Adh | Alice's Diffie-Hellman Public Key | Adh = adh * G |
Bdh | Bob's Diffie-Hellman Public Key | Bdh = bdh * G |
Symbol | Description | Alice's Derivation | Bob's Derivation |
---|---|---|---|
sab | Shared Secret | sab = adh * Bdh | sab = bdh * Adh |
Note: this derivation method implements homogeneous key derivation to protect against various deanonymization attacks.
Symbol | Description | Derivation |
---|---|---|
Si | Shared Hash #i | Si = Hash(sab || i) |
Bi | Bob's Single-Use Public Key #i | Bi = Si * Bdh + Br |
Ai | Alice's Single-Use Public Key #i | Ai = Si * Adh + Ar |
bi | Bob's Single-Use Private Key #i | bi = Si * bdh + br |
ai | Alice's Single-Use Private Key #i | ai = Si * adh + ar |
Hashes should be derived using the key-derivation function HKDF
and the hashing function SHA256
, with no salt, with info
set to the string Key-${i}
where "i" is the index of the key, and with a key length of 40 bytes. The number should then be mapped onto the curve order using a modular operation.
Signers used to recover funds must use deterministic nonces for signing transactions. This is a mitigation designed to prevent nonce reuse from revealing root keys (related-nonce attacks).
Clients must check the validity of public keys before doing calculations with them. This is a mitigation designed to prevent attackers from using invalid public keys to cause a leak of bits of the recipient's DH private keys.
The sender and the recipient both need to be operating with the same public directory.
For this reason, the public directory should be decentralized, reliable, simple to access, and well-known.
The best option for this is storage in a popular blockchain such as Bitcoin or Ethereum.
Optionally, to reduce cost and increase scalability, a blockchain could be used to simply store pointers to centralized directories and have indexers create their own combined indexes across the centralized directories.
Centralized directories and distributed hahs tables should not be used because they cannot guaranteed availability or censorship resistance.
The single-use key derivation process of the protocol is designed to include one of two mitigations: (a) blinding of the root key component (b) homogeneous key derivation. These are each mitigations designed to prevent (a) related-nonce attacks (b) mutual transaction deanonymization.
- An audit was performed by Trail of Bits, which produced a report with various findings, and recommended mitigations were incorporated into the protocol design.
- Stealth Addresses by Robin Linus, 2022
- Silent Payments by Ruben Somsen, 2022
- BIP351 Private Payments by Alfred Hodler & Clark Moody, 2022
- Stealth Payments by Peter Todd, 2015
- BIP47 Reusable Payment Codes by Justus Ranvier, 2015
- Kixunil’s Reusable Taproot Addresses, 2021
- BIP47 Prague Discussion by Ruben Somsen, Afilini, & Kixunil, 2022
- EIP-5564: Non-Interactive Stealth Generation, 2022
- Silent Payments (Bitcoin-Dev), 2022
- Private Payments (Bitcoin-Dev), 2022
- An Incomplete Guide to Stealth Addresses by Vitalik Buterin, 2023
Symbol | Description | Derivation |
---|---|---|
Si | Shared Hash #i | Si = Hash(sab || i) |
Bi | Bob's Single-Use Public Key #i | Bi = Si * G + Br |
Ai | Alice's Single-Use Public Key #i | Ai = Si * G + Ar |
bi | Bob's Single-Use Private Key #i | bi = Si + br |
ai | Alice's Single-Use Private Key #i | ai = Si + ar |
Symbol | Description | Derivation |
---|---|---|
Sx,i | Shared Hash X #i | Sx,i = Hash(sab || "x" || i) |
Sy,i | Shared Hash Y #i | Sy,i = Hash(sab || "y" || i) |
Bi | Bob's Single-Use Public Key #i | Bi = Sx,i * G + Sy,i * Br |
Ai | Alice's Single-Use Public Key #i | Ai = Sx,i * G + Sy,i * Ar |
bi | Bob's Single-Use Private Key #i | bi = Sx,i + Sy,i * br |
ai | Alice's Single-Use Private Key #i | ai = Sx,i + Sy,i * ar |