1
0
mirror of https://github.com/bitcoin/bips.git synced 2025-05-12 12:03:29 +00:00

- Make message public key sharing mandatory for messages that are encrypted and where both keys are known. For EncryptedInvoiceRequest, only the sender_public_key is required

- Add nonce to EncryptedPaymentRequest, EncryptedPayment and EncryptedPaymentACK
- Update ECDH instruction to allow for the current message instead of an InvoiceRequest to contain the nonce
- Updated paymentrequest.proto with BIP definition changes
This commit is contained in:
Matt David 2016-02-22 12:04:54 -08:00
parent 6a08dae8c4
commit 10e6f46569
2 changed files with 92 additions and 41 deletions

View File

@ -145,13 +145,15 @@ message EncryptedInvoiceRequest {
|- |-
| sender_public_key || Sender's EC public key | sender_public_key || Sender's EC public key
|- |-
| receiver_public_key || Receiver's EC public key, can be omitted if this message is sent directly to the recipient, or is sent to a Store & Forward server that already understands who the recipient should be (if specified by URI endpoint, for example) | receiver_public_key || Receiver's EC public key
|- |-
| nonce || The nonce in use for the CBC encryption | nonce || The nonce in use for the CBC encryption
|- |-
| identifier || A unique key to identify this entire exchange on the server. By default, invoice_request_hash SHOULD be used. | identifier || A unique key to identify this entire exchange on the server. invoice_request_hash SHOULD be used by default.
|} |}
receiver_public_key MAY be omitted if this message is sent directly to the Receiver. receiver_public_key MAY also be omitted if the EncryptedInvoiceRequest is being sent to a Store & Forward server which already understands who the Receiver is. An example of this is a Store & Forward server URL that uniquely identifies the Receiver (and their public key).
===EncryptedPaymentRequest=== ===EncryptedPaymentRequest===
The EncryptedPaymentRequest message is an encapsulating message that allows the transmission of an encrypted, serialized PaymentRequest. The EncryptedPaymentRequest message is an encapsulating message that allows the transmission of an encrypted, serialized PaymentRequest.
@ -160,12 +162,12 @@ The EncryptedPaymentRequest message is an encapsulating message that allows the
message EncryptedPaymentRequest { message EncryptedPaymentRequest {
required bytes encrypted_payment_request = 1; required bytes encrypted_payment_request = 1;
required bytes payment_request_hash = 2; required bytes payment_request_hash = 2;
optional bytes receiver_public_key = 3; required bytes receiver_public_key = 3;
optional bytes sender_public_key = 4; required bytes sender_public_key = 4;
optional uint64 nonce = 5; required uint64 nonce = 5;
optional bool requires_payment_message = 6; optional bool requires_payment_message = 6;
optional bytes signature = 7; optional bytes signature = 7;
optional bytes identifier = 6; optional bytes identifier = 8;
} }
</pre> </pre>
{| class="wikitable" {| class="wikitable"
@ -175,17 +177,17 @@ message EncryptedPaymentRequest {
|- |-
| payment_request_hash || SHA256 Hash of non-encrypted, serialized PaymentRequest. MUST be used for verification to prevent oracle attacks. | 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, only necessary if not already shared or known (for example, if this message is not in response to an InvoiceRequest) | receiver_public_key || Receiver's EC public key
|- |-
| sender_public_key || Sender's EC public key, can be omitted if this message is sent directly to the recipient, or is sent to a Store & Forward server that already understands who the recipient should be (if specified by URI endpoint, for example) | sender_public_key || Sender's EC public key
|- |-
| nonce || The nonce in use for the CBC encryption, only necessary if not already shared (for example, if this message is not in response to an InvoiceRequest) | nonce || The nonce in use for the CBC encryption
|- |-
| requires_payment_message || Internal PaymentRequest requires follow-up Payment message | 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. Only necessary if required by the server to authenticate a reply to an InvoiceRequest. | signature || A signature of this message using Receiver's EC key, serialized with a value of "" for signature. REQUIRED if server requires InvoiceRequest reply authentication.
|- |-
| identifier || If the PaymentRequest is in response to an InvoiceRequest, use the identifier specified with the InvoiceRequest, if any. Otherwise, use payment_request_hash or other unique value. | 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=== ===EncryptedPayment===
@ -196,8 +198,11 @@ The EncryptedPayment message allows a BIP70 Payment message to be transmitted th
message EncryptedPayment { message EncryptedPayment {
required bytes encrypted_payment = 1; required bytes encrypted_payment = 1;
required bytes payment_hash = 2; required bytes payment_hash = 2;
required bytes signature = 3; required bytes receiver_public_key = 3;
optional bytes identifier = 4; required bytes sender_public_key = 4;
required uint64 nonce = 5;
required bytes signature = 6;
optional bytes identifier = 7;
} }
</pre> </pre>
{| class="wikitable" {| class="wikitable"
@ -207,6 +212,12 @@ message EncryptedPayment {
|- |-
| payment_hash || SHA256 Hash of original non-encrypted, serialized Payment message. MUST be used for verification to prevent oracle attacks. | payment_hash || SHA256 Hash of original non-encrypted, serialized Payment message. 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
|-
| signature || A signature of this message using Sender's EC key, serialized with a value of "" for signature. | signature || A signature of this message using Sender's EC key, serialized with a value of "" for signature.
|- |-
| identifier || Use the identifier specified with the EncryptedPaymentRequest, if any. | identifier || Use the identifier specified with the EncryptedPaymentRequest, if any.
@ -220,8 +231,11 @@ An encrypted version of the BIP70 PaymentAck.
message EncryptedPaymentACK { message EncryptedPaymentACK {
required bytes encrypted_payment_ack = 1; required bytes encrypted_payment_ack = 1;
required bytes payment_ack_hash = 2; required bytes payment_ack_hash = 2;
required bytes signature = 3; required bytes receiver_public_key = 3;
optional bytes identifier = 4; required bytes sender_public_key = 4;
required uint64 nonce = 5;
required bytes signature = 6;
optional bytes identifier = 7;
} }
</pre> </pre>
{| class="wikitable" {| class="wikitable"
@ -231,6 +245,12 @@ message EncryptedPaymentACK {
|- |-
| payment_ack_hash || SHA256 Hash of original non-encrypted, serialized Payment message. MUST be used for verification to prevent oracle attacks. | 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 EC public key
|-
| sender_public_key || Sender's EC public key
|-
| nonce || The nonce in use for the CBC encryption
|-
| signature || A signature of this message using Receiver's EC key, serialized with a value of "" for signature. | signature || A signature of this message using Receiver's EC key, serialized with a value of "" for signature.
|- |-
| identifier || Use the identifier specified with the EncryptedPayment, if any. | identifier || Use the identifier specified with the EncryptedPayment, if any.
@ -301,10 +321,12 @@ SHOULD be done through standard HTTP Status Code messaging ([https://tools.ietf.
For the following we assume the Sender already knows the Receiver's public key, and the exchange starts with an EncryptedInvoiceRequest. For the following we assume the Sender already knows the Receiver's public key, and the exchange starts with an EncryptedInvoiceRequest.
Where used, **nonce** MUST be set to a non-repeating number. The current epoch time in microseconds SHOULD be used, unless the creating device doesn't have access to a RTC (in the case of a smart card, for example). The service receiving the message containing the **nonce** MAY use whatever method to make sure that the **nonce** is never repeated.
===InvoiceRequest Message Creation=== ===InvoiceRequest Message Creation===
* Create an InvoiceRequest message * Create an InvoiceRequest message
* sender_public_key MUST be set to the public key of an EC keypair * sender_public_key MUST be set to the public key of an EC keypair
* nonce MUST be set to a non-repeating number. The current epoch time in microseconds SHOULD be used, unless the creating device doesn't have access to a RTC (in the case of a smart card, for example) * 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 be rejected with HTTP status code 406. * 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 be rejected with HTTP status code 406.
* Memo is optional. This MAY be set to a human readable description of the InvoiceRequest * 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 * Set notification_url to URL that the Receiver will submit completed EncryptedPaymentRequest to
@ -318,10 +340,12 @@ For the following we assume the Sender already knows the Receiver's public key,
===EncryptedInvoiceRequest Message Creation=== ===EncryptedInvoiceRequest Message Creation===
* Create an EncryptedInvoiceRequest * Create an EncryptedInvoiceRequest
* Retrieve endpoint public key to use in <b>ECDH Point Generation</b> as specified in <b>Initial Public Key Retrieval for InvoiceRequest Encryption</b> (see below) * Retrieve endpoint public key to use in <b>ECDH Point Generation</b> as specified in <b>Initial Public Key Retrieval for InvoiceRequest Encryption</b> (see below)
* sender_public_key MUST be set to the public key of an EC keypair * sender_public_key MUST be set to the public key of the Sender's EC keypair
* receiver_public_key MAY 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) * 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 <b>ECDH Point Generation and AES-256 (CBC Mode) Setup (see below)</b> * Encrypt the serialized InvoiceRequest using AES-256-CBC setup as described in <b>ECDH Point Generation and AES-256 (CBC Mode) Setup (see below)</b>
* encrypted_invoice_Request MUST be set to the encrypted values of the InvoiceRequest * 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 * Set identifier to invoice_request_hash
===InvoiceRequest Validation=== ===InvoiceRequest Validation===
@ -336,9 +360,14 @@ For the following we assume the Sender already knows the Receiver's public key,
* Create EncryptedPaymentRequest message * Create EncryptedPaymentRequest message
* Set encrypted_payment_request to be the encrypted value of the PaymentRequest * 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) * Set payment_request_hash to generated SHA256 hash of the serialized PaymentRequest (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
* requires_payment_message MAY be set to true if the PaymentRequest requires a Payment message
* Set identifier to the value received in EncryptedInvoiceRequest * Set identifier to the value received in EncryptedInvoiceRequest
* Set signature to "" * Set signature to ""
* Sign the serialized EncryptedPayment message with the Receiver's EC public key * Sign the serialized EncryptedPayment message with the Receiver's EC public key
* Set signature to the result of the signature operation above
===EncryptedPaymentRequest Validation and Decryption=== ===EncryptedPaymentRequest Validation and Decryption===
* 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> * 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>
@ -349,7 +378,7 @@ For the following we assume the Sender already knows the Receiver's public key,
* Generate the '''secret point''' using [https://en.wikipedia.org/wiki/Elliptic_curve_DiffieHellman ECDH] using the local entity's private key and the remote entity's public key as inputs. * Generate the '''secret point''' using [https://en.wikipedia.org/wiki/Elliptic_curve_DiffieHellman 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] * Initialize [http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf HMAC_DRBG]
** Use '''secret point's''' X value for Entropy ** Use '''secret point's''' X value for Entropy
** Use the given InvoiceRequest's nonce field for Nonce ** Use the given message's nonce field for Nonce
* Initialize AES-256 in CBC Mode * Initialize AES-256 in CBC Mode
** Use HMAC_DRBG.GENERATE(32) as the Encryption Key (256 bits) ** Use HMAC_DRBG.GENERATE(32) as the Encryption Key (256 bits)
** Use HMAC_DRBG.GENERATE(16) as the Initialization Vector (IV) (128 bits) ** Use HMAC_DRBG.GENERATE(16) as the Initialization Vector (IV) (128 bits)
@ -366,8 +395,11 @@ Initial public key retrieval for InvoiceRequest encryption can be done in a numb
* Encrypt the serialized Payment using AES-256-CBC using secret key calculated in the <b>EncryptedPaymentRequest Message Creation and PaymentRequest Encryption</b> step (see above) * Encrypt the serialized Payment using AES-256-CBC using secret key calculated in the <b>EncryptedPaymentRequest Message Creation and PaymentRequest Encryption</b> step (see above)
* Create EncryptedPayment message * Create EncryptedPayment message
* Set encrypted_payment to be the encrypted value of the Payment * Set encrypted_payment to be the encrypted value of the Payment
* Set identifier to the value received in EncryptedPaymentRequest
* Set payment_hash to generated SHA256 hash of the serialized Payment (without encryption) * 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 "" * Set signature to ""
* Sign the serialized EncryptedPayment message with the Sender's EC public key * Sign the serialized EncryptedPayment message with the Sender's EC public key
* Set signature to the result of the signature operation above * Set signature to the result of the signature operation above
@ -377,6 +409,10 @@ Initial public key retrieval for InvoiceRequest encryption can be done in a numb
* Create EncryptedPaymentACK message * Create EncryptedPaymentACK message
* Set encrypted_payment_ack to be the encrypted value of the PaymentACK * 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) * 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 "" * Set signature to ""
* Sign the serialized EncryptedPaymentACK message with the Receiver's EC public key * Sign the serialized EncryptedPaymentACK message with the Receiver's EC public key
* Set signature to the result of the signature operation above * Set signature to the result of the signature operation above

View File

@ -46,11 +46,6 @@ message PaymentACK {
} }
// BIP-IR Extensions // BIP-IR Extensions
message EncryptedInvoiceRequest {
required bytes encrypted_invoice_request = 1; // AES-256-CBC Encrypted InvoiceRequest as defined in InvoiceRequest Spec
required bytes sender_public_key = 2; // Sender's EC Public Key
required bytes invoice_request_hash = 3; // SHA256 Hash of Non-Encrypted, Serialized InvoiceRequest (used for authentication)
}
message InvoiceRequest { message InvoiceRequest {
required bytes sender_public_key = 1; // Sender's EC Public Key required bytes sender_public_key = 1; // Sender's EC Public Key
@ -63,22 +58,42 @@ message InvoiceRequest {
optional bytes signature = 8; // PKI-dependent signature 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
optional 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
}
message EncryptedPaymentRequest { message EncryptedPaymentRequest {
required bytes encrypted_payment_request = 1; // AES-256-CBC Encrypted PaymentRequest as defined in InvoiceRequest Spec required bytes encrypted_payment_request = 1; // AES-256-CBC Encrypted PaymentRequest as defined in InvoiceRequest Spec
required bytes receiver_public_key = 2; // Receiver's EC Public Key required bytes payment_request_hash = 2; // SHA256 Hash of Non-Encrypted, Serialized PaymentRequest (used for authentication)
required bytes ephemeral_public_key = 3; // Public Key of ECDH-derived keypair required bytes receiver_public_key = 3; // Receiver's EC Public Key
required bytes payment_request_hash = 4; // SHA256 Hash of Non-Encrypted, Serialized PaymentRequest (used for authentication) required bytes sender_public_key = 4; // Sender's EC Public Key
required bool requires_payment_message = 5 [default = false]; // Requires Payment/PaymentACK message exchange 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.
} }
message EncryptedPayment { message EncryptedPayment {
required bytes encrypted_payment = 1; // AES-256-CBC Encrypted Payment as defined in InvoiceRequest Spec required bytes encrypted_payment = 1; // AES-256-CBC Encrypted BIP70 Payment as defined in InvoiceRequest Spec
required bytes payment_request_hash = 2; // SHA256 Hash of Non-Encrypted, Serialized PaymentRequest returned in the transaction's EncryptedPaymentRequest message required bytes payment_hash = 2; // SHA256 Hash of Non-Encrypted, Serialized BIP70 Payment
required bytes signature = 3; // Signature over EncryptedPayment with original Sender's EC Private Key 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 EncryptedPayment with Sender's EC Key
optional bytes identifier = 7; // Use the identifier specified with the EncryptedPaymentRequest, if any.
} }
message EncryptedPaymentACK { message EncryptedPaymentACK {
required bytes encrypted_payment_ack = 1; // AES-256-CBC Encrypted Payment as defined in InvoiceRequest Spec required bytes encrypted_payment_ack = 1; // AES-256-CBC Encrypted BIP70 PaymentACK as defined in InvoiceRequest Spec
required bytes payment_request_hash = 2; // SHA256 Hash of Non-Encrypted, Serialized PaymentRequest returned in the transaction's EncryptedPaymentRequest message required bytes payment_ack_hash = 2; // SHA256 Hash of Non-Encrypted, Serialized BIP70 PaymentACK
required bytes signature = 3; // Signature over EncryptedPaymentACK with the Receiver's EC Private key. 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.
} }