Wallet Selection Binding during Issuance
There is an ask from government Issuers to provide a strong signal of which wallet the user selected during a .create() call.
The attack they are looking to mitigate assumes a user with a trusted browser and OS, but has installed a malicious wallet application. If the user selects this malicious wallet application it may able to forward the request to a wallet on an attacker controlled phone, where the digital credential would get provisioned. The Issuer can't easily detect this attack today. This is issue to look at API that maybe required to address this issue.
The attack would go as follows:
- User has a phone in a good state. Neither the browser or OS is compromised
- But they have installed a malicious wallet app
- The issuer website/app makes a DC create call offering to issue a credential. This request contains the pre-auth code.
- Malicious wallet is selected by the user and it gets the request.
- It forwards it to an attacker controlled phone (which could be rooted) where the request is injected into a legitimate wallet app, e.g Google Wallet etc.. This instance of the wallet app is full attacker controlled.
- The legitimate wallet creates the credential. All the attestations and such would be valid
- The Digital Credential is now available in a legitimate and issuer-approved wallet, but on the attacker controlled phone.
There are a number of ways we could solve this:
- The DC Create call could return the wallet that was selected by the user.
- The Issuer could provide an allow-list of acceptable wallet package name when making the create call
- The Issuer could provide a binding key when making the create call. Here the platform would pass the wallet hmac(binding_key, selected_wallet_identifier)
- Something where the Issuer could provide an allow-list of wallet attestations using some new to-be-standardized PKI
Of these option 3 or 4 are my preferred options.
Option 1 is awkward as the credential issuance flow is normally complete before the call returns. It also exposes the user's wallet app in every call and this has poor privacy properties. Doesn't really work cross-device.
Option 2 exposes OS internals to the web, requiring a web API to contain OS specific app package names. Also just don't much like sending allow lists of package names, as you could imagine an issuer allowing any certified wallet, without knowing the package names upfront. It could lead to a lot of fragmentation. If this is signed over it could work for hybrid though.
Option 3 the caller could add a binding_key param to the top level DC create() call. This can just be a random string of 64 bytes. This key will be kept secret from the wallet app. The user agent/OS will produce hmac(binding_key, selected_wallet_identifier) and send it to the wallet application along with the normal issuance request. The wallet can then pass this value to the Issuer servers as part of any validation steps. The issuer can now get a strong signal for which wallet was selected by the user. This doesn't really work for hybrid though.
Option 4 assumes that wallet apps hold a industry defined attestation, this could be a special type of Digital Credential issued to them by an certification org. In this option the issuer could provide a list of acceptable attestation credentials (like the get call) and the OS could challenge the wallet to prove it holds one before it appears in the selector to the user. This also has the benefit of the solving the problem of filtering out non-malicious wallets that may offer themselves up even though they would fail during the process if selected (as they are not approved by the issuer).
All of these add a decent amount of new complexity and will likely require a healthy amount of discussion.
Discussed on the 1 October call. Leaving on the agenda to continue the discussion next week.
My preference would be on 3 or 4 with a slightly higher preference for 4 for basically the reasons given above.
In the context of large scale identity federations the so called discovery problem presents a similar security issue: how do you know that in a list of identity providers, the user isn't presented with a malicious IdP. One approach to mitigate this is precisely a variant of 4, where policy tags can be added to authenticated (signed) metadata as a way to carry a signal to the discovery interface.
Further discussion on the 6 October call. Group is leaning towards 3; will likely have a breakout session at TPAC.
Just to reiterate and expand on what I just said on the call about this: it seems to me that the key question is what level of involvement the DC API layer has (relative to the underlying prototcol layer) in the issuer<-> wallet trust framework. In options 1, 2 and 4 the DC API needs to define some aspect of that framework (is trust bound to native app identifiers like package names or via some PKI system?). While option 3 lets the underlying protocol choose which mechanism is best given the use case.
It seems to me that in the presentation space we're converging on a design where our spec has security / privacy considerations for the protocol layer, but leaves precise control over those properties to the protocol layer giving it some flexibility in what tradeoff is appropriate given the context. So I think option 3 is most consistent with that.
Hi everyone,
[cc'ing @Sh-Amir, @ZAnsaroudi]
The key concept, as @RByers says, is related to the involvement/role of the DC API in the rest of the ecosystem, and in any case, as a medium.
On the other hand, as @leecam clearly explained in the killchain, the root cause is in point 2:
But they have installed a malicious wallet app
This is clearly a concept contained in the first Immutable Laws of Security v2 (the corrections are mine):
If a bad actor can persuade you to run their ~~program~~ Malicious Wallet on your ~~computer~~ device, it's not solely your ~~computer~~ device anymore."
That said, since no one prohibits applying countermeasures at a different level than that of the threat.
Very interesting when @leifj says this, which makes me think of two things:
- Potentially, we could have a malicious issuer who gives you a credential with tracking capabilities
- It also makes me think about the various uses of the DC API that are not for government-issued credentials, and it also makes sense in scenarios where the user has the freedom “by design” to choose their wallet.
In summary, if we decide to apply mitigation at the API level, I prefer option 3 for flexibility, but option 4 also seems like a good solution.
Having good protections against malware in the software users might install is a separate consideration from relying on issuers or verifiers to enforce such protections. The latter can cause significant harms to ecosystems. This has been discussed in similar settings the past. For example, see a related conversation around the potential harms of "attestations" (something that came up with WebAuthn) see:
https://www.imperialviolet.org/2018/03/27/webauthn.html#attestation:~:text=Traditionally%2C%20anyone%20who,have%20to%20pay
This is also linked to in a conversation around "wallet attestations" happening here:
https://lists.w3.org/Archives/Public/public-security/2025Oct/0015.html
I prefer option 3, as
- option 1 is insufficient
- it seems less of a layer violation compared to 2 & 4
- it seems less complex than 4
Ideally, option 3 could also be done using something with random nonce and SHA-256 (similar to PKCE) instead of HMAC.
We had a discussion at IIW, and integration for option 3 into VCI seems not too hard:
- send platform attestation containing hashed origin at Token/PAR Request
- define a claim for origin in wallet attestation
- issuer needs to compare origins
There is an ask from government Issuers to provide a strong signal of which wallet the user selected during a .create() call.
I'd like to, as politely as possible, suggest that it is inappropriate for our specifications to intentionally help sovereign states surveil users.
There really is no good reason for the state to demand to know which client you are supposedly using. Not only because it's none of their business (my political perspective), but also because it cannot provide them with the guarantee they are expecting (my technical opinion). There is simply no way to know for sure what client a user is running. Secret keys can be reverse engineered. Good clients can be compromised.
Every system is hackable. Every "user-agent" fingerprint is spoofable. Any security that depends on not being hackable simply makes it easier for successful hackers to sneak past the formal (yet ineffective) gatekeeping and then compromise those systems relying on the spoofed security.
So, not only is it offensive to think that we, as a global organization, would enable any given country to spy on web users, it is a security malpractice to support the idea that it is even possible to determine what software is running at the other end of a digital transaction. You can't.
The mistake, I believe, in the original analysis, is that it a "malicious wallet application" is somehow detectable.
It is no more detectable than a malicous web browser, browser extension , or even a malicious website.
Yes, these things exist. But a registry of allowable clients--which is what we are talking about--is a non-starter for both political and technical reasons.
Users choose their user-agents.
Full stop.
If users are not allowed to choose their agents, it is no longer the World Wide Web, it is just another proprietary walled silo.
I hope we can keep our sites on maintaining an open web for everyone.
Given this assumes the browser and OS are not compromised and there doesn't appear to be PKI associated with option 3, I would prefer that approach that doesn't require OS-specific app identities to be transmitted to the issuer (albeit in an opaque-to-the-wallet way).
Could we instead have something like a .well-known file hosted by the issuer that contains a list of all platform/app identity combos that it considers to be itself? And then the OS would fetch that, cross-reference it, and locally compute a value based on if it met the desired app identity criteria (perhaps a boolean, perhaps some enum that can also disambiguate "app identity does not match" vs. "this platform is not specified in the .well-known file at all"). That value would then be what's combined with binding_key (instead of the app identity).
I acknowledge the mainline case still requires the issuer to do work to add each new wallet that it wants to support in a mainline way, but it would also allow platforms to explore a mechanism to unblock it anyway if a scenario arises where the issuer-- for whatever reason-- won't support the user's preferred platform that doesn't involve hardcoding/spoofing some other platform's app identifiers.
In some future stage, if a PKI-based scheme is defined, the .well-known mechanism could be extended to support that criteria instead without modifying the format of the binding is transmitted to the issuer.
I believe what I'm describing is some hybrid of option 2 (makes a web-exposed thing contain app identities-- but if the issuer at the end of the flow is computing the same value I'm not sure option 3 avoids this concern), option 3 (still uses an opaque passthrough value that conveys some limited state), and option 4 (can extend to use some PKI mechanism later).
Given the stated threat model of "malicious wallets should be disallowed," I hope this would be sufficient while also giving more flexibility to respond to unintended ecosystem platform lock-in effects if they arise.
@erik-anderson Could we instead have something like a .well-known file hosted by the issuer that contains a list of all platform/app identity combos that it considers to be itself?
I'm not sure I understand this proposal. In many (likely most) cases, the issuer will not have an up front relationship with the credential manager.
Hoping this is useful for your discussion: in the latest version of the ARF 2.7.3 for the EUDI Wallet, in particular section 4.4, we tried to consolidate our position on DC API and related issues, addressing several topics including the one raised in this thread. You can find it here: https://eudi.dev/latest/architecture-and-reference-framework-main/#44-data-presentation-flows
We more details here and in the FAQ section https://eudi.dev/latest/discussion-topics/f-digital-credential-api/
@erik-anderson Could we instead have something like a .well-known file hosted by the issuer that contains a list of all platform/app identity combos that it considers to be itself?
I'm not sure I understand this proposal. In many (likely most) cases, the issuer will not have an up front relationship with the credential manager.
It's possible I'm not parsing the relationships here. In the initial comment in this issue, it states a possible option is, "The Issuer could provide an allow-list of acceptable wallet package name when making the create call."
Yet I think you're saying that the issuer does not know what wallet(s) it cares about. Or maybe the word "relationship" is carrying some weight; if so, I'm not suggesting the wallet needs to do any work to establish a relationship. It's all up to the issuer.
Whatever the case is, my strong preference is-- if the device is trusted to give a signal about some aspect of the credential manager-- that signal should not be tied to something that allows deriving the wallet name by running the same hashing computation against an oracle of known, supported wallets. Instead, it should send something close to a boolean signal which is derived from a local computation. That computation would presumably be tied to an allow-list mechanism initially but could also be changed to some form of PKI in the future.
It seems user hostile to reveal or allow the control over the wallet to the issuer, both for privacy purposes (I might not want my government to know my software choices), and for control purposes that can affect future decisions the user might want to make (government-approved wallets might either phone home, or cutoff access, or alter documents).
Blocking use of malicious wallets seems like something you don't want to leave up to the issuer. If someone knows about a malicious wallet, asking every issuer in the world to update their allow/deny lists seems way less effective than letting OS vendors/anti-malware vendors know the signature of the malicious software so that users can be notified and protected.