-
Notifications
You must be signed in to change notification settings - Fork 241
Description
Since the SPC specification is to be discussed at https://github.com/w3c/webpayments/wiki/Agenda-FTF2021, I took the liberty outlining an enhanced scheme that may serve as "inspiration". It is not entirely complete (enrollment is currently missing), but the core is hopefully understandable. The proposal mainly deals with security constructs and data flows.
Updated: 2021-02-19
Enhancements
- Privacy: User-unique information (PII) is neither required nor provided to external actors.
- Security: Reduced attack space since no sensitive data is given to external actors. Encryption replaces tokenization.
- Universality: Applicable to any account based payment system.
- Simplicity: In similarity to EMV the scheme does not not depend on external challenge data or centralized registries holding enrolled account numbers.
Although not a part of this specification, the underpinning authorization scheme also opens the door to non-direct payments, including secure (tokenized) versions of Card-on-File.
Prerequisite - Payment Credentials
The scheme outlined here depends on that the User already has received a payment credential from the Issuer in an enrollment process. A payment credential is supposed to at least contain the following elements:
- A User specific (unique) FIDO key for signing payment authorization data.
- An
accountIdassociated with the FIDO signature key. - An Issuer specific (shared) public key for encrypting payment authorization data.
- An
issuerIdin the form of a BIN number or a URL associated with the Issuer. - An icon identifying the payment credential for the User.
A payment credential is associated with a specific paymentMethod established during enrollment.
Detailed Operation
The different steps in following state diagram are described in this section.

Note: this specification does not elaborate on the return data from the Issuer etc.
1. The Merchant creates payment request data (PREQ) and invokes the payment request API with it:
{
"id": "7040566321",
"payee": "Rocket Shop",
"amount": {
"currency": "EUR",
"value": "435.00"
}
}Note: the JSON object above outlines the conceptual data before being translated into a compliant Payment Request call. It seems that payee currently have no obvious place in the API.
2. The Browser responds with PREQ rendered in a user interpretable fashion:

