Skip to content

Instantly share code, notes, and snippets.

@shea256
Last active January 26, 2024 23:50
Show Gist options
  • Save shea256/e4a8dccd1e83fa801c7328a0af611798 to your computer and use it in GitHub Desktop.
Save shea256/e4a8dccd1e83fa801c7328a0af611798 to your computer and use it in GitHub Desktop.

Private Social Payments

Author: Ryan Shea

Initial Draft: Oct 10, 2022

Last Updated: Aug 3, 2023

Overview

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.

Protocol

Initial Setup

  1. Make two "identity" public keys to be used for public key derivations (a root public key and a Diffie-Hellman public key)
  2. Register the pair of identity public keys in a decentralized public directory
  3. Map personal identifiers to the keys using web channels (domains, usernames, emails, etc.)

Preparation to Receive

  1. Perform a diffie-hellman key exchange with every source public key in the directory
  2. Derive all of your potential recieve addresses
  3. Monitor all of your potential receive addresses
  4. Optional: publish an endpoint where you can get receive hints about incoming transactions

Sending

  1. Use a personal identifier of the intended recipient to lookup their source public keys
  2. Perform a diffie-hellman key exchange with your private key and the recipient's public key to determine a shared secret
  3. Use the shared secret to determine the recipient's single-use public key
  4. Send the transaction to the recipient's single-use public key

Symbols, Keys and Shared Secrets

Base Symbols

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

Identity Public Keys

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

Shared Secret Derivation

Symbol Description Alice's Derivation Bob's Derivation
sab Shared Secret sab = adh * Bdh sab = bdh * Adh

Single-Use Key Derivations

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

Implementation Considerations

Hash Derivations

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

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

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.

Public Key Directory

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.

Key-Derivation Mitigations

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.

Code

Examples in JavaScript/TypeScript

Audits

  • An audit was performed by Trail of Bits, which produced a report with various findings, and recommended mitigations were incorporated into the protocol design.

References

Top Protocol References

Additional Protocol References

Discussions and Articles

Appendices

Original Design of Derivations of Single-Use Keys (w/out mitigations)

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

Alternative Design of Derivations of Single-Use Keys (w/ root key blinding)

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment