mirror of
https://github.com/bitcoin/bips.git
synced 2025-01-18 21:35:13 +01:00
181 lines
8.2 KiB
Plaintext
181 lines
8.2 KiB
Plaintext
<pre>
|
||
BIP: XXX
|
||
Title: Out of Band Address Exchange using Encrypted PaymentRequests
|
||
Authors: Matt David <matt@netki.com>
|
||
Justin Newton <justin@netki.com>
|
||
Aaron Voisine <voisine@gmail.com>
|
||
Status: Draft
|
||
Type: Informational
|
||
Created: 2015-11-20
|
||
</pre>
|
||
|
||
==Abstract==
|
||
|
||
This BIP is an extension to BIP70 that extends the payment protocol to prevent PaymentRequet interception / modification
|
||
during transmission using ephemeral key encryption. This also allows permissioned release of a PaymentRequest to a requestor
|
||
and allows a requestor to supply a certificate and signature to the PaymentRequest creator.
|
||
|
||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and
|
||
"OPTIONAL" in this document are to be interpreted as described in RFC 2119.
|
||
|
||
==Motivation==
|
||
|
||
The motiviation for defining this extension to the BIP-70 Payment Protocol is to allow 2 parties to exchange payment
|
||
information in a permissioned and encrypted way such that wallet address communication can become a more automated process.
|
||
Additionally, this extension allows for the requestor of a PaymentRequest to supply a certificate and signature in order
|
||
to facilitate identification for address release.
|
||
|
||
==Definitions==
|
||
{| class="wikitable"
|
||
| Sender || Entity wishing to transfer value that they control
|
||
|-
|
||
| Receiver || Entity receiving a value transfer
|
||
|}
|
||
|
||
==Acronyms==
|
||
{| class="wikitable"
|
||
! Acronym !! Expanded !! Description
|
||
|-
|
||
| IR || InvoiceRequest || A request to create and return an encrypted PaymentRequest
|
||
|-
|
||
| RPR || ReturnPaymentRequest || A message returned based on a submitted InvoiceRequest containing an encrypted PaymentRequest
|
||
|}
|
||
|
||
==New Messages==
|
||
|
||
===InvoiceRequest===
|
||
The InvoiceRequest message allows a Sender to send information to the Receiver such that they can create and return a ReturnPaymentRequest.
|
||
|
||
<pre>
|
||
message InvoiceRequest {
|
||
required bytes sender_public_key = 1; // Sender's EC Public Key
|
||
optional uint64 amount = 2 [default = 0]; // amount is integer-number-of-satoshis
|
||
optional string pki_type = 3 [default = "none"]; // none / x509+sha256
|
||
optional bytes pki_data = 4; // Depends on pki_type
|
||
optional string notification_url = 5; // URL to notify on ReturnPaymentRequest ready
|
||
optional bytes signature = 6; // PKI-dependent signature
|
||
}
|
||
</pre>
|
||
|
||
{| class="wikitable"
|
||
! Field Name !! Description
|
||
|-
|
||
| sender_public_key || Sender's EC Public Key
|
||
|-
|
||
| amount || amount is integer-number-of-satoshis (default: 0)
|
||
|-
|
||
| pki_type || none / x509+sha256 (default: "none")
|
||
|-
|
||
| pki_data || Depends on pki_type
|
||
|-
|
||
| notification_url || Secure (usually HTTPS) location where a ReturnPaymentRequest (see below) may be sent when ready
|
||
|-
|
||
| signature || PKI-dependent signature
|
||
|}
|
||
|
||
===ReturnPaymentRequest===
|
||
|
||
The ReturnPaymentRequest message is an encapsulating message that allows the transmission of an encrypted, serialized PaymentRequest.
|
||
|
||
<pre>
|
||
message ReturnPaymentRequest {
|
||
required bytes encrypted_payment_request = 1; // Encrypted, Serialized PaymentRequest
|
||
required bytes receiver_public_key = 2; // Receiver's EC Public Key
|
||
required bytes ephemeral_public_key = 3; // Public Key of keypair created with ECDH-derived secret point
|
||
required bytes payment_request_hash = 4; // SHA256 of Serialized PaymentRequest
|
||
}
|
||
</pre>
|
||
{| class="wikitable"
|
||
! Field Name</b> !! Description
|
||
|-
|
||
| encrypted_payment_request || AES-256-CBC Encrypted Serialized PaymentRequest
|
||
|-
|
||
| receiver_public_key || Receiver's EC Public Key
|
||
|-
|
||
| ephemeral_public_key || Ephemeral EC Public Key
|
||
|-
|
||
| payment_request_hash || SHA256 Hash of Non-Encrypted, Serialized PaymentRequest
|
||
|}
|
||
|
||
==InvoiceRequest / ReturnPaymentRequest Process==
|
||
|
||
===Overview===
|
||
|
||
# Sender creates InvoiceRequest
|
||
# Sender transmits InvoiceRequest to Receiver
|
||
# Receiver validates InvoiceRequest
|
||
# Receiver creates PaymentRequest
|
||
# Receiver encrypts the PaymentRequest
|
||
# Receiver creates ReturnPaymentRequest (containing an encrypted PaymentRequest)
|
||
# Receiver transmits ReturnPaymentRequest to Sender
|
||
# Sender validates ReturnPaymentRequest
|
||
# Sender decrypts and validates encrypted PaymentRequest
|
||
|
||
This overview flow is illustrated below:
|
||
|
||
<img src=bip-ir/overview_flow.png></img>
|
||
|
||
===Message Interaction Details===
|
||
|
||
====InvoiceRequest====
|
||
Sender must transmit InvoiceRequest to Receiver (or Receiver's agent) via TLS-protected HTTP. Sender transmitting InvoiceRequest
|
||
messages must set appropriate Content-Type headers as specified here:
|
||
<pre>Content-Type: application/bitcoin-invoicerequest</pre>
|
||
|
||
====ReturnPaymentRequest====
|
||
Receiver must transmit ReturnPaymentRequest to Sender (or Sender's agent) via TLS-protected HTTP. Receiver transmitting
|
||
ReturnPaymentRequest messages must set appropritate Content-Type headers as specified here:
|
||
<pre>Content-Type: application/bitcoin-returnpaymentrequest</pre>
|
||
|
||
====Message or Communication Errors====
|
||
An invalid or unparsable message or communications error must be communicated to the party that initiated the communication. This
|
||
should be done through standard HTTP Status Code messaging ([https://tools.ietf.org/html/rfc7231 RFC 7231 Section 6]).
|
||
|
||
===InvoiceRequest Message Creation===
|
||
|
||
* Create an InvoiceRequest message
|
||
* sender_public_key MUST be set to the public key of an EC keypair.
|
||
* Amount is optional
|
||
* Set notification_url to URL that the Receiver will submit completed ReturnPaymentRequest to
|
||
* If NOT including certificate, set pki_type to "none"
|
||
* If including certificate:
|
||
** Set pki_type to "x509+sha256"
|
||
** Set pki_data as it would be set in BIP-0070 (see [https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki#Certificates Certificates]) section)
|
||
** Sign InvoiceRequest with signature == "" using the X509 Certificate's private key
|
||
|
||
===InvoiceRequest Validation===
|
||
* Validate sender_public_key is a valid EC public key
|
||
* Validate notification_url if set, contains characters deemed valid for a URL (avoiding XSS related characters, etc).
|
||
* If pki_type is None, InvoiceRequest is VALID
|
||
* If pki_type is x509+sha256 and signature is valid for the serialized InvoiceRequest where signature is set to "", InvoiceRequest is VALID
|
||
|
||
===ReturnPaymentRequest Message Creation and PaymentRequest Encryption===
|
||
* Encrypt the serialized PaymentRequest using AES-256-CBC setup as described in <b>ECDH Point Generation and AES-256 (CBC Mode) Setup (see below)</b>
|
||
* Create ReturnPaymentRequest message
|
||
* Set encrypted_payment_request to be the encrypted value of the PaymentRequest
|
||
* Set receiver_public_key to the Receiver's EC public key (of which the private key was previously used in ECDH secret point calculation)
|
||
* Set ephemeral_public_key to the public key of an EC keypair created using the secret point's X value.
|
||
* Set payment_request_hash to generated SHA256 hash of the serialized PaymentRequest (without encryption)
|
||
|
||
===ReturnPaymentRequest Validation and Decryption===
|
||
* Validate ephemeral_public_key matches public key of an EC keypair created using the secret point's X value.
|
||
* Decrypt the serialized PaymentRequest using AES-256-CBC setup as described in <b>ECDH Point Generation and AES-256 (CBC Mode) Setup (see below)</b>
|
||
* Validate payment_request_hash matches SHA256 of the decrypted, serialized PaymentRequest
|
||
* Deserialize the serialized PaymentRequest
|
||
|
||
===ECDH Point Generation and AES-256 (CBC Mode) Setup===
|
||
* Generate the '''secret point''' using [https://en.wikipedia.org/wiki/Elliptic_curve_Diffie–Hellman ECDH] using the local entity's private key and the remote entity's public key as inputs.
|
||
* Initialize [http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf HMAC_DRBG]
|
||
** Use '''secret point's''' X value for Entropy
|
||
** Use Sender's public key for Nonce
|
||
* Initialize AES-256 in CBC Mode
|
||
** Use HMAC_DRBG.GENERATE(32) as the Encryption Key (256 bits)
|
||
** Use HMAC_DRBG.GENERATE(16) as the Initialization Vector (IV) (128 bits)
|
||
|
||
==Reference==
|
||
|
||
* [[bip-0070.mediawiki|BIP70 - Payment Protocol]]
|
||
* [https://en.wikipedia.org/wiki/Elliptic_curve_Diffie–Hellman ECDH]
|
||
* [http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf HMAC_DRBG]
|
||
* [https://tools.ietf.org/html/rfc6979 RFC6979]
|