Non-normative UI.
3. The User authorizes the request with a fingerprint, PIN, or similar.
4. After successful user authorization, the Browser MUST perform the following internal steps.
4.1 Calculate a Base64Url-encoded SHA256 hash of PREQ, canonicalized according to RFC8785. Expressed as a formula: BASE64URL(SHA256(RFC8785(PREQ))). Applied to the sample data, the result of this operation should be "Zf6qUOoA3NWM77rksuji2tE7tlGHrzu9K5Y_AGn5tkw".
4.2 Create an authorization data object (AD) with data needed for processing by the Issuer:
{
"requestHash": {
"algorithm": "S256",
"value": "Zf6qUOoA3NWM77rksuji2tE7tlGHrzu9K5Y_AGn5tkw"
},
"payeeHost": "spaceshop.com",
"accountId": "FR7630002111110020050014382",
"timeStamp": "2021-02-18T10:32:35+01:00"
}requestHashcryptographically binds PREQ to AD.payeeHostis picked-up by the Browser.accountIddenotes the actual account number to be debited and is retrieved from the payment credential. The sample uses a French IBAN number but it could equally well be a credit card PAN.timeStampis generated internally.
4.3 Using the FIDO signature key, sign AD using JWS/CT resulting in the following completed AD object:
{
"requestHash": {
"algorithm": "S256",
"value": "Zf6qUOoA3NWM77rksuji2tE7tlGHrzu9K5Y_AGn5tkw"
},
"payeeHost": "spaceshop.com",
"accountId": "FR7630002111110020050014382",
"timeStamp": "2021-02-18T10:32:35+01:00",
"signature": "eyJhbGciOiJFUzI1NiIsImp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2IiwieCI6IjZCS3hwdHk4Y0ktZXhEekNraC1nb1U2ZFhxM01iY1kwY2QxTGFBeGlOclUiLCJ5IjoibUNiY3ZVem00NGozTHQyYjVCUHlRbG9ROTF0ZjJEMlYtZ3plVXhXYVVkZyJ9fQ..XvwOEMX4CG8l5nq-rOSkEbdFRcrhtAdQ6s1HFtLgiWMoNliiPSJnurmBnkBzudoLucBLVRwql6ZWANq1AALcXA"
}Although not visible in the listing above (due to JWS' Base64Url-encoding requirements on JWS header data), AD signatures MUST provide a key identifier. In the sample, the following JWK holding the public key was used:
{
"kty": "EC",
"crv": "P-256",
"x": "6BKxpty8cI-exDzCkh-goU6dXq3MbcY0cd1LaAxiNrU",
"y": "mCbcvUzm44j3Lt2b5BPyQloQ91tf2D2V-gzeUxWaUdg"
}4.4 For privacy and security reasons, the completed AD object MUST be encrypted by a public key provided by the Issuer through the payment credential. This specification builds on JWE (RFC7516) using the compact serialization mode. The selection between an RSA or ECDH encryption scheme is at the discretion of the Issuer. AD objects MUST be JSON-serialized to UTF-8 before being encrypted. The resulting JWE string would look something like this (with line breaks for display purposes only):
eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.OKOawDo13gRp2oja
HV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGeipsEdY3mx_etLbb
WSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDbSv04uVuxIp5Zms
1gNxKKK2Da14B8S4rzVRltdYwam_lDp5XnZAYpQdb76FdIKLaVmqgfwX7XWRxv2
322i-vDxRfqNzo_tETKzpVLzfiwQyeyPGLBIO56YJ7eObdv0je8860ppamavo35
UgoRdbYaBcoh9QcfylQr66oc6vFWXRcZ_ZT2LawVCWTIy3brGPi6UklfCpIMfIj
f7iGdXKHzg.48V1_ALb6US04U3b.5eym8TW_c8SuK0ltJ3rpYIzOeDQz7TALvtu
6UG9oMo4vpzs9tX_EFShS8iB7j6jiSdiwkIr3ajwQzaBtQD_A.XFBoMYUZodetZ
dvTiFvSkQ
To simplify documentation, the JWE string is subsequently referred to as "JWE-Encrypted-AD".
Note that due to the end-2-end encryption scheme, the domain constraints usually associated with FIDO, do not apply.
4.5 Put the encrypted AD into a payment response object (PRES) together with clear text data needed for payment "backend" processing:
{
"encryptedAuthorization": "JWE-Encrypted-AD",
"paymentMethod": "https://europeanpaymentsinitiative.eu/spc",
"issuerId": "https://mybank.fr/payment"
}paymentMethod is the actual SPC method used. See #1570 (comment).
Note that by encrypting authorization data, the "routing" of payment requests with respect to the Issuer is separated from account numbers. By using URLs like in the example, the need for databases holding BIN numbers is eliminated.
5. The Browser returns PRES to the Merchant.
6. The Merchant puts its original PREQ and the received PRES into an authorization request object (AREQ):
{
"paymentRequest": {
"id": "7040566321",
"payee": "Rocket Shop",
"amount": "435.00",
"currency": "EUR"
},
"encryptedAuthorization": "JWE-Encrypted-AD",
"paymentMethod": "https://europeanpaymentsinitiative.eu/spc",
"issuerId": "https://mybank.fr/payment"
}7. The Merchant sends AREQ to the Acquirer service associated with the specific paymentMethod. Note that authentication of AREQ is out of scope for this specification.
8. The Acquirer validates the authenticity and syntax of the received AREQ as well as looking up the Issuer through the supplied issuerId.
9. The Acquirer augments the received AREQ with additional data (like Merchant collection account), and forwards the completed object to the designated Issuer. Note that authentication of AREQ is out of scope for this specification.
10. The Issuer MUST now perform a number of steps to verify the correctness of the received AREQ. With respect to the User the following steps are the most significant:
10.1 Decrypt the encryptedAuthorization object in AREQ using the Issuer specific (but shared) decryption key. Set result as AD.
10.2 Retrieve the signature key declared in the JWS header of the AD signature element. Abort if unknown.
10.3 Verify that the retrieved signature key is associated with the AD accountId element. Abort on failure.
10.4 Validate the AD signature using the retrieved signature key. Abort on failure.
10.5 Perform the same calculation as specified in 4.1 on the received paymentRequest object and compare the result with the AD requestHash. Abort on failure.
10.6 Check that the AD timeStamp element is within limits. Tentative: CurrentTime - 600s < timeStamp < CurrentTime + 60s. Abort on failure.
10.7 To cope with possible replays, check that the received AD has not already been utilized. Ideally, the Issuer should support idempotent operation to facilitate benign transaction retries.
Available funds also needs to be validated but that is out of scope for this specification.
@equalsJeffH @nadalin @rlin1