Support Credential Request application-layer encryption
While not relevant when making a direct request form a Wallet to an Issuer endpoint, when going through Wallet Server between the Wallet and the Issuer, application-layer encryption provides a positive privacy benefit to the user.
In particular, for a credential format like mdoc, if the Wallet Server sees the device keys being sent to the issuer, they are able to collude with RPs to track all presentations of the issued credentials. If the credential request is instead encrypted, (and using single-use MSOs) this sort of tracking would only be possible through issue-RP collusion.
I'm not sure if we explicitly say it, but I think there is a current assumption in the spec that calls to the issuer endpoint are made from the wallet app.
I guess the first thing we need to agree on is why there may be a need for these calls to go through a wallet's backend?
Oh, sure. From prior conversation with others on the spec my understanding was that OpenID4VCI was intended to support both going through some wallet sever infrastructure as well as directly connecting to the issuer. Clearly, there are privacy implications to doing so, and that e2ee was the intended mechanism for closing some of these gap (and why it is available for credential response).
At its heart the reason for going through a wallet server infrastructure is reliability and usability at scale. Functionally, it should be assumed that any Wallet application can never be updated, as in practice users update slowly and inconsistently. Similarly any analytics/monitoring is slow and unreliable, making detection of issues challenging.
Wallet server infrastructure does not face these issues, and allows for working around client version skew issues that would simply be infeasible for issuers to deal with.
My assumption here is that the Wallet in question is distributed to millions or billions of devices, and is intending to contact 100s of different issuers. Similarly, Issuers would assume to interact with multiple wallets that they do not own, control or understand.
If you'd like, I can open a different issue to ask if using wallet server infrastructure is a valid way to use OpenId4VCI? For me to want to use this would be a hard requirement.
Thanks Gareth! I think that's probably fair - I'm not sure it's necessarily intended to support this architecture but it's certainly not prevented. We don't have any privacy considerations for that kind of architecture so potentially we might need to add them.
The credential response encryption unfortunately isn't great at the moment as currently the wallet backend could gain access to the encrypted data (unless there's extra checks in the issuer on the key used for encryption), but adding the kind of encryption you suggest in this issue might solve that some of that issue.
Using OpenID4VP we have considered useful the encryption of the presentation response. If we have recognized values in the presentation phase we should recognize the same values in the issuance too.
i don't have aprticular privacy concerns about the request, while I would put our attention about the consistency between the request and the response to preserve confidentiality. if the request is exncrypted, the response should be encrypted too.
with this further awareness and changes I would completely support this
As stated on the Mon Oct 28, 2024 OIDF DCP WG Hybrid Meeting at Microsoft, I am opposed to the complexity of more application layer encryption.
@bc-pi: My understanding of your objection was that you do not agree that a wallet server infrastructure is a valid architecture, and therefore the complexity is not warranted. As a prospective user of OpenID4VCI, with an existing issuance system, I disagree, hence the feature request.
In terms of complexity: I think its a smaller change than credential_response_encryption, but can follow a similar pattern:
add an optional credential_request_encryption parameter in the Credential Issuer Metadata, containing the jwk/alg/enc needed to perform the encryption.
Then, as with credential_response_encryption, require the content-type of credential request to be application/jwt, and require the client to encrypt the CredentialRequest as a jwt using the parameters in Credential Issuer Metadata.
This seems technically sound, relatively straight forward, and then it can be up to profiles/issuers/clients as to whether this is necessary.
From discussions at II#40 I support this. OpenID4VCI is meant to support different wallet architectures. Gareth layed out valid reasons to have a wallet backend involved as a proxy. Furthermore, it allows us to fix credential response encryption which seems broken to me in its current form and does not protect to MITM behind TLS termination. If we add this, requirement should be that Credential Response encryption enforces Credential Request encryption.
i do not want to complicate things, but wanted to document that there was a proposal from ISO not to use JWE/ application/jwt, but have a direct encrypted connection between the wallet (server) and the issuer.
I personally believe approach suggested in this issue (add an optional credential_request_encryption parameter in the Credential Issuer Metadata) is simpler and easier to implement for existing implementers.
Discussed on today's call.
Exposing a jwks so that the wallet potentially has a choice of keys with different algs etc, and wallet signals with kid in the JWE which it picked.
Martijn & Brian raised some concerns and will hopefully add comments explaining them.
[...] & Brian raised some concerns and will hopefully add comments explaining them.
The concern was that I think it's a bad idea that adds unnecessary complexity and cognitive overhead in a way that allows a kind of misplaced security theater while likely not providing many of the benefits described. Also that it would likely prove to be more difficult to spec out than expected. But I agreed to stop expressing these concerns and let those that wish to pursue more application-layer encryption proceed with this.
WG discussion: on the credential request:
- add an optional
credential_request_encryptionparameter in the Credential Issuer Metadata, containing a jwks so that the wallet potentially has a choice of keys with different algs etc, and wallet signals with kid in the JWE which it picked. Then, require the content-type of credential request to beapplication/jwt. - entire request will be encrypted.
- @martijnharing to confirm that there are no concerns with this
- wallet and wallet backend interface is not standardized and they can communicate unencrypted information among themselves.
- hypothetically, there can be a situation where part of the credential request only frontend should know, and another part only backend should know, in which case, the current design is not optimal, but we are not aware of such a scenario, so not optimizing for this.
- who decides whether the request needs to be encrypted?
- if issuer puts encryption key, the wallet MUST encrypt the credential request
on the credential response
- @martijnharing to open an issue why there is a need for a feature to encrypt only part of the credential response. with examples of specific data in the credential response that need/do not need to be encrypted
To provide completeness on the different approaches possible:
A per-field or part-encrypted request/response provides the advantage (both now and in the future) of allowing some fields to be provided or understood by the server and some by the client. In principal this allows the PII to be hidden from the server and forward secrecy guaranteed while getting reliability.
Pro:
- Provides more capabilities to work around protocol/issuer behavior without client updates (so reliability)
- Potentially latency advantages (preventing extra round trips) Cons:
- More complexity (regardless of what exact mechanism is chosen)
- More difficult to reason about the privacy guarantees
Some approaches that could be taken to achieve this:
- Split the payload into an encrypted part and un-encrypted portions (structural change)
- use JWE on a per-field bases that needs to be encrypted (space/efficiency cost)
- do our own key-wrapping, and then encrypt each field with that async key (complex)
As an added note: We may want to consider using a JWT rather than a JWE and provide the option to sign it to integrity protect the contents, and bind it to the wallet (I don't know enough, but perhaps using the same as the dpop key, or the key used in the proofs). The proofs are obviously already bound, but the other contents (most notably the device encryption keys) aren't.
We could also do this by signing over those keys, but probably simpler to simply use the existing JWT structure and integrity protect everything we are encrypting.
WG discussion:
- agree to start with encryption of entire credential request, if partial request encryption will be needed in the future, do it in 1.1 in a non-breaking manner.
I'm no cryptographer (or lawyer or much of anything) but I'd be hesitant to use phrases like 'forward secrecy guaranteed' with encryption involving likely relatively static server public keys.