From 8bb63058fd80b6b89b2e09de402ad5ba635e9eeb Mon Sep 17 00:00:00 2001 From: Matt David Date: Tue, 26 Apr 2016 15:23:12 -0700 Subject: - Reset bip-0070/extensions.mediawiki to the original BIP70 contents - Remove status_code and status_message from individual Payment Protocol messages - Remove EncryptedInvoiceRequest, EncryptedPaymentRequest, EncryptedPayment and EncryptedPaymentACK messages from protobuf definition file - Add ProtocolMessageType enum and ProtocolMessageType and EncryptedProtocolMesssage messages to bip-0075/paymentrequest.proto definition file - Update BIP75 text to remove old individual message encryption paths and include new encapsulating messages for self-contained PaymentProtocol communication (including errors) over various transport layers - Add initial list of status codes - Update BIP75 to use AES-256-GCM and remove message hash as GCM mode provides authenticated encryption - Update ECDH calculation to use SHA256 hash of ECDH's X point instead of the raw X point itself --- bip-0070/extensions.mediawiki | 4 +- bip-0075.mediawiki | 345 +++++++++++++----------------------------- bip-0075/paymentrequest.proto | 70 +++------ 3 files changed, 128 insertions(+), 291 deletions(-) diff --git a/bip-0070/extensions.mediawiki b/bip-0070/extensions.mediawiki index 947622d..b572b1d 100644 --- a/bip-0070/extensions.mediawiki +++ b/bip-0070/extensions.mediawiki @@ -5,7 +5,5 @@ Add your extension below using tags starting at 1000 and submit a pull-req. {| | Field Number || Extension Name || Field Name || Description |- -| 1000 || [[https://github.com/bitcoin/bips/bip-0075.mediawiki|(BIP75)]] || status_code || Status Code for Payment Protocol error communication -|- -| 1001 || [[https://github.com/bitcoin/bips/bip-0075.mediawiki|(BIP75)]] || status_message || Human-readable message for Payment Protocol error communication +| 1000 || [[https://example.com|(unassigned)]] || (unassigned) || (unassigned) |} \ No newline at end of file diff --git a/bip-0075.mediawiki b/bip-0075.mediawiki index 6bac44a..3b0ba1f 100644 --- a/bip-0075.mediawiki +++ b/bip-0075.mediawiki @@ -14,9 +14,9 @@ This BIP is an extension to BIP 70 that provides two enhancements to the existing Payment Protocol. -# It allows the requester (Sender) of a Payment Request to voluntarily sign the original request and provide a certificate to allow the payee to know the identity of who they are transacting with. +# It allows the requester (Sender) of a PaymentRequest to voluntarily sign the original request and provide a certificate to allow the payee to know the identity of who they are transacting with. -# It encrypts the Payment Request that is returned, before handing it off to the SSL/TLS layer to prevent man in the middle viewing of the Payment Request details. +# It encrypts the PaymentRequest that is returned, before handing it off to the SSL/TLS layer to prevent man in the middle viewing of the Payment Request details. 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. @@ -69,12 +69,12 @@ A Bitcoin wallet developer would like to use a public Store & Forward service fo With this BIP, returned payment information is encrypted with an ECDH-computed shared key before sending to a Store & Forward service. In this case, a successful attack against a Store & Forward service would not be able to read or modify wallet address or payment information, only delete encrypted messages. ==New Messages== -Updated [/bip-0075/paymentrequest.proto paymentrequest.proto] contains the existing PaymentRequest Protocol Buffer messages as well asthe messages newly defined in this BIP. +Updated [/bip-0075/paymentrequest.proto paymentrequest.proto] contains the existing PaymentRequest Protocol Buffer messages as well as the messages newly defined in this BIP. Note: Public keys from both parties must be known to each other in order to facilitate encrypted communication. Although including both public keys in every message may get redundant, it provides the most flexibility as each message is completely self-contained. ===InvoiceRequest=== -The InvoiceRequest message allows a Sender to send information to the Receiver such that they can create and return a PaymentRequest. +The InvoiceRequest message allows a Sender to send information to the Receiver such that the Receiver can create and return a PaymentRequest.
 message InvoiceRequest {
@@ -106,190 +106,97 @@ message InvoiceRequest {
 | signature             || PKI-dependent signature
 |}
 
-
-===EncryptedInvoiceRequest===
-The EncryptedInvoiceRequest message allows a Sender to send an encrypted InvoiceRequest to the Receiver such that the details of the InvoiceRequest are kept secret.
+===ProtocolMessageType Enum===
+The ProtocolMessageType enum is defined in an extensible way to allow for new message type additions to the Payment Protocol. This enum is used in the newly defined ProtocolMessage and EncryptedProtocolMessage messages to define the serialized message type.
 
-message EncryptedInvoiceRequest {
-    required bytes  encrypted_invoice_request = 1;
-    required bytes  invoice_request_hash = 2;
-    required bytes  sender_public_key = 3;
-    required bytes  receiver_public_key = 4;
-    required uint64 nonce = 5;
-    optional bytes  signature = 6;
-    optional bytes  identifier = 7;
-    
+enum ProtocolMessageType {
+    INVOICE_REQUEST = 0;
+    PAYMENT_REQUEST = 1;
+    PAYMENT = 2;
+    PAYMENT_ACK =  3;
 }
 
-{| class="wikitable" -! Field Name !! Description -|- -| encrypted_invoice_request || AES-256-CBC encrypted, serialized InvoiceRequest -|- -| invoice_request_hash || SHA256 Hash of non-encrypted, serialized InvoiceRequest. MUST be used for verification to prevent oracle attacks. -|- -| sender_public_key || Sender's EC public key -|- -| receiver_public_key || Receiver's EC public key -|- -| nonce || The nonce in use for the CBC encryption -|- -| signature || A signature of this message using Sender's EC key, serialized with a value of "" for signature. REQUIRED if server requires authentication. -|- -| identifier || A unique key to identify this entire exchange on the server. invoice_request_hash SHOULD be used by default. -|} - -===EncryptedPaymentRequest=== - -The EncryptedPaymentRequest message is an encapsulating message that allows the transmission of an encrypted, serialized PaymentRequest. - +===ProtocolMessage=== +The ProtocolMessage message is an encapsulating wrapper for any Payment Protocol message. It allows two-way, non-encrypted communication of Payment Protocol messages. The message also includes a status code and a status message that is used for error communication so the protocol does not rely on transport-layer error handling.
-message EncryptedPaymentRequest {
-        required bytes  encrypted_payment_request = 1;
-        required bytes  payment_request_hash = 2;
-        required bytes  receiver_public_key = 3;
-        required bytes  sender_public_key = 4;
-        required uint64 nonce = 5;
-        optional bool   requires_payment_message = 6;
-        optional bytes  signature = 7;
-        optional bytes  identifier = 8;
+message ProtocolMessage {
+    required ProtocolMessageType message_type = 1;
+    required bytes serialized_message = 2;
+    optional uint64 status_code = 3;
+    optional string status_message = 4;
+    optional bytes identifier = 5;
 }
 
-{| class="wikitable" -! Field Name !! Description -|- -| encrypted_payment_request || AES-256-CBC encrypted, serialized BIP70 PaymentRequest -|- -| payment_request_hash || SHA256 Hash of non-encrypted, serialized PaymentRequest. MUST be used for verification to prevent oracle attacks. -|- -| receiver_public_key || Receiver's EC public key -|- -| sender_public_key || Sender's EC public key -|- -| nonce || The nonce in use for the CBC encryption -|- -| requires_payment_message || Internal PaymentRequest requires follow-up Payment message -|- -| signature || A signature of this message using Receiver's EC key, serialized with a value of "" for signature. REQUIRED if server requires authentication. -|- -| identifier || MUST use the identifier specified with the InvoiceRequest if the PaymentRequest is in response to an InvoiceRequest. Otherwise, use payment_request_hash or other unique value. -|} -===EncryptedPayment=== - -The EncryptedPayment message allows a BIP70 Payment message to be transmitted through a third party without revealing the details of the transaction. This message allows Store & Forward servers or other third parties to match and authenticate PaymentRequest and Payment messages without revealing the details of the transaction, thereby protecting privacy. - -
-message EncryptedPayment {
-        required bytes  encrypted_payment = 1;
-        required bytes  payment_hash = 2;
-        required bytes  sender_public_key = 3;
-        required bytes  receiver_public_key = 4;
-        required uint64 nonce = 5;
-        optional bytes  signature = 6;
-        optional bytes  identifier = 7;
-}
-
{| class="wikitable" ! Field Name !! Description |- -| encrypted_payment || AES-256-CBC encrypted, serialized BIP70 Payment message -|- -| payment_hash || SHA256 Hash of original non-encrypted, serialized Payment message. MUST be used for verification to prevent oracle attacks. +|message_type || Message Type of serialized_message (using enum ProtocolMessageType) |- -| sender_public_key || Sender's EC public key +|serialized_message || Serialized Payment Protocol Message |- -| receiver_public_key || Receiver's EC public key +|status_code || Payment Protocol Status Code |- -| nonce || The nonce in use for the CBC encryption +|status_message || Human-readable Payment Protocol status message |- -| signature || A signature of this message using Sender's EC key, serialized with a value of "" for signature. REQUIRED if server requires authentication. -|- -| identifier || Use the identifier specified with the EncryptedPaymentRequest, if any. +|identifier || Unique key to identify this entire exchange on the server. SHA256 of initial serialized InvoiceRequest SHOULD be used by default |} -===EncryptedPaymentACK=== - -An encrypted version of the BIP70 PaymentAck. - +===EncryptedProtocolMessage=== +The EncryptedProtocolMessage message is an encapsualting wrapper for any Payment Protocol message. It allows two-way, authenticated and encrypted communication of Payment Protocol messages in order to keep their contents secret. The message also includes a status code and status message that is used for error communication so the protocol does not rely on transport-layer error handling.
-message EncryptedPaymentACK {
-        required bytes  encrypted_payment_ack = 1;
-        required bytes  payment_ack_hash = 2;
-        required bytes  receiver_public_key = 3;
-        required bytes  sender_public_key = 4;
-        required uint64 nonce = 5;
-        required bytes  signature = 6;
-        optional bytes  identifier = 7;
+message EncryptedProtocolMessage {
+    required ProtocolMessageType message_type = 1;
+    required bytes encrypted_message = 2;
+    required bytes receiver_public_key = 3;
+    required bytes sender_public_key = 4;
+    required uint64 nonce = 5;
+    optional bytes signature = 6;
+    optional bytes identifier = 7;
+    optional uint64 status_code = 8;
+    optional string status_message = 9;
 }
 
{| class="wikitable" -! Field Name !! Description +! Field Name !! Description +| message_type || Message Type of Decrypted encrypted_message |- -| encrypted_payment_ack || AES-256-CBC encrypted, serialized BIP70 PaymentACK message +| encrypted_message || AES-256-GCM Encrypted (as defined in BIP75) Payment Protocol Message |- -| payment_ack_hash || SHA256 Hash of original non-encrypted, serialized Payment message. MUST be used for verification to prevent oracle attacks. +| receiver_public_key || Receiver's DER-encoded EC Public Key |- -| receiver_public_key || Receiver's EC public key +| sender_public_key || Sender's DER-encoded EC Public Key |- -| sender_public_key || Sender's EC public key +| nonce || Microseconds since epoch |- -| nonce || The nonce in use for the CBC encryption +| signature || DER-encoded Signature over the full EncryptedProtocolMessage with EC Key Belonging to Sender / Receiver, respectively |- -| signature || A signature of this message using Receiver's EC key, serialized with a value of "" for signature. REQUIRED if server requires authentication. +| identifier || Unique key to identify this entire exchange on the server. SHA256 of initial serialized InvoiceRequest SHOULD be used by default |- -| identifier || Use the identifier specified with the EncryptedPayment, if any. +| status_code || Payment Protocol Status Code +|- +| status_message || Human-readable Payment Protocol status message |} -==Updated Messages== -The BIP70 PaymentRequest, Payment and PaymentACK messages have been updated by this BIP to contain Payment Protocol error communication. The following two extension fields have been added to each of the aforementioned messages: +==Payment Protocol Process with InvoiceRequests== +The full process overview for using InvoiceRequests in the Payment Protocol is defined below. All Payment Protocol messages are to be encapsulated in either a ProtocolMessage or EncryptedProcotolMessage. Once the process begins using EncryptedProtocolMessage messages, all subsequent communications MUST use EncryptedProtocolMessages. All Payment Protocol messages SHOULD be communicated using EncryptedProtocolMessage encapsulating messages with the exception that an InvoiceRequest MAY be communicated using the ProtocolMessage if the receiver's public key is unknown. -
-{
-...
-    optional uint32 status_code = 1000;     // Payment Protocol status code
-    optional string status_message = 1001;  // Human-readable status message
-}
-
+See [[Sending_Encrypted_Payment_Protocol_Messages_using_EncryptedProtocolMessages|Sending Encrypted Payment Protocol Messages using EncryptedProtocolMessages]] and [[Validating_and_Decrypting_Payment_Protocol_Messages_using_EncryptedProtocolMessages|Validating and Decrypting Payment Protocol Messages using EncryptedProtocolMessages]] for the process of communicating using encrypted Payment Protocol messages. -status_code and/or status_message MUST be set to communicate a Payment Protocol error to the message receiver. The message consumer MUST handle status_code and status_message if either field is present. +TODO: See about adding some info about using ProtocolMessages -==InvoiceRequest / PaymentRequest Process== -The process overview for using InvoiceRequests and receiving encrypted PaymentRequests is defined below in two sections. Optionally, the Sender MAY choose to encrypt the InvoiceRequest message and therefore MUST follow the '''Encrypted InvoiceRequest Overview''' process below. - -===Non-Encrypted InvoiceRequest Overview=== # Sender creates InvoiceRequest -# Sender transmits InvoiceRequest to Receiver -# Receiver validates InvoiceRequest +# Sender encapsulates InvoiceRequest in (Encrypted)ProtocolMessage +# Sender sends (Encrypted)ProtocolMessage to Receiver +# Receiver retrieves InvoiceRequest from (Encrypted)ProtocolMessage # Receiver creates PaymentRequest -# Receiver encrypts the PaymentRequest -# Receiver creates EncryptedPaymentRequest (containing an encrypted PaymentRequest) -# Receiver transmits EncryptedPaymentRequest to Sender -# Sender validates EncryptedPaymentRequest -# Sender decrypts and validates encrypted PaymentRequest -# The PaymentRequest is processed according to BIP70, including optional Payment and PaymentACK messages - +# Receiver encapsulates PaymentRequest in EncryptedProtocolMessage +# Receiver transmits EncryptedProtocolMessage to Sender +# Sender validates PaymentRequest +# The PaymentRequest is processed according to BIP70, including optional Payment and PaymentACK messages encapsulated in EncryptedProtocolMessage messages. -Flow diagram of Non-Encrypted InvoiceRequest - -===Encrypted InvoiceRequest Overview=== -# Sender retrieves Receiver InvoiceRequest Public Key -# Sender creates InvoiceRequest -# Sender encrypts the InvoiceRequest -# Sender creates EncryptedInvoiceRequest (containing an encrypted InvoiceRequest) -# Sender transmits EncryptedInvoiceRequest to Receiver -# Receiver decrypts and validates EncryptedInvoiceRequest -# Receiver validates InvoiceRequest -# Receiver creates PaymentRequest -# Receiver encrypts the PaymentRequest -# Receiver creates EncryptedPaymentRequest (containing an encrypted PaymentRequest) -# Receiver transmits EncryptedPaymentRequest to Sender -# Sender validates EncryptedPaymentRequest -# Sender decrypts and validates encrypted PaymentRequest -# The PaymentRequest is processed according to BIP70, including optional EncryptedPayment and EncryptedPaymentACK messages - -'''NOTE:''' See section [[#Initial_Public_Key_Retrieval_for_InvoiceRequest_Encryption|Initial Public Key Retrieval for InvoiceRequest Encryption]] below for possible options to retrieve Receiver InvoiceRequest public keys. +'''NOTE:''' See section [[#Initial_Public_Key_Retrieval_for_InvoiceRequest_Encryption|Initial Public Key Retrieval for InvoiceRequest Encryption]] below for possible options to retrieve Receiver's public key. Flow diagram of Encrypted InvoiceRequest @@ -300,48 +207,44 @@ When communicated via HTTP, these messages MUST be transmitted via TLS-protected {| class="wikitable" ! Message Type !! Content Type |- -| InvoiceRequest || application/bitcoin-invoicerequest -|- -| EncryptedInvoiceRequest || application/bitcoin-encrypted-invoicerequest -|- -| EncryptedPaymentRequest || application/bitcoin-encrypted-paymentrequest +| ProtocolMessage || application/bitcoin-paymentprotocol-message |- -| EncryptedPayment || application/bitcoin-encrypted-payment -|- -| EncryptedPaymentACK || application/bitcoin-encrypted-paymentack +| EncryptedProtocolMessage || application/bitcoin-encrypted-paymentprotocol-message |} -===Payment Protocol Errors=== +===Payment Protocol Status Communication=== -Payment Protocol errors MUST be communicated to the party that initiated the communication via the status_code and status_message extension fields present in the PaymentRequest, Payment and PaymentACK messages. For example, if the provided hash of each message does not match the contents of the message once decrypted, a general error MUST be returned to prevent oracle attacks. +In the case of an error that causes the Payment Protocol process to be stopped or retried for a transaction, a ProtocolMessage or EncryptedProtocolMessage MUST be sent by the party generating the error. The content of the message must contain the same serialized_message or encrypted_message and identifier (if used) and MUST have the status_code set appropriately. The status_message value SHOULD be set with a human readable explanation of the status code. For example, if in an EncryptedProtocolMessage, the provided hash of the serialized message does not match the contents of the message once decrypted, a general error (100) MUST be returned to prevent oracle attacks. ====Payment Protocol Status Codes==== {| class="wikitable" ! Status Code !! Description +|- +| 1 || OK |- -| 1 || General / Unknown Error +| 100 || General / Unknown Error |- -| 2 || Authentication Failed +| 102 || Authentication Failed |- -| 3 || Encrypted Message Required +| 102 || Encrypted Message Required |- -| 100 || Amount Too High +| 200 || Amount Too High |- -| 101 || Amount Too Low +| 201 || Amount Too Low |- -| 102 || Amount Invalid +| 202 || Amount Invalid |- -| 103 || Payment Does Not Meet PaymentRequest Requirements +| 203 || Payment Does Not Meet PaymentRequest Requirements |- -| 200 || Certificate Required +| 300 || Certificate Required |- -| 201 || Certificate Expired +| 301 || Certificate Expired |- -| 202 || Certificate Invalid for Transaction +| 302 || Certificate Invalid for Transaction |- -| 203 || Certificate Revoked +| 303 || Certificate Revoked |- -| 204 || Certificate Not Well Rooted +| 304 || Certificate Not Well Rooted |- |} @@ -349,7 +252,8 @@ Payment Protocol errors MUST be communicated to the party that initiated the com Communications errors MUST be communicated to the party that initiated the communication via the communication layer's existing error messaging faciltiies. In the case of TLS-protected HTTP, this SHOULD be done through standard HTTP Status Code messaging ([https://tools.ietf.org/html/rfc7231 RFC 7231 Section 6]). -==Process Step Details== +==New Process Details== +This BIP extends the Payment Protocol as defined in BIP70. For the following we assume the Sender already knows the Receiver's public key, and the exchange is being facilitated by a Store & Forward server which requires valid signatures for authentication. @@ -358,7 +262,6 @@ Where used, '''nonce''' MUST be set to a non-repeating number AND MUST be chosen ===InvoiceRequest Message Creation=== * Create an InvoiceRequest message * sender_public_key MUST be set to the public key of an EC keypair -* nonce MUST be set according to the requirement above. * Amount is optional. If the amount is not specified by the InvoiceRequest, the Receiver MAY specify the amount in the returned PaymentRequest. If an amount is specified by the InvoiceRequest and a PaymentRequest cannot be generated for that amount, the InvoiceRequest SHOULD return a PaymentRequest with the status_code and status_message fields set appropriately. * Memo is optional. This MAY be set to a human readable description of the InvoiceRequest * Set notification_url to URL that the Receiver will submit completed EncryptedPaymentRequest to @@ -369,97 +272,57 @@ Where used, '''nonce''' MUST be set to a non-repeating number AND MUST be chosen ** Sign InvoiceRequest with signature = "" using the X509 Certificate's private key ** Set signature value to the computed signature -===EncryptedInvoiceRequest Message Creation=== -* Create an EncryptedInvoiceRequest -* Retrieve endpoint public key to use in '''ECDH Point Generation''' as specified in [[#Initial_Public_Key_Retrieval_for_InvoiceRequest_Encryption|Initial Public Key Retrieval for InvoiceRequest Encryption]] (see below) -* sender_public_key MUST be set to the public key of the Sender's EC keypair -* receiver_public_key MUST be set to the public key of the Receiver's EC keypair -* invoice_request_hash MUST be set to the SHA256 hash of the serialized InvoiceRequest (without encryption) -* Encrypt the serialized InvoiceRequest using AES-256-CBC setup as described in [[#ECDH_Point_Generation_and_AES256_CBC_Mode_Setup|ECDH Point Generation and AES-256 (CBC Mode) Setup]] (see below) -* encrypted_invoice_Request MUST be set to the encrypted values of the InvoiceRequest -* nonce MUST be set to the nonce used in the AES-256-CBC encryption operation -* Set identifier to invoice_request_hash - ===InvoiceRequest Validation=== -* Validate sender_public_key is a valid EC public key -* The nonce MUST not be repeated. The service receiving the InvoiceRequest MAY use whatever method to make sure that the nonce is never repeated. +* 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 -===EncryptedPaymentRequest Message Creation and PaymentRequest Encryption=== -* Encrypt the serialized PaymentRequest using AES-256-CBC setup as described in [[#ECDH_Point_Generation_and_AES256_CBC_Mode_Setup|ECDH Point Generation and AES-256 (CBC Mode) Setup]] (see below) -* Create EncryptedPaymentRequest message -* Set encrypted_payment_request to be the encrypted value of the PaymentRequest -* Set payment_request_hash to generated SHA256 hash of the serialized PaymentRequest (without encryption) +===Sending Encrypted Payment Protocol Messages using EncryptedProtocolMessages=== +* Encrypt the serialized Payment Protocol message using AES-256-CBC setup as described in [[#ECDH_Point_Generation_and_AES256_GCM_Mode_Setup|ECDH Point Generation and AES-256 (GCM Mode) Setup]] (see below) +* Create EncryptedProtocolMessage message +* Set encrypted_message to be the encrypted value of the Payment Protocol message * sender_public_key MUST be set to the public key of the Sender's EC keypair * receiver_public_key MUST be set to the public key of the Receiver's EC keypair * nonce MUST be set to the nonce used in the AES-256-CBC encryption operation -* requires_payment_message MAY be set to true if the PaymentRequest requires a Payment message -* Set identifier to the value received in EncryptedInvoiceRequest +* requires_payment_message MAY be set to true if the PaymentRequest requires a Payment message '''TODO: How are we doing this now?''' +* Set identifier to the identifier value received in the originating InvoiceRequest's ProtocolMessage or EncryptedProtocolMessage wrapper message * Set signature to "" -* Sign the serialized EncryptedPayment message with the Receiver's EC public key +* Sign the serialized EncryptedProtocolMessage message with the communicating party's EC public key * Set signature to the result of the signature operation above -===EncryptedPaymentRequest Validation and Decryption=== -* Decrypt the serialized PaymentRequest using AES-256-CBC setup as described in [[#ECDH_Point_Generation_and_AES256_CBC_Mode_Setup|ECDH Point Generation and AES-256 (CBC Mode) Setup]] (see below) -* Validate payment_request_hash matches SHA256 of the decrypted, serialized PaymentRequest -* Deserialize the serialized PaymentRequest +'''SIGNATURE NOTE:''' EncryptedProtocolMessage messages are signed with the public keys of the party transmitting the message. This allows a Store & Forward server or other transmission system to prevent spam or other abuses. For those who are privacy conscious and don't want the server to track the interactions between two public keys, the Sender can generate a new public key for each interaction to keep their identity anonymous. + +===Validating and Decrypting Payment Protocol Messages using EncryptedProtocolMessages=== +* The nonce MUST not be repeated. The service receiving the InvoiceRequest MAY use whatever method to make sure that the nonce is never repeated. +* Decrypt the serialized Payment Protocol message using AES-256-GCM setup as described in [[#ECDH_Point_Generation_and_AES256_GCM_Mode_Setup|ECDH Point Generation and AES-256 (GCM Mode) Setup]] (see below) +* Deserialize the serialized Payment Protocol message -===ECDH Point Generation and AES-256 (CBC Mode) Setup=== +===ECDH Point Generation and AES-256 (GCM Mode) Setup=== +'''NOTE''': AES-256-GCM is used because it provides authenticated encryption facilities, thus negating the need for a separate message hash for authentication. * 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 '''SHA256(secret point's X value)''' for Entropy ** Use the given message's nonce field for Nonce -* Initialize AES-256 in CBC Mode +* Initialize AES-256 in GCM Mode ** Use HMAC_DRBG.GENERATE(32) as the Encryption Key (256 bits) ** Use HMAC_DRBG.GENERATE(16) as the Initialization Vector (IV) (128 bits) ===Initial Public Key Retrieval for InvoiceRequest Encryption=== -Initial public key retrieval for InvoiceRequest encryption can be done in a number of ways including, but not limited to, the following: +Initial public key retrieval for InvoiceRequest encryption in EncryptedProtocolMessage can be done in a number of ways including, but not limited to, the following: * Wallet Name public key asset type resolution - DNSSEC-validated name resolution returns Base64 encoded DER-formatted EC public key via TXT Record [https://www.ietf.org/rfc/rfc5480.txt RFC 5480] * Key Server lookup - Key Server lookup (similar to PGP's pgp.mit.edu) based on key server identifier (i.e., e-mail address) returns Base64 encoded DER-formatted EC public key [https://www.ietf.org/rfc/rfc5480.txt RFC 5480] * QR Code - Use of QR-code to encode DER-formatted EC public key [https://www.ietf.org/rfc/rfc5480.txt RFC 5480] - -==EncryptedPayment and EncryptedPaymentACK Details== - -===EncryptedPayment Message Creation=== -* Encrypt the serialized Payment using AES-256-CBC using secret key calculated in the [[#EncryptedPaymentRequest_Message_Creation_and_PaymentRequest_Encryption|EncryptedPaymentRequest Message Creation and PaymentRequest Encryption]] step (see above) -* Create EncryptedPayment message -* Set encrypted_payment to be the encrypted value of the Payment -* Set payment_hash to generated SHA256 hash of the serialized Payment (without encryption) -* sender_public_key MUST be set to the public key of the Sender's EC keypair -* receiver_public_key MUST be set to the public key of the Receiver's EC keypair -* nonce MUST be set to the nonce used in the AES-256-CBC encryption operation -* Set identifier to the value received in EncryptedPaymentRequest -* Set signature to "" -* Sign the serialized EncryptedPayment message with the Sender's EC public key -* Set signature to the result of the signature operation above - -===EncryptedPaymentACK Message Creation=== -* Encrypt the serialized PaymentACK using AES-256-CBC using secret key calculated in the [[#EncryptedPaymentRequest_Message_Creation_and_PaymentRequest_Encryption|EncryptedPaymentRequest Message Creation and PaymentRequest Encryption]] step (see above) -* Create EncryptedPaymentACK message -* Set encrypted_payment_ack to be the encrypted value of the PaymentACK -* Set payment_ack_hash to generated SHA256 hash of the serialized PaymentACK (without encryption) -* sender_public_key MUST be set to the public key of the Sender's EC keypair -* receiver_public_key MUST be set to the public key of the Receiver's EC keypair -* nonce MUST be set to the nonce used in the AES-256-CBC encryption operation -* Set identifier to the value received in EncryptedPaymentRequest -* Set signature to "" -* Sign the serialized EncryptedPaymentACK message with the Receiver's EC public key -* Set signature to the result of the signature operation above - - -'''SIGNATURE NOTE:''' EncryptedPaymentRequest, EncryptedPayment, and EncryptedPaymentACK messages are signed with the public keys of the party transmitting the message. This allows a Store & Forward server or other transmission system to prevent spam or other abuses. For those who are privacy conscious and don't want the server to track the interactions between two public keys, the Sender can generate a new public key for each interaction to keep their identity anonymous. +* Address Service Public Key Exposure ==Payment / PaymentACK Messages with a Store & Forward Server== -When a Store & Forward server is in use during the Payment Protocol exchange, an EncryptedPayment message generated as the result of a EncryptedPaymentRequest with the requires_payment_message flag set to true MUST be accepted by a Store & Forward server. The accepted Payment message is NOT validated as the Store & Forward server does not have access to encrypted data. +When a Store & Forward server is in use during the Payment Protocol exchange, a Payment message generated as the result of a PaymentRequest with the '''requires_payment_message''' (TODO: Should add something more generic to the encapsulating messages?) flag set to true MUST be accepted by a Store & Forward server. The accepted Payment message is NOT validated as the Store & Forward server does not have access to encrypted data. -Store & Forward servers MAY accept and/or overwrite EncryptedPayment messages until an EncryptedPaymentACK message with matching identifier and valid Receiver signature is received, after which the server MAY reject all further EncryptedPayment messages matching that identifier. This feature SHOULD be used for updating Payment metadata or replacing invalid transactions with valid ones. Clients SHOULD keep in mind Receivers can broadcast a transaction without returning an ACK. If a payment message needs to be updated, it SHOULD include at least one input referenced in the original transaction to prevent the Receiver from broadcasting both transactions and getting paid twice. +Store & Forward servers MAY accept and/or overwrite Payment messages until an PaymentACK message with matching identifier and valid Receiver signature is received, after which the server MAY reject all further Payment messages matching that identifier. This feature SHOULD be used for updating Payment metadata or replacing invalid transactions with valid ones. Clients SHOULD keep in mind Receivers can broadcast a transaction without returning an ACK. If a payment message needs to be updated, it SHOULD include at least one input referenced in the original transaction to prevent the Receiver from broadcasting both transactions and getting paid twice. ==Public Key & Signature Encoding== -* Each EC public key (sender_public_key, receiver_public_key) included in any message defined in this BIP MUST be DER [ITU.X690.1994] encoded. -* Each ECC signature included in any message defined in this BIP MUST use the SHA-256 hashing algorithm and MUST be DER [ITU.X690.1994] encoded. +* All EC public keys (sender_public_key, receiver_public_key) included in any message defined in this BIP MUST be DER [ITU.X690.1994] encoded. +* All ECC signatures included in any message defined in this BIP MUST use the SHA-256 hashing algorithm and MUST be DER [ITU.X690.1994] encoded. ==Implementation== A reference implementation for a Store & Forward server supporting this proposal can be found here: @@ -468,7 +331,7 @@ A reference implementation for a Store & Forward server supporting this proposal A reference client implementation can be found in the InvoiceRequest functional testing for Addressimo here: -[https://github.com/netkicorp/addressimo/blob/master/functest/functest_ir.py InvoiceRequest Client Reference Implementation] +[https://github.com/netkicorp/addressimo/blob/master/functest/functest_bip75.py BIP75 Client Reference Implementation] ==BIP70 Extension== The following flowchart is borrowed from BIP70 and expanded upon in order to visually describe how this BIP is an extension to BIP70. diff --git a/bip-0075/paymentrequest.proto b/bip-0075/paymentrequest.proto index 912fcd3..3c1ef40 100644 --- a/bip-0075/paymentrequest.proto +++ b/bip-0075/paymentrequest.proto @@ -23,9 +23,6 @@ message PaymentDetails { optional string memo = 5; // Human-readable description of request for the customer optional string payment_url = 6; // URL to send Payment and get PaymentACK optional bytes merchant_data = 7; // Arbitrary data to include in the Payment message - optional uint64 subtractable_fee = 1000; // How many Satoshis can be subtracted from the requested amount and instead applied towards the fee - optional uint64 fee_per_kb = 1001; // Minimum transaction fee that must be included with the transaction in order for it to be accepted with zero confirmations. - optional bool replace_by_fee = 1002; // Indicates the sender can enable the Replace By Fee flag for this transaction and the receiver will still consider it accepted with zero confirmations. Otherwise, RBF transactions will not be accepted by the receiver until they are confirmed. } message PaymentRequest { optional uint32 payment_details_version = 1 [default = 1]; @@ -33,8 +30,6 @@ message PaymentRequest { optional bytes pki_data = 3; // depends on pki_type required bytes serialized_payment_details = 4; // PaymentDetails optional bytes signature = 5; // pki-dependent signature - optional uint32 status_code = 1000; // Payment Protocol status code - optional string status_message = 1001; // Human-readable Payment Protocol status message } message X509Certificates { repeated bytes certificate = 1; // DER-encoded X.509 certificate chain @@ -44,20 +39,15 @@ message Payment { repeated bytes transactions = 2; // Signed transactions that satisfy PaymentDetails.outputs repeated Output refund_to = 3; // Where to send refunds, if a refund is necessary optional string memo = 4; // Human-readable message for the merchant - optional uint32 status_code = 1000; // Payment Protocol status code - optional string status_message = 1001; // Human-readable Payment Protocol status message } message PaymentACK { required Payment payment = 1; // Payment message that triggered this ACK optional string memo = 2; // Human-readable message for customer - optional uint32 status_code = 1000; // Payment Protocol status code - optional string status_message = 1001; // Human-readable Payment Protocol status message } // BIP-IR Extensions - message InvoiceRequest { - required bytes sender_public_key = 1; // Sender's EC Public Key + required bytes sender_public_key = 1; // Sender's DER-Encoded EC Public Key optional uint64 amount = 3 [default = 0]; // amount is integer-number-of-satoshis optional string pki_type = 4 [default = "none"]; // none / x509+sha256 optional bytes pki_data = 5; // Depends on pki_type @@ -66,43 +56,29 @@ message InvoiceRequest { optional bytes signature = 8; // PKI-dependent signature } -message EncryptedInvoiceRequest { - required bytes encrypted_invoice_request = 1; // AES-256-CBC Encrypted InvoiceRequest as defined in InvoiceRequest Spec - required bytes invoice_request_hash = 2; // SHA256 Hash of Non-Encrypted, Serialized InvoiceRequest (used for authentication) - required bytes sender_public_key = 3; // Sender's EC Public Key - required bytes receiver_public_key = 4; // Receiver's EC Public Key - required uint64 nonce = 5; // Microseconds since epoch - optional bytes identifier = 6; // Unique key to identify this entire exchange on the server. invoice_request_hash SHOULD be used by default - optional bytes signature = 7; // Signature of this message using Sender's EC key -} - -message EncryptedPaymentRequest { - required bytes encrypted_payment_request = 1; // AES-256-CBC Encrypted PaymentRequest as defined in InvoiceRequest Spec - required bytes payment_request_hash = 2; // SHA256 Hash of Non-Encrypted, Serialized PaymentRequest (used for authentication) - required bytes receiver_public_key = 3; // Receiver's EC Public Key - required bytes sender_public_key = 4; // Sender's EC Public Key - required uint64 nonce = 5; // Microseconds since epoch - optional bool requires_payment_message = 6 [default = false]; // Requires Payment/PaymentACK message exchange - optional bytes signature = 7; // Signature of this message using Receiver's EC key - optional bytes identifier = 8; // MUST use the identifier specified with the InvoiceRequest if the PaymentRequest is in response to an InvoiceRequest. Otherwise, use payment_request_hash or other unique value. +enum ProtocolMessageType { + INVOICE_REQUEST = 0; + PAYMENT_REQUEST = 1; + PAYMENT = 2; + PAYMENT_ACK = 3; } -message EncryptedPayment { - required bytes encrypted_payment = 1; // AES-256-CBC Encrypted BIP70 Payment as defined in InvoiceRequest Spec - required bytes payment_hash = 2; // SHA256 Hash of Non-Encrypted, Serialized BIP70 Payment - required bytes sender_public_key = 3; // Sender's EC Public Key - required bytes receiver_public_key = 4; // Receiver's EC Public Key - required uint64 nonce = 5; // Microseconds since epoch - required bytes signature = 6; // Signature over EncryptedPayment with Sender's EC Key - optional bytes identifier = 7; // Use the identifier specified with the EncryptedPaymentRequest, if any. +message ProtocolMessage { + required ProtocolMessageType message_type = 1; // Message Type of serialized_message + required bytes serialized_message = 2; // Serialized Payment Protocol Message + optional uint64 status_code = 3; // Payment Protocol Status Code + optional string status_message = 4; // Human-readable Payment Protocol status message + optional bytes identifier = 5; // Unique key to identify this entire exchange on the server. SHA256 of initial serialized InvoiceRequest SHOULD be used by default } -message EncryptedPaymentACK { - required bytes encrypted_payment_ack = 1; // AES-256-CBC Encrypted BIP70 PaymentACK as defined in InvoiceRequest Spec - required bytes payment_ack_hash = 2; // SHA256 Hash of Non-Encrypted, Serialized BIP70 PaymentACK - required bytes receiver_public_key = 3; // Receiver's EC Public Key - required bytes sender_public_key = 4; // Sender's EC Public Key - required uint64 nonce = 5; // Microseconds since epoch - required bytes signature = 6; // Signature over EncryptedPaymentACK with Receiver's EC Key - optional bytes identifier = 7; // Use the identifier specified with the EncryptedPaymentRequest, if any. -} +message EncryptedProtocolMessage { + required ProtocolMessageType message_type = 1; // Message Type of Decrypted encrypted_message + required bytes encrypted_message = 2; // AES-256-GCM Encrypted (as defined in BIP75) Payment Protocol Message + required bytes receiver_public_key = 3; // Receiver's DER-encoded EC Public Key + required bytes sender_public_key = 4; // Sender's DER-encoded EC Public Key + required uint64 nonce = 5; // Microseconds since epoch + optional bytes signature = 6; // Signature over the full EncryptedProtocolMessage with EC Key Belonging to Sender / Receiver, respectively + optional bytes identifier = 7; // Unique key to identify this entire exchange on the server. SHA256 of initial serialized InvoiceRequest SHOULD be used by default + optional uint64 status_code = 8; // Payment Protocol Status Code + optional string status_message = 9; // Human-readable Payment Protocol status message +} \ No newline at end of file -- cgit v1.2.3