-
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 vaultProviderURL;
optional boolean tokenized; // option to tokenize card
};
The Javascript would look as follows:
var supportedInstruments = [
{
supportedMethods: ['encrypted-card']
data: {
supportedNetworks: ['amex', 'discover', 'mastercard', 'visa'],
supportedTypes: ['credit', 'debit'],
vaultProviderURL: '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 EncryptedCardVaultRequest {
required DOMString cardNumber;
DOMString cardholderName;
DOMString cardSecurityCode;
DOMString expiryMonth;
DOMString expiryYear;
PaymentAddress? billingAddress;
};
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
};
The encryption can occur in one of two ways:
- through the public key in the TLS certificate of the vault provider if a manifest is not found or the parameter is not found in the manifest
- through a Web App Manifest parameter on the vault provider's origin, specifying a public key and list of ciphers as defined by WebCrypto
- through a public key provided as part of the
PaymentMethodData
dictionary
There's an inherent advantage to re-use the public key in the TLS certificate. This is because a lot can be cached/short circuited.
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 step in TLS. The same cipher suite can be used to encrypt the card data.
That said, re-using the public key, where TLS expressly chooses not to for Forward Secrecy for transport makes this method less ideal for that reason.
A web manifest file can be provided with additional parameters specifying cryptographic parameters. Here's a quick example:
{
encryptedCardKey: {
format,
keyData,
algo,
extractable,
usages
}
}
This data will be fed directly in SubtleCrypto's
importKey
function.
Alternatively, encryption configuration can be specified in PaymentMethodData
. It can use the same parameters specified above, in the web app manifest.
Tokenization can be enabled by setting a true
value to the tokenized
option, as defined above.
The javascript would look as follows:
var supportedInstruments = [
{
supportedMethods: ['encrypted-card']
data: {
supportedNetworks: ['amex', 'discover', 'mastercard', 'visa'],
supportedTypes: ['credit', 'debit'],
vaultProviderURL: 'https://www.bobpay.com/encrypted-cards',
tokenized: true
}
},
...,
];
var payment = new PaymentRequest(
supportedInstruments,
details,
options
);
This will add a roundtrip from the Payment Method
to the vault provider.
The vault provider will return an opaque payload to the Payment Method
, which is then passed on to the merchant.
Additionally, this payload may have a new parameter: expiry
, which can be one of:
nil
"once"
- ISO8061-formatted datetime string