Skip to content

Instantly share code, notes, and snippets.

@laanwj
Last active August 29, 2015 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save laanwj/9e9c30326e37cd178b5b to your computer and use it in GitHub Desktop.
Save laanwj/9e9c30326e37cd178b5b to your computer and use it in GitHub Desktop.
Pay-to-HS BIP draft
BIP: XX
Title: Pay-to-hidden-service
Author: Wladimir J. van der Laan, Gregory Maxwell
Status: Draft
Type: Standards Track
Created: 2014-12-18

Table of Contents

(TODO)

Abstract

The goal of this BIP is to provide an an authenticated user-to-user channel for payment messages, as well as a simple to use, reusable payment identity.

Motivation

The current BIP70 [4] + BIP71 [5] flow is unwieldy in a user-to-user scenario because of two reasons:

  • It relies on URLs to communicate payment requests. This requires running a web server, or at least upload rights to one
  • Payment requests are authenticated by CA chains. Must users do not have a certificate

This proposal aims to provide an alternative solution. This provides some often-requested features:

  • stable, reusable payment identities
  • a private, off-chain method to send a message (memo) with a payment (through BIP70)
  • as an optional authenticated "from identity" (not a bitcoin address but a reusable HS address)

It does not rely on certificate validation chains, and respects the pseudonymous nature of Bitcoin.

Specification

From a user point of view, (s)he pays to a special kind of Bitcoin address which identifies a Tor HS. A new prefix byte is introduced for this.

This can work because HS are defined using a RSA key pair. The private key is kept private by the provider of the hidden service, whereas the public key is used to identify the service. The first 80 bits of the 160-bit SHA1 hash of the public key are used by clients to connect to the hidden service [6].

As 80 bits of security is not acceptable, the whole 160-bit public key hash must be verified. This happens to fit exactly in a normal-length Bitcoin address. (TODO: is this wise, or should we choose an identifier that does not look like a Bitcoin address?)

The concept is very simple:

  • Participants create one or more identities in the form of Tor hidden service keys. They accept connections to those hidden services speaking the specific protocol described in this BIP.
  • Payer and payee exchange BIP70 payment messages over Tor. All communication goes back and forth over the same connection.

Pay-to-hidden-service addresses

(TODO: Prefix bytes, example addresses, ...)

Protocol

Two parties are involved: payer is the wallet of the sender of the payment and payee is the wallet of the receiver.

  1. Payer connects to Tor hidden service of payee on port XYZ
  2. Optional: Payer does authentication (see below)
  3. Payer reqeusts to send a payment (message: send_payment). This message includes the amount that is desired to be paid
  4. If it accepts the payment, Payee constructs a BIP70 payment request for the desired amount and sends this (message: request_payment). As Tor provides authentication, this can be an unsigned payment request
  5. Payer verifies that the amount specified when sending matches that of the request. If not, it cancels and disconnects
  6. Payer creates and signs the transaction
  7. Payer sends the signed transaction to the payee (message: payment)
  8. Payee sends back a payment ACK (message: packment_ack)
  9. Payee disconnects

If the payer wishes to authenticate (for explanation see "Bidirectional authentication"),

  1. Payer sends its own HS address, an optional freeform label, and a nonce A (message: identify)
  2. Payee connects to HS address specified by payer on port XYZ
  3. Payee sends a nonce B, along with its own the none A sent by the payer for identification (message: nonce)
  4. Payee disconnects connection made in step 2
  5. Payer sends back nonce B over existing connection (message: nonce_reply)

If the payer authenticates in this way, the payee can add the "from identity" to its administration for the transaction, and show it in e.g. its user interface.

(TODO: pick port XYZ. Do we need a different port for testnet/mainnet? identities would be separate anyhow)

Messages

Payer to payee:

  • send_payment(amount): (TODO: define wire format)
  • payment(merchant_data, transactions, refund_to, memo): see BIP 71 under "Payment"
  • cancel(): (TODO: define wire format)
  • identify(fromhs, fromlabel, nonce_A): (TODO: define wire format)
  • nonce_reply(nonce_B): (TODO: define wire format)

Payee to payer:

  • request_payment(payment_request): see BIP 71 under "PaymentRequest"
  • payment_ack(memo): see BIP 71 under "PaymentACK"
  • nonce(nonce_A, nonce_B): (TODO: define wire format)

(TODO: define framing wire format)

Bidirectional authentication

Onion connections have no origin address. To provide for optional bidirectional authentication, we use the same method as Torchat[1].

One side is authenticated by accepting the connection to the HS in the first place, the other side is authenticated by sending back a nonce to it's claimed HS address, then asking for it over the existing connection:

  • A initiates connection to B, and sends its own onion address for call back, as well as a nonce to authenticate the callback connection
  • B connects to A's claimed address, and sends a nonce, along with the nonce provided by A, then immediately disconnects
  • A sends back B's nonce to B over the existing connection
  • B now knows that A is who he claims he is

DoS concerns

The hidden service provides a direct channel to the user. Care has to be taken that a payer can't exhaust the resources of a payee by repeatedly asking it to create payment requests... (needs some kind of rate limiting)

Payee has to reserve ECDSA keypair(s) only as long as the connection is open, and if a valid signed transaction is received. If the payment is cancelled, or the connection is terminated without receiving a valid signed transaction, the keypair(s) could be returned to a pool.

Advantages

  • HS identifiers provide a stable pay-to identity. Generating new addresses happens entirely in the background, invisible to the user.

  • Optional two-way authentication can provide a "from identity"

  • Extra private data can be sent with the payment, e.g. messages, which does not show up in the block chain in any way

  • Provides instant feedback on whether the recipient accepts the transaction. Removes risk of sending to no-longer-attended addresses.

  • Tor provides the encryption and authentication, gives reasonable privacy, and solves the problem of users connecting through each other behind NATs

Disadvantages

The disadvantages are related to the synchronous, low-latency nature of Tor.

  • The sender and recipient have to be online at the same time.

    (This doesn't necessarily mean the payee needs to be online at time the payer sends the payment. After sending the transaction in the UI, the sender could keep trying to connect, exponentially backing off, until expiration or until the user cancels. However, as we need to be able to sign a transaction as soon as the payee comes online and replies with a payment request, this does not interact well with encrypted wallets)

  • An adversary can determine when the payee's wallet is online by pinging the hidden service. This could be used to make a time profile.

Appendix: Hidden service names

(TODO:

  • describe how to convert address to SHA1 hash + test vectors
  • describe how to convert SHA1 hash to address + test vectors
  • describe convert SHA1 hash to .onion for connection + test vectors
  • describe how to verify the complete 160-bit hidden service pubkey hash with Tor )

Appendix: Hidden service management from wallet

Although this BIP makes no statement as to where the HS keys should be stored, in a user to user payment scenario the most straightforward manager of the private keys would be the wallet, not the Tor configuration.

Dynamically creating and removing Tor hidden services from an application is possible through the control port [2]. An example of doing this from Python is given in [3].

References

[1] https://github.com/prof7bit/TorChat

[2] https://gitweb.torproject.org/torspec.git/tree/control-spec.txt

[3] https://jordan-wright.github.io/blog/2014/10/06/creating-tor-hidden-services-with-python

[4] https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki

[5] https://github.com/bitcoin/bips/blob/master/bip-0071.mediawiki

[6] https://trac.torproject.org/projects/tor/wiki/doc/HiddenServiceNames

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment