From 991a35eecd671529e854379907dd81223556fb77 Mon Sep 17 00:00:00 2001 From: DanGould Date: Wed, 1 Nov 2023 16:05:39 -0400 Subject: [PATCH] Include TABConf feedback --- bip-???-payjoin-v2.mediawiki | 176 +++++++++++++++-------------------- 1 file changed, 73 insertions(+), 103 deletions(-) diff --git a/bip-???-payjoin-v2.mediawiki b/bip-???-payjoin-v2.mediawiki index 5c74ac1b3..66ec64096 100644 --- a/bip-???-payjoin-v2.mediawiki +++ b/bip-???-payjoin-v2.mediawiki @@ -12,7 +12,7 @@ ==Abstract== -This document proposes a backwards-compatible second version of the payjoin protocol described in [[bip-0078.mediawiki|BIP 78]], allowing complete payjoin receiver functionality including payment output substitution without requiring them to host a secure public endpoint. This requirement is replaced with an untrusted third-party relay and streaming clients which communicate using an asynchronous protocol and authenticated, encrypted payloads. +This document proposes a backwards-compatible second version of the payjoin protocol described in [[bip-0078.mediawiki|BIP 78]], allowing complete payjoin receiver functionality including payment output substitution without requiring them to host a secure public endpoint. This requirement is replaced with an untrusted third-party relay and HTTP clients which communicate using an asynchronous protocol and authenticated, encrypted payloads. Authenticated encryption depends only on cryptographic primitives available in Bitcoin Core. Requests use Oblivious HTTP to prevent the relay and payjoin peers from linking requests to client IP addresses. ==Copyright== @@ -22,29 +22,29 @@ This BIP is licensed under the 2-clause BSD license. Payjoin solves the sole privacy problem left open in the bitcoin paper, that transactions with multiple inputs "necessarily reveal that their inputs were owned by the same owner." Breaking that common-input ownership assumption and others requires input from multiple owners. Cooperative transaction construction also increases transaction throughput by providing new opportunity for payment batching and transaction cut-through. -Version 1 coordinates payjoins over a public server endpoint secured by either TLS or Tor onion hidden service hosted by the receiver. Version 1 is synchronous, so both sender and reciever must be online simultaneously to payjoin. Both requirements present significant barriers for all but sophisticated server operators or those wallets with complex Tor integration. These barriers are [[https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-January/018358.html|regarded]] as limits to payjoin adoption. +Version 1 coordinates payjoins over a public server endpoint secured by either TLS or Tor hidden service hosted by the receiver. Version 1 is synchronous, requiring both sender and reciever to be online simultaneously to payjoin. Both requirements present significant barriers for all but sophisticated server operators or those wallets with complex Tor integration. Wallet develoepers [[https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-January/018358.html|regard]] these as limits to payjoin adoption. -The primary goal of this proposal is to provide a practical coordination mechanism to be adopted in a vast majority of wallet environments. This is realized as a simple protocol built on bitcoin URI requests, web standards, common crypto, and minimal dependencies. +The primary goal of this proposal is to provide a practical coordination mechanism adaptable to a majority of wallet environments. This is realized as a simple protocol built on bitcoin URI requests, web standards, common crypto, and minimal dependencies. ===Relation to BIP 78 (Payjoin version 1)=== -The message payloads in this version parrallel those used in BIP 78 while being encapsulated in authenticated encryption, forgoing HTTP messaging for WebTransport streaming of asynchronus interactions, and leveraging PSBT version 2. +The message payloads in this version parallel those used in BIP 78 while being encapsulated in authenticated encryption. TLS and Tor security, which depend on third-party authorities, are replaced with Hybrid Public Key Encryption ([[https://www.rfc-editor.org/rfc/rfc9180|HPKE]]). The synchronous HTTP client-server model is replaced with an asynchronous store-and-forward mechanism. This protocol also upgrades to PSBT version 2 to simplify transaction construction. The BIP 78 standard allows for an [[https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki#unsecured-payjoin-server|unsecured payjoin server|]] to operate separately from the so-called "payment server" responsible for generating [[https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki|BIP 21]] request URIs. Because BIP 78 messages relayed over an unsecured server are neither end-to-end authenticated nor encrypted between sender and receiver, a malicious unsecured payjoin server is able to modify the Payjoin PSBT in flight, thus requiring payment output substitition to be disabled. Output substitition is useful for a number of block space optimizations, including payment batching and transaction cut-through. This proposal introduces authentication and encryption to secure output substition while using a relay without compromising sender or receiver privacy. -Although unsecured payjoin server separation is mentioned in BIP 78, no known specification or implementation of one exists. This document specifies one to be backwards compatible with version 1 senders. Receivers responding to version 1 senders must disable output substitution, since their payloads are saved in plaintext, so that they may payjoin without the risk of the relay stealing funds. +Although unsecured payjoin server separation is mentioned in BIP 78, no known specification or implementation exists. This document specifies a way to use the payjoin relay as an unsecured backwards compatible server for version 1 senders. Receivers responding to version 1 senders must disable output substitution, since their payloads are saved in plaintext, so that they may payjoin without the risk of the relay stealing funds. -The protocols in this document reuse BIP 78's BIP 21 URI parameters. A Fallback PSBT timeout parameter is introduced which may also help coordinate the synchronous version 1 protocol. +The protocols in this document reuse BIP 78's BIP 21 URI parameters. A Original PSBT timeout parameter is introduced which may also help coordinate the synchronous version 1 protocol. ===Relation to Stowaway=== -[[https://code.samourai.io/wallet/ExtLibJ/-/blob/develop/doc/cahoots/STOWAWAY.md|Stowaway]] is a payjoin coordination mechanism which depends on Tor, a third-party relay, and the [[https://samouraiwallet.com/paynym|PayNym]] [[https://github.com/bitcoin/bips/blob/master/bip-0047.mediawiki|BIP 47]] Payment codes directory for subdirectory identification and encryption. The payjoin version 2 protocol uses per-request public keys for relay subdirectory identification, authentication, and encryption instead of BIP 47 public keys derived from the wallet. Payjoin version 2 also supports asynchronous messaging, in contrast to online Stowaway's synchronous HTTP-based messaging. Offline stowaway depends on manual message passing rather than an asynchronous network protocol. Successful Stowaway execution results in 2-output transactions, while BIP 78, and this work may produce batched transactions with many outputs. +[[https://code.samourai.io/wallet/ExtLibJ/-/blob/develop/doc/cahoots/STOWAWAY.md|Stowaway]] is a payjoin coordination mechanism which depends on Tor, a third-party relay, and the [[https://samouraiwallet.com/paynym|PayNym]] [[https://github.com/bitcoin/bips/blob/master/bip-0047.mediawiki|BIP 47]] Payment codes directory for subdirectory identification and encryption. The payjoin version 2 protocol uses per-request public keys for relay subdirectory identification, authentication, and encryption instead of BIP 47 public keys derived from a wallet. Payjoin version 2 also supports asynchronous messaging, in contrast to Stowaway's synchronous messaging. Offline stowaway depends on manual message passing rather than an asynchronous network protocol. Successful Stowaway execution results in 2-output transactions, while BIP 78, and this work may produce batched transactions with many outputs. ==Specification== ===Overview=== -Payjoin requests are made using familiar BIP 21 URIs. Instead of a public HTTP endpoint, this scheme allows a WebTransport client to enroll with a relay server to receive payjoin. Relays may optionally require an authorization credential before allocating resources in order to prevent DoS attacks. Sender and receiver payloads are buffered at the relay to support asynchronous interaction. Authenticated encryption prevents the relay from snooping on message contents or forging messages. Aside from a application layer authenticate encryption and relayed asynchronus networking, the version 2 messaging takes much the same form as the existing BIP 78 specification. +Payjoin requests are made using familiar BIP 21 URIs. Instead of a public HTTP endpoint, this scheme allows an HTTP client to enroll with a store-and-forward relay server to receive payjoin. Relays may optionally require an authorization credential before allocating resources in order to prevent DoS attacks. Sender and receiver payloads are buffered at the relay to support asynchronous interaction. Authenticated encryption prevents the relay from snooping on message contents or forging messages by way of HPKE. Oblivious HTTP is required for version 2 interactions in order to separate client IP addresses from the relay to prevent metadata attacks. Aside from a application layer authenticated encryption and relayed asynchronus networking, the version 2 messaging takes much the same form as the existing BIP 78 specification. ===Basic scheme=== @@ -62,19 +62,17 @@ Payjoin v2 messages use [[https://github.com/bitcoin/bips/blob/master/bip-0370.m The payjoin version 2 protocol takes the following steps: -- The recipient sends their payjoin pubkey and optional authentication credential according to [[#receiver-relay-enrollment|receiver relay enrollment]] protocol. It may go offline and replay enrollment to come back online. +- The recipient sends their payjoin pubkey and optional authentication credential according to [[#relay-enrollment|receiver relay enrollment]] protocol. It may go offline and replay enrollment to come back online. - Out of band, the receiver of the payment, shares a bitcoin URI with the sender including a pj= query parameter describing the relay subdirectory endpoint parameter with base64-uri encoded pubkey. To support version 1 senders the relay acts as an unsecured payjoin server so pjos=0 must be specified in the URI. Version 2 senders may safely allow output substitution regardless. -- The sender creates a valid PSBT according to [[https://github.com/bitcoin/bips/blob/master/bip-0078#receivers-original-psbt-checklist|the receiver checklist]] formatted as PSBTv2. We call this the Fallback PSBT. This Fallback PSBT, optional sender parameters, and cryptographic keys are encrypted and authenticated according to the Secp256k1 IK handshake and streamed to the relay subdirectory endpoint. -- The sender awaits a response from the relay stream containing an encrypted Payjoin PSBT as Message B. It can replay the Fallback PSBT Mesasge A to request a response if it goes offline. -- The request is stored in the receiver's subdirectory buffer. -- Once the receiver is online, it awaits a stream of request updates from the relay. The receiver decrypts aund authenticates the payload then checks it according to [[https://github.com/bitcoin/bips/blob/master/bip-0078#receivers-original-psbt-checklist|the receiver checklist]]. It updates it to include new signed inputs and outputs invalidating sender signatures, and may adjust the fee. We call this the Payjoin PSBT. -- It responds with the Payjoin PSBT encrypted then authenticated as Message B according to the Secp256k1 IK handshake. -- The relay awaits a connection from the sender if it goes offline. Upon connection, it relays the encrypted Payjoin PSBT to the sender. +- The sender creates a valid version 2 PSBT satisfying the [[https://github.com/bitcoin/bips/blob/master/bip-0078#receivers-original-psbt-checklist|the receiver checklist]]. We call this the Original PSBT. This Original PSBT, optional sender parameters, and HPKE keys are encrypted and authenticated, and encapsulated in OHTTP. This [[#original-psbt-request|Original PSBT Request]] is sent to the relay's OHTTP Gateway. +- The sender continues to replay this request in order to await a response from the relay containing a Payjoin PSBT. It stops after expiry. +- The request is stored in the relay's subdirectory buffer. +- Once the receiver is online, it sends /receiverequests to await updates from the relay subdirectory. The receiver decrypts and authenticates the response which and checks it according to [[https://github.com/bitcoin/bips/blob/master/bip-0078#receivers-original-psbt-checklist|the receiver checklist]]. It updates it to include new signed inputs and outputs invalidating sender signatures, and may adjust the fee. We call this the Payjoin PSBT. +- The Payjoin PSBT and HPKE keys are encrypted, authenticated, encapsulated in OHTTP, and sent to the relay's OHTTP Gateway. +- The relay awaits a request from the sender if it goes offline. Upon request, it relays the encrypted Payjoin PSBT. - The sender validates the Payjoin PSBT according to [[#senders-payjoin-psbt-checklist|the sender checklist]], signs its inputs and broadcasts the transaction to the Bitcoin network. -The encrypted Fallback PSBT and Payjoin PSBT payloads are sent as bytes. - -The Fallback PSBT MUST: +The Original PSBT MUST: - Include complete UTXO data. - Be signed. @@ -82,80 +80,63 @@ The Fallback PSBT MUST: - Set input and output Transaction Modifiable Flags to 1 - Be broadcastable. -The Fallback PSBT MAY: +The Original PSBT MAY: - Include outputs unrelated to the sender-receiver transfer for batching purposes. - Set SIGHASH_SINGLE Transaction Modifiable Flags flags to 1 The Payjoin PSBT MUST: -- Include all inputs from the Fallback PSBT. -- Include all outputs which do not belong to the receiver from the Fallback PSBT. +- Include all inputs from the Original PSBT. +- Include all outputs which do not belong to the receiver from the Original PSBT. - Include complete UTXO data. The Payjoin PSBT sender MAY: -- Add, remove or modify Fallback PSBT outputs under the control of the receiver (i.e. not sender change). +- Add, remove or modify Original PSBT outputs under the control of the receiver (i.e. not sender change). The Payjoin PSBT MUST NOT: - Shuffle the order of inputs or outputs; the additional outputs or additional inputs must be inserted at a random index. - Decrease the absolute fee of the original transaction. -===Receiver's Payjoin PSBT checklist=== - -Other than requiring PSBTv2 the receiver checklist is the same as the [[https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki#receivers-original-psbt-checklist|the BIP 78 receiver checklist]] - -===Sender's Payjoin PSBT checklist=== - -The version 2 sender's checklist is largely the same as the [[https://github.com/bitcoin/bips/blob/master/bip-0078#senders-payjoin-proposal-checklist|the BIP 78 checklist]] with the exception that it expects ALL utxo data to be filled in. BIP 78 required sender inputs UTXO data to be excluded from the PSBT which has caused many headaches since it required the sender to add them back to the Payjoin proposal PSBT. Version 2 has no such requirement. - -===Relay interactions=== - -The Payjoin Relay provides a rendezvous point for sender and receiver to meet. It stores Payjoin payloads to support asynchronous communication. It is available on the open internet over HTTPS to accept both WebTransport for Payjoin version 2, accepting encrypted payloads, and optionally HTTP/1.1 to support backwards compatible Payjoin version 1 requests. - -===Receiver interactions=== +====Enroll Messaging==== -====Relay enrollment==== +The client discovers the OHTTP gateway's key configuration via an HTTP OPTIONS request to the gateway's URI. -Receivers must enroll to have resources allocated on a relay. Sessions may begin by having a receiver send the static pubkey to the relay. The receiver returns the subdirectory endpoint url with the final subdirectory as base64-uri encoded pubkey. Enrollment may be replayed in case the receiver goes offline. +Receivers must enroll to have resources allocated on a relay. Sessions may begin by having a receiver send the static pubkey to the relay. The receiver returns the subdirectory endpoint url with the final subdirectory as base64-uri encoded pubkey AND an Oblivious HTTP Key Configuration. Enrollment may be replayed in case the receiver goes offline. Optionally, before returning the uri the receiver may request an authentication token by presenting a message containing only the word Authenticate: after which the receiver is required to submit an Authenticate: including the token from the Relay out of band. If authentication fails an error is returned. In the case a relay is operated by an exchange, it may give out authentication tokens for users of its app, or may require some proof of work out of band. Tokens should be anonymous credentials from the relay describing the parameters of their authorization. Specific credentialing is out of the scope of this proposal. -====Receiver Payjoin PSBT response==== +====Send Messaging==== -The receiver streams the base64 Payjoin PSBT as encrypted bytes according to Secp256k1 IK. +The version 2 Original PSBT is placed in an HTTP POST request body, base64 serialized, with text/plain in the Content-Type HTTP header and Content-Length set correctly, as in version 1, before being encoded into BHTTP and encrypted according to the HPKE protocol. This Original PSBT BHTTP Request is then encrypted according to the HPKE, generating an ephemeral keypair `e` from which it derives a shared secret `es` with the receiver's key `s`. It generates a nonce from sufficient randomness, and constructs a ciphertext containing the Original PSBT BHTTP Request and serialized ephemeral key `e`'s pubkey as associated data using ChaCha20Poly1305. A payload is constructed by concatenating the ephemeral pubkey, the nonce, and the ciphertext. This payload is then sent to the relay in an OHTTP request encapsulating the binary payload. -===Sender interactions=== +The relay's OHTTP Gateway decapsulates the OHTTP request, decrypts the payload, and forwards the BHTTP POST request to the receiver's internal subdirectory endpoint which stores the HPKE encrypted payload to be forwarded to the receiver. The relay's OHTTP Gateway then awaits a response from the receiver's subdirectory endpoint, encapsulates it, and responds according to OHTTP. -The sender starts a WebTransport session with the relay at the Payjoin endpoint URI provided by the receiver. It sends the following payload and awaits a relayed response payload from the receiver. +====Receive Messaging==== -====Version 2 Fallback PSBT request==== +The receiver sends a GET request to the path of the subdirectory followed by `/receive`. This request is encapsulated in OHTTP. It awaits an OHTTP response from the relay containing the BHTTP request from the sender with status code 200 OK, or sends a new OHTTP request after receiving 202 ACCEPTED notifying the receiver that the relay has not yet received an request from the sender. -The version 2 Fallback PSBT Payload is constructed in JSON before being encrypted as follows. +Once an Original PSBT Payload is decrypted and checked according to the list, the receiver may respond with a Payjoin PSBT. The receiver encrypts the PSBT according to the HPKE protocol, generating an ephemeral keypair `e` from which it derives a shared secret `ee` with the sender's key `e` from the payload. It generates a nonce from sufficient randomness, and constructs a ciphertext containing the Payjoin PSBT and serialized receiver ephemeral key `e`'s pubkey as associated data using ChaCha20Poly1305. A payload is constructed by concatenating the ephemeral pubkey, the nonce, and the ciphertext. This payload is then sent to the relay in an OHTTP request encapsulating the binary payload as a POST message to the subdirectory followed by `/receive`. -
-{
-  "psbt": "",
-  "params": {
-      "param1": "",
-      "param2": "",
-      ...
-  }
-}
-
+===Receiver's Payjoin PSBT checklist=== -The payload must be encrypted according to Secp256k1 IK. +Other than requiring PSBTv2 the receiver checklist is the same as the [[https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki#receivers-original-psbt-checklist|the BIP 78 receiver checklist]] -====Version 1 Fallback PSBT request==== +===Sender's Payjoin PSBT checklist=== -The message should be the same as version 2 but unencrypted, as version 1 is unaware of encryption when using an unsecured payjoin server. The Relay should convert the PSBT to PSBTv2 and construct the JSON payload from the HTTP request body and optional query parameters. Upon receiving an unencrypted PSBTv2 response from a receiver, it should convert it to PSBTv0 for compatibility with BIP 78. +The version 2 sender's checklist is largely the same as the [[https://github.com/bitcoin/bips/blob/master/bip-0078#senders-payjoin-proposal-checklist|the BIP 78 checklist]] with the exception that it expects ALL utxo data to be filled in. BIP 78 required sender inputs UTXO data to be excluded from the PSBT which has caused many headaches since it required the sender to add them back to the Payjoin proposal PSBT. Version 2 has no such requirement. + +===Relay interactions=== + +The Payjoin Relay provides a rendezvous point for sender and receiver to meet. It stores Payjoin payloads to support asynchronous communication. It must only accept OHTTP requests with an OHTTP Gateway for Payjoin version 2, accepting encrypted payloads. It may optionally accept HTTP/1.1 POST requests without HTTP to enrolled subdirectories to support backwards compatible Payjoin version 1 requests. ===Asynchronous relay buffers=== -Each receiver subdirectory on the relay server has a buffer for requests and one for responses. Each buffer updates listeners through awaitable events so that updates are immediately apparent to relevant client sessions. +Each receiver subdirectory on the relay server has a buffer for requests and one for responses. Each buffer updates listeners through awaitable events so that updates are immediately apparent upon client request. ===BIP 21 receiver parameters=== @@ -163,7 +144,7 @@ A major benefit of BIP 78 payjoin over other coordination mechanisms is its comp This proposal defines the following new [[https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki|BIP 21 URI]] parameters: -- exp: represents a request expiration after which the receiver reserves the right to broadcast the Fallback and ignore requests. This is only necessary for receivers who only support synchonous execution of the protocol, like automated payment processors. +- exp: represents a request expiration after which the receiver reserves the right to broadcast the transaction extracted from the Original PSBT and ignore requests. This is only necessary for receivers who only support synchonous execution of the protocol, like automated payment processors. BIP 78's BIP 21 payjoin parameters are also valid for version 2. @@ -177,79 +158,63 @@ BIP 78's optional query parameters are also valid as version 2 parameters. ==Rationale== -===Request expiration & fallback=== +===Request expiration & Original PSBT=== The relay may hold a request for an offline payjoin peer until that peer comes online. However, the BIP 78 spec recommends broadcasting request PSBTs in the case of an offline counterparty. Doing so exposes a naïve, surveillance-vulnerable transaction which payjoin intends to avoid. -The existing BIP 78 protocol has to be synchronous only for automated endpoints which may be vulnerable to probing attacks. It can cover this tradeoff by demanding a fallback transaction that would not preserve privacy the same way as a payjoin. BIP 21 URI can communicate a request expiration to alleviate both of these problems. Receivers may specify a deadline after which they will broadcast this fallback with a new expiration parameter exp=. - -===WebTransport=== - -Many transport protocols are good candidates for Serverless Payjoin functionality, but WebTransport stands out in its ability to stream and take advantage of QUIC's performance in mobile environments. In developing this BIP, serverless payjoin proofs of concept using TURN, HTTP/1.1 long polling, WebSockets, Magic Wormhole, and Nostr have been made. Streaming allows the relay to have more granular and asynchronous understanding of the state of the peers, and this protcol is designed specifically to address the shortcomings of an HTTP protocol's requirement to receive from a reliable, always-online connection. - -While WebTransport and HTTP/3 it is built on are relatively new, widespread support across browsers assures me that it is being accepted as a standard and even has a fallback to HTTP/2 environments. Being built on top of QUIC allows it to multiplex connections from a relay to multiple peers which may prove advantageous for later payjoin protocols between more than two participants contributing inputs, such as those used to fund a lightning node with channels from multiple sources in one transaction, or those with threat models more similar to ZeroLink CoinJoin. - -While Nostr is fascinating from the perspective of censorship resistance, the backwards compatibility with Payjoin v1 would mean only custom Nostr Payjoin relays exposing an https endpoint would be suitable. Nostr transport is also limited by the performance of WebSockets, being an abstraction on top of that protocol. There is nothing stopping a new version of this protocol or a NIP making Payjoin version 2 possible over Nostr should Payjoin censorship become a bottleneck in the way of adoption. +The existing BIP 78 protocol has to be synchronous only for automated endpoints which may be vulnerable to probing attacks. It can cover this tradeoff by demanding Original PSBT from which a valid payment transaction may be extracted that would not preserve privacy the same way as a payjoin. BIP 21 URI can communicate a request expiration to alleviate both of these problems. Receivers may specify a deadline after which they will broadcast this original with a new expiration parameter exp=. -WebTransport is already shipped in both Firefox, Chrome, h3 in Rust, Go, and all popular languages. There is also [[https://w3c.github.io/p2p-webtransport/|a working draft for full P2P WebTransport]] without any relay, which a future payjoin protocol may make use of. +===HTTP=== -===Secp256k1 IK inspired handshake=== - -<-- The cryptographic handshake is conducted in parallel to the payjoin messaging inspired by the [[http://www.noiseprotocol.org/noise.html#zero-rtt-and-noise-protocols|zero-RTT]] version of the [[http://www.noiseprotocol.org/noise.html|Noise Framework]] [[https://noiseexplorer.com/patterns/NKpsk0/|IK]] pattern. A receiver shares its public key out of band in the BIP21 URI. Static noise keys are only to be used once per session - -====Noise IK pattern==== - -
-NKpsk0:
-  <- s
-  ...
-  -> e, es, s, ss
-  <- e, ee, se
-
+HTTP is ubiquitous. Using simple HTTP polling allows even Bitcoin Core to consider an implementation. Unlike a WebSockets protocol, plain HTTP is eligible to enjoy metadata protection from Oblivious HTTP. -====BIP 21 pre-shared public key==== +===Oblivious HTTP=== -The recipient shares the first handshake message containing the receiver's static public key, i.e. s in Noise framework parlance. The key is encoded in [[https://datatracker.ietf.org/doc/html/rfc4648#section-5|base64url]] encoding so it can be provided in the pj= parameter +OHTTP protects sender and receiver IP addresses from both the relay and one another. This makes it more difficult for a relay to correlate many payjoin transactions with a specific IP addresses by intersection. -====Fallback PSBT Message A==== +OHTTP relays can be run as basic HTTP proxies from wallet providers. Getting OHTTP Gateway configurations does require additional communication between each client and the relay, but this can be done over Tor (hidden service even), a VPN, or provided by a trusted third party like the wallet provider. -Sender derives an ephemeral secp256k1 key pair for this session. Sender derives a shared secret using Elliptic Cureve Diffie-Hellman (ECDH) key agreement. The sender derives a symmetric key +===Message Padding=== -Message A includes a sender ephemeral key, DH shared secret derived from the sender's ephemeral key and the receiver's static key, the sender's static key s, and a shared ss DH secret derived from both sender and receiver's static keys. +TODO ??? TODO -Message A, sent by the sender, benefits from receiver authentication and is resistant to Key Compromise Impersonation. Message contents benefit from message secrecy and some forward secrecy since ephemeral keys are used. The compromise of the receivers's (but not the sender's) static private keys,even at a later date, will lead to message contents being decrypted by an attacker. +All cyphertexts should be padded to the same length to prevent traffic analysis. This is not yet implemented in the reference implementation. -====Payjoin PSBT Message B==== +===Secp256k1 Hybrid Public Key Encryption=== -Message B is encreypted and authenticated using the shared secrets based off of per-session ephemeral keys. +Hybrid Public Key Encryption is a modern web standard for secure message exchange without TLS. Since client and server agree on a configuration out of band, we can pre-define the payjoin v2 appication specific configuration to use DHKEM(Secp256k1, HKDF-SHA256) and ChaCha20Poly1305 AEAD. -The receiver's shared secrets - -The sender can be confident that message B has sender authentication and is Key Compromise Impersonation resistant. If the sender receives a valid message from the receiver, then the receiver must have sent that message, unless the keys have been compromised before this session. If the responder's long-term static keys were previously compromised, the later compromise of the initiator's long-term static keys can lead to message contents being decrypted by an active attacker, should that attacker also have forged the initiator's ephemeral key during the session +The cryptographic handshake is conducted in parallel to the payjoin messaging inspired by the [[http://www.noiseprotocol.org/noise.html#zero-rtt-and-noise-protocols|zero-RTT]] version of the [[http://www.noiseprotocol.org/noise.html|Noise Framework]] [[https://noiseexplorer.com/patterns/NKpsk0/|IK]] pattern. A receiver shares its public key out of band in the BIP21 URI. Static keys shared in URIs must only for a single session. The key is encoded in [[https://datatracker.ietf.org/doc/html/rfc4648#section-5|base64url]] encoding as a subdirectory of the relay server in the pj= parameter. ====Secp256k1==== -Secp256k1 should be used in place of Noise's specified Curve25519 DH functions because of it's availability in bitcoin contexts. +Secp256k1 should be used in place of HPKE's specified DH functions because of it's availability in bitcoin contexts. A proposal to standardize its inclusion may be appropriate. ====ChaCha20Poly1305 AEAD==== This authenticated encryption with additional data [[https://en.wikipedia.org/wiki/ChaCha20-Poly1305|algorithm]] is standardized in [[https://www.rfc-editor.org/rfc/rfc8439|RFC 8439]] and has high performance. ChaCha20Poly1305 AEAD seems to be making its way into bitcoin by way of [[https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki|BIP 324]] as well. The protocol has widespread support in browsers, OpenSSL and libsodium. AES-GCM is more widespread but is both older, slower, and not necessarily already a dependency in bitcoin software. +====HKDF-SHA256==== + +SHA-256 is secure and widely available in bitcoin contexts. + ===PSBT Version 2=== The PSBT version 1 protocol was replaced because it was not designed to have inputs and outputs be mutated. Payjoin mutates the PSBT, so BIP 78 uses a hack where a new PSBT is created by the receiver instead of mutating it. This can cause some strange behaviors from signers who don't know where to look to find the scripts that they are accountable for. PSBT version 2 makes mutating a PSBT's inputs and outputs trivial. It also eliminates the transaction finalization step. Receivers who do not understand PSBT version 1 may choose to reject Payjoin version 1 requests and only support PSBT version 2. ===Attack vectors=== -Since relays store arbitrary encrypted payloads to the tragedy of the commons and denial of service attacks. Relay operators may impose an authentication requirement before they provide relay service to receivers to mitigate such attacks. +Since relays store arbitrary encrypted payloads they are vulnerable to the tragedy of the commons and denial of service attacks. Relay operators may impose an authentication requirement before they provide relay service to receivers to mitigate such attacks. -Since we make use of 0-RTT IK, the first message containing the sender's original PSBT has minimal forward secrecy. If the receiver's key is compromised, this message containing the Fallback PSBT could be read. +Since we make use of 0-RTT HPKE, the first message containing the sender's original PSBT has minimal forward secrecy. If the receiver's key is compromised, this message containing the Original PSBT could be read by the compromiser. -Since the Fallback PSBT is valid, even where exp= is specified, the receiver may broadcast it and lose out on ambiguous privacy protection from payjoin at any time. Though unfortunate, this is the typical bitcoin transaction flow today anyhow. +Since the Original PSBT is valid, even where exp= is specified, the receiver may broadcast it and lose out on savings from payment batching and privacy protection from payjoin structure at any time. Though unfortunate, this failure mode is the typical bitcoin transaction flow today anyhow. -===Network privacy=== +===Network privacy=== -Unlike BIP 78 implementations, sender and receiver peers will only see the IP address of the relay, not their peer's. Relays may be made available via Tor hidden service or Oblivious HTTP in addition to IP / DNS to allow either of the peers to protect their IP from the relay with without requiring both peers to use additional network security dependencies. +Oblivious HTTP must be used to protect the IP address of both sender and receiver from the relay. This requires an additional key configuration to be shared in the bip21 URI and for the relay to support Oblivious HTTP. A secp256k1 HPKE OHTTP configuration should be used to leverage the crypto already in use for the payjoin protocol. + +Unlike BIP 78 implementations, sender and receiver peers will only see the IP address of the relay, not their peer's. Relays may aditionally be made available via Tor hidden service to allow either of the peers to protect their IP from the relay with without OHTTP. ==Backwards compatibility== @@ -257,9 +222,7 @@ The receivers advertise payjoin capabilities through [[https://github.com/bitcoi Senders not supporting payjoin will just ignore the pj= parameter and proceed to typical address-based transaction flows. req-pj= may be used to compel payjoin. -Receivers may choose to support version 1 payloads. Version 2 payjoin URIs should enable pjos=0 so that these v1 senders disable output substitution since the v1 messages are neither encrypted nor authenticated, putting them at risk for man-in-the-middle attacks otherwise. The relay protocol should carry on as normal, validating based on HTTP headers and constructing an unencrypted Version 2 payload from optional query parameters, and PSBT in the body. - -The BIP 78 error messages are already JSON formatted, so it made sense to rely on the same dependency for these payloads and error messages. +Receivers may choose to support version 1 payloads. Version 2 payjoin URIs should enable pjos=0 so that these v1 senders disable output substitution since the v1 messages are neither encrypted nor authenticated, putting them at risk for man-in-the-middle attacks otherwise. The relay protocol should carry on as normal, responding to `/receive` get requests instead with this version 1 request as BHTTP in an OHTTP response. The receiver should POST version 1 Payjoin PSBTs to `/receive` to respond to these version 1 senders within 30 seconds to respond to the sender's request. ==Reference implementation== @@ -267,4 +230,11 @@ An early proof of concept draft reference implementation can be found at https:/ ==Acknowledgements== -Thank you to OpenSats for funding this pursuit, to Human Rights Foundation for putting a bounty on it and funding invaluable BOB Space space support, who I owe a thank you to as well. Thank you to Ethan Heilman, Nicolas Dorier, Kukks, nopara73, Kristaps Kaupe, Kixunil, /dev/fd0/, Craig Raw, Mike Schmidt, Murch, Dávid Molnár, Lucas Ontiviero, waxwing, Christopher Allen, Symphonic, and countless twitter plebs for feedback that has turned this idea from concept into draft, to Mike Jarmuz for suggesting that I write a BIP, and to Satsie for writing the "All About BIPS" zine which I've referenced a number of times in the drafting process. Thanks to Armin Sabouri, Ron Stoner, and Johns Beharry for hacking on the first iOS Payjoin receiver and uncovering the problem that this solves in the first place. \ No newline at end of file +Thank you to OpenSats for funding this pursuit, to Human Rights Foundation for putting a bounty on it and funding invaluable BOB Space space support, who I owe a thank you to as well. Thank you to Ethan Heilman, Nicolas Dorier, Kukks, nopara73, Kristaps Kaupe, Kixunil, /dev/fd0/, Craig Raw, Mike Schmidt, Murch, Dávid Molnár, Lucas Ontiviero, Waxwing, Christopher Allen, Symphonic, Steve Meyers, Sjors Provost, Andrew Chow, and countless plebs for feedback that has turned this idea from concept into draft, to Mike Jarmuz for suggesting that I write a BIP, and to Satsie for writing the "All About BIPS" zine which I've referenced a number of times in the drafting process. Thanks to Armin Sabouri, Ron Stoner, and Johns Beharry for hacking on the first iOS Payjoin receiver and uncovering the problem that this solves in the first place. + + +--- + + +Threat model is that the directry is not actively malicious and should not bee suceptible to log attacks +DNS attack \ No newline at end of file