-
Notifications
You must be signed in to change notification settings - Fork 15
encrypted_card
This document describes a proposal for a payment handler that behaves like basic card, but provides additional security, by ensuring that the card information is not transmitted in the clear to the merchant.
This reduces PCI scope for the merchant, especially v3+
We'd like to consider this colloquially as "BasicCard++". In that sense, there are a few things that a similar to BasicCard
and a few differences.
Similarities:
- Form Fills are used to populate payment instruments
- Payment Request invocation is similar
Differences:
- The PAN is encrypted following an exchange with a vault provider
- The returned value from the
PaymentRequest
API does not contain the PAN, but contains an opaque blob - The returned blob can only be used to process the transaction with the vault provider that created it
- Additional constraints may be put by the vault provider on the blob (could be a nonce, time bounded, or permanent)
The payment handler can be specified using the same syntax as BasicCard
with a notable difference: a vault provider will be specified.
This parameter will be provided in addition to those specified in basic-card
:
dictionary EncryptedCardRequest {
sequence<DOMString> supportedNetworks; // Defined in Basic Card
sequence<CardType> supportedTypes; // Defined in Basic Card
required DOMString encryptionProviderURL;
};
The Javascript would look as follows:
var supportedInstruments = [
{
supportedMethods: ['encrypted-card']
data: {
supportedNetworks: ['amex', 'discover', 'mastercard', 'visa'],
supportedTypes: ['credit', 'debit'],
encryptionProviderURL: 'https://www.bobpay.com/encrypted-cards'
}
},
...,
];
var payment = new PaymentRequest(
supportedInstruments,
details,
options
);
The exact same data contained in the BasicCardResponse
dictionary, is encrypted.
dictionary EncryptedCardResponse {
required DOMString cardNumber;
DOMString cardholderName;
DOMString cardSecurityCode;
DOMString expiryMonth;
DOMString expiryYear;
PaymentAddress? billingAddress;
};
The (asymmetric) encryption can occur in one of two ways:
- through the origin's SSL public key if a manifest is not found or the parameter is not found in the manifest
- through a Web App Manifest parameter, specifying a public key and list of ciphers
There's an inherent advantage to using 1. because if there has already been a cipher exchange, the public key is potentially in the Browser's cache, and the result of the TLS handshaking will have selected a cipher suite for the key exchange. The same cipher suite can be used to encrypt the card data.
The card data is then encrypted and represented as a base64-encoded string.
This data is returned as part of the PaymentResponse
as follows:
dictionary EncryptedCardResponse {
DOMString cardholderName; // data from BasicCardResponse
optional DOMString suffix; // Last four digits of card number
required DOMString encryptedCardData; // base64-encoded string
};