Skip to content

encrypted_card

Olivier Yiptong edited this page Sep 12, 2017 · 32 revisions

Encrypted Card Payment Handler

Overview

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+

Payment Handler Properties

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 key 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 key provider that created it
  • Additional constraints may be put by the key provider on the blob (could be a nonce, time bounded, or permanent)

image

PaymentMethodData Specification

The payment handler can be specified using the same syntax as BasicCard with a notable difference: a key 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                 keyProviderURL;
    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'],
      keyProviderURL: 'https://www.bobpay.com/encrypted-cards'
    }
  },
  ...,
];
var payment = new PaymentRequest(
  supportedInstruments,
  details,
  options
);

Card Encryption

The exact same data contained in the BasicCardResponse dictionary, is encrypted.

dictionary EncryptedCardData {
    required DOMString       cardNumber;
             DOMString       cardholderName;
             DOMString       cardSecurityCode;
             DOMString       expiryMonth;
             DOMString       expiryYear;
             PaymentAddress? billingAddress;
};

PaymentRequest Response

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
};

Discussion: Encryption

The encryption can occur in one of these ways:

  1. through the public key in the TLS certificate of the key provider if a manifest is not found or the parameter is not found in the manifest
  2. through a Web App Manifest parameter on the key provider's origin, specifying a public key and list of ciphers as defined by WebCrypto
  3. through a public key provided as part of the PaymentMethodData dictionary

1. Public Key Cryptography using TLS certificate

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.

2. Encryption using Manifest

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.

3. Encryption options specified in PaymentMethodData

Alternatively, encryption configuration can be specified in PaymentMethodData. It can use the same parameters specified above, in the web app manifest.

4. Cipher exchange using metadata in key request API call


Tokenization Extension Use-Case

This use-case is added to support the current scheme employed by Braintree. 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'],
      keyProviderURL: '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 key provider.

image

The data passed to the key provider looks as follows:

dictionary EncryptedCardKeyTokenizationRequest {
  EncryptedCardData cardData;
}

The response will be:

dictionary EncryptedCardKeyTokenizationRequest {
           DOMString encryptedCardData;
  optional DOMString expiry;
}

The key provider returns an opaque payload in encryptedCardData, 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

The response to the Payment Request is unchanged:

dictionary EncryptedCardResponse {
             DOMString       cardholderName; // data from BasicCardResponse
    optional DOMString       suffix; // Last four digits of card number
    required DOMString       encryptedCardData; // base64-encoded string
};
Clone this wiki locally