Giter Site home page Giter Site logo

Comments (11)

Goosth avatar Goosth commented on June 1, 2024 2

@ianbjacobs, @stephenmcgruer & @rsolomakhin

This post will explore how we could utilize Public-private keypairs (asymmetric encryption) to provide a layer of obscurity and anonymization to protect Credential ID's for SPC.

There are 4 entities participating in an SPC journey

  • Relying Party(RP): Typically the Bank/Issuer that knows about the customer, the payment instrument and its associated WebAuthn credentials.
  • Intermediary: The merchant, acting as a facilitator, that wants to take advantage of the better user experience and higher success rates, but who does not need to know much about the Webauthn credentials.
  • Browser Agent (e.g. Chrome), that is fulfilling the SPC action. It has a privileged position (and therefore is more trusted), since it manages the domain boundary and determines what is displayed and signed.
  • Fido Authenticator: This challenges the user, and signs the data

The RP (bank) has the identifier (PAN) to credential mapping. We do not want the intermediary to know anything they do not need (for various reasons, including privacy and potential caching of credential ids). The Browser is implicitly trusted and needs to know the credentials, since it needs to call the Fido Authenticator.

Transporting the information
What if we could let the RP pass a JSON Web Encryption (JWE at https://datatracker.ietf.org/doc/html/rfc7516) packet to the Browser? This JWE will be passed to the browser via the Intermediary, but the intermediary would not be able to see or change any value.

The JWE could contain the following encrypted fields

  • List of Credential ID’s
  • RP Origin
  • RP Friendly name
    We could even include other less sensitive fields linked to the transaction such as the Amount, Currency Code, Instrument Name and Instrument Image URL, in an unencrypted format. These fields would therefore be extractable and usable by the Intermediary (Merchant) but they would not be able to ‘tamper’ with it.

The Browser needs to be able to verify and decrypt the JWE, since it needs to use it in the SPC display; to reach out to the correct the Fido Authenticators and also to sign the result.

Transporting the key material
If the Browser Agent could generate a keypair (with the private key kept secret) for each SPC session, and the public key is passed to the RP, the RP would be able to generate the JWE and the browser would be able to decrypt it. (Implementation note: We would be able to use WebCrypto API’s, which would not required additional crypto-work inside the Browser)?

The intermediary already has a back-channel communications mechanism to the Bank (e.g. 3D Secure). As part of this, it today already passes along the PAN, for example, and in return receives a list of credentials and instrument details.

For this to work, the Intermediary would have to do two things:

  • Ask the Browser for an SPC Public-private keypair to be generated, and the public key returned
  • Include the Public key together with the PAN in the request to the RP.

The RP would also need to do some more work to generate this JWE, but we can make that an RP decision, and not enforce it (this optionality needs some thinking, since it could make Intermediary implementations more complex)

** Summary **
Summary of the flow would therefore be

  • Intermediary gathers the identifier (PAN) from the customer (or looks it up from storage)
  • Intermediary asks the Browser Agent to create an keypair, and the public key is returned.
  • Intermediary sends the identifier and public key to the Relying party via an alternative channel (3D Secure)
  • Relying party validates that it is willing to engage with this Intermediary for SPC. It creates a JWE from that public key, and includes the sensitive fields inside it
  • The intermediary receives this JWT and passes it to the Browser Agent to decrypt, perhaps with together some transaction values/fields (Amount/CurrencyCode, Mercant ID)
  • The information is decrypted by Browser Agent, and displayed.
  • Payload constructed for Fido Authenticator and signed.
  • Returned to the Intermediary, who includes this in their request to the Relying party (via external channel). Could also be included in transaction definition.
  • The Intermediary includes this as proof of SPC in the message to the RP.

Would something like this make sense? If so, how do we unpack/design this in more detail?

from secure-payment-confirmation.

rsolomakhin avatar rsolomakhin commented on June 1, 2024

Which algorithm would be used for encryption in this proposal, @ianbjacobs?

Alternative idea is to hash the credential ID with a salt. The salt can be either random or based on the merchant origin.

Random salt:

  1. Merchant requests the list of credential IDs from the issuer.
  2. Issuer generates a random salt.
  3. Issuser sends [salt, hash(salt || credential ID] to the merchant. SHA256 or SHA512 can be used for hashing.
  4. Merchant invokes PaymentRequest API with this hashed credential ID and the salt.
  5. The browser generates hash(salt || credential ID) for each of the credential IDs that it has stored in the user profile.
  6. If any of the hashes match what the merchant provided, then show the verification UI to the user.
  7. Include the salt in the signature to further reduce the risk of replay attacks.

Merchant based salt

For merchant origin based salt, the issuer does not need to generate random salt in step 2. Instead, both issuer and browser use the origin of the merchant as the salt. The salt would not need to be included in the signature, because the signature already included the merchant origin.

A couple of questions:

  1. What other ways do we have to hide the credential ID from the merchant?
  2. How important is this?

from secure-payment-confirmation.

stephenmcgruer avatar stephenmcgruer commented on June 1, 2024
  1. What other ways do we have to hide the credential ID from the merchant?

One (still not very thought-through) option that we've discussed is letting the relying party provide a fetch URL to get the credentials from, rather than have the caller provide the credentials from. The happy path is then that the merchant gets the URL (from their PSP, or 3DS flow, whatever), and passes it to SPC. The browser fetches from the URL, and uses those credentials.

Of course, this is ripe for abuse if the merchant just fetches the URL itself. A relying party could have some protection by making the URL a one-time URL, which allows for detecting if not prevention, but it does get messy...

An advantage of the URL approach vs the salt approach is that it doesn't require the browser to store a list of credential IDs in the user profile, which I consider an annoying part of SPC currently and would love to get rid of! (Because it significantly inhibits portability.)

from secure-payment-confirmation.

ianbjacobs avatar ianbjacobs commented on June 1, 2024

Thanks @rsolomakhin and @stephenmcgruer for the rich ideas. One downside of the URL approach is that RPs need to then offer public-facing services.

@rsolomakhin, the merchant salt idea sounds interesting. I assume that it relies on the relying party never sharing the "real" SPC Credential ID. Is that something we should rely on? (Perhaps the risk is no greater than the RP sharing the private key that is featured in my pseudo-algorithm.)

Regarding "how important is this" I don't have a good sense. It is probably more valuable in payment methods where the instrument data itself is well-managed (e.g., tokenized, origin-bound card info).

For the moment I've described this as "should" in the requirements document. I assume through discussion we will find out whether this feature is a "must".

from secure-payment-confirmation.

ianbjacobs avatar ianbjacobs commented on June 1, 2024

Side note: if the credentials change every transaction, one implication is that caching credentials will not work. I don't yet know how desirable or common it would be to cache credentials.

from secure-payment-confirmation.

stephenmcgruer avatar stephenmcgruer commented on June 1, 2024

This was discussed today at the SPC task-force. We do not believe that the proposed JWT approach would work, as the merchant can trivially person-in-the-middle it as follows:

  1. The Merchant asks the browser for an SPC public key: Browser generates (browser_pub, browser_priv)
  2. The Merchant generates their own public/private key-pair: Merchant generates (merchant_pub, merchant_priv)
  3. The Merchant sends merchant_pub via the back-channel communication to the Relying Party.
  4. The Relying Party encrypts the JWT with merchant_pub and sends it back to the Merchant.
  5. The Merchant decrypts the JWT with merchant_priv, and reads the decrypted credential data.
  6. The Merchant encrypts the JWT with browser_pub, and passes it into SPC.
  7. SPC proceeds as normal.

In general, an encryption based scheme can only work if there is some alternative communication channel directly between the Browser and the Relying Party. This could be online (e.g. during SPC) or offline (e.g. by browsers publishing some known public key that the Relying Party can use), but in either case substantially complicates matters.

I think, but have not verified, that the salting proposal is not subject to a person-in-the-middle attack, but it also may not be compatible with FIDO at all - we've asked the FIDO/WebAuthn folks to take a look.

from secure-payment-confirmation.

ve7jtb avatar ve7jtb commented on June 1, 2024

The salt idea would only work for "Discoverable" credentials. The platform would need to authenticate the user to get the list of credentials from the credential management API then do the hashing with the salt to compare.

Non-resident credentials encode information in the credentialID itself so they would be broken by this.

The other thing to consider is that the authentication response contains the credentialID in the publickeycredentialdescriptor.
https://w3c.github.io/webauthn/#dictdef-publickeycredentialdescriptor

Encrypting or hashing the request is not sufficient, to protect the information from intermediate parties we would also need to encrypt the response to the RP. That could be done by having the issuer store a key in credblob and have the browser use that to encrypt the response. That is however a lot of additional complexity.

from secure-payment-confirmation.

cyberphone avatar cyberphone commented on June 1, 2024

@ve7jtb Since SPC anyway requires you to handover your credit card number to the merchant (w3ctag/design-reviews#675 (comment)), I don't see much of a rationale for protecting credentialId from a privacy perspective. BTW, Apple Pay, Google Pay, and most similar solutions never expose key handles outside of the payment application.

from secure-payment-confirmation.

npdoty avatar npdoty commented on June 1, 2024

suggestion on today's call was that one non-technical mitigation was contractual limits on merchants retaining credential IDs

from secure-payment-confirmation.

ianbjacobs avatar ianbjacobs commented on June 1, 2024

Based on today's discussion, the Editors will work on additional text for the specification regarding guidance to RPs.

from secure-payment-confirmation.

ianbjacobs avatar ianbjacobs commented on June 1, 2024

Closing this after merger of pull request #189. Thank you @samuelweiler and @npdoty! (And thank you for updating the privacy labels as needed.)

from secure-payment-confirmation.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.