Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using 'detached' session information as part of encryption key derivation to solve 'lazy verifier' problem #347

Open
jogu opened this issue Nov 26, 2024 · 4 comments

Comments

@jogu
Copy link
Collaborator

jogu commented Nov 26, 2024

The current encryption methods supported in OID4VP require that any information that is used as part of the key derivation is included in the JWE header (e.g. apu and apv). This is basically how the JWE specs and libraries currently work and it's not really possible to not send this information and be compliant with the current JWE RFCs.

It seems it be advantageous to not send some of this information in the JWE and to instead have the verifier provide it from it's view of the world - in particular if information like the web origin, keys, etc, where included in the key derivation and not transmitted, then the verifier would hopefully fail to decrypt a response that has been injected into the wrong session.

Given we have seen a long history of OAuth clients not implementing security checks like session binding correctly, a mechanism where a response from a different session simply fails to decrypt is highly advantageous from an "overall security of an ecosystem" point of view.

@awoie
Copy link
Contributor

awoie commented Dec 9, 2024

In my opinion, the only way to achieve this with a regular JWE compact form is by using a detached protected header. Note that apu, apv, or any additional parameters in the protected header are part of the AAD (Additional Authenticated Data). The AAD is sent in plaintext but is integrity-protected by the authentication tag of the JWE. However, the JWE compact form does not support a dedicated component for additional AAD beyond what is provided via the protected header. In contrast, the JWE JSON serialization form includes a dedicated aad parameter that is concatenated with the protected header to form the full AAD.

Example (Unprotected Header / JARM):

{
  // Could be negotiated or static
  "alg": "ECDH-ES",
  // Could be negotiated or static
  "enc": "A256GCM",
  // Could be a web origin, e.g., https://rp.com
  "apu": "MTIzNDU2Nzg5MGFiY2RlZmdo",
  // Could be a web origin, e.g., https://rp.com
  "apv": "YWJjZGVmZ2gxMjM0NTY3ODkw",
  // Verifier decryption key identifier
  "kid": "P8p0virRlh6fAkh5-YSeHt4EIv-hFGneYk14d8DF51w",
  // Ephemeral decryption key produced by the wallet
  "epk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "laKMaRZltDtdJV0fmSivSI2dhGyOJilIZcXjdsheEfM",
    "y": "jwiLJu_o4PlxGg0RS3zjjT7g3mNcydj5Vc0n5Neby0Y"
  }
}

For the JWE compact form, all these headers are part of the AAD. If we want to detach any AAD value, the entire protected header must be detached.

This creates challenges:

  • Sending the protected header detached would likely result in a non-compliant JWE/JARM during transit, i.e., breaking the JWE specification.
  • Alternatively, we could send an unprotected header with some values omitted, requiring the verifier to compute those missing values which is not great either.
  • In both cases, if the verifier must compute the protected header, a consistent canonicalization process is required. Without canonicalization, the verifier and wallet may generate different versions of the protected header, breaking the integrity check.

Alternatively, we could explore JWE JSON serialization where only the aad JWE component is detached which might be much simpler. The aad is optional and if it is omitted, it is still a compliant JWE, although it cannot be validated without knowing its value (in the case of AES GCM one could probably still decrypt the ciphertext but most implementations would probably still reject it).

@jogu
Copy link
Collaborator Author

jogu commented Dec 11, 2024

Thanks Oliver. I'd tend to agree that calculating the protected header at the verifier is going to be hard/problematic.

I think this is the advantage of using JOSE HPKE - that can potentially update the JWE RFC. We only need a very small addition really - a sentence saying that when using compact serialisation a JWE AAD (which is distinct from AAD) can be communicated out of band. As far as I can see the rest of the steps should all work. (The AAD is defined to be ASCII(Encoded Protected Header || '.' || BASE64URL(JWE AAD)). in the case where a JWE AAD is available.)

The language e.g. around step 14 of https://datatracker.ietf.org/doc/html/rfc7516#section-5.1 makes this probably technically a bit of a grey area:

Screenshot 2024-12-11 at 11 16 41

Technically I think we could perhaps use that same approach with ECDH-ES too, but I think getting existing libraries updated to support that is potentially troublesome. (If I missed some other nuance please let me know!)

@awoie
Copy link
Contributor

awoie commented Dec 12, 2024

Related issue: ietf-wg-jose/draft-ietf-jose-hpke-encrypt#13

@Sakurann Sakurann added the ISO_VirtualMeeting relevant for ISO OID4VP mdoc profile over DC API label Jan 13, 2025
@tlodderstedt tlodderstedt modified the milestones: Final 1.0, 1.1 Jan 13, 2025
@tlodderstedt tlodderstedt modified the milestones: 1.1, Final 1.0 Jan 13, 2025
@Sakurann Sakurann removed the ISO_VirtualMeeting relevant for ISO OID4VP mdoc profile over DC API label Jan 13, 2025
@Sakurann
Copy link
Collaborator

[editor hat on] Already agreed in openid/oid4vc-haip#131 (comment) that not doing detached in Final 1.0, so this is 1.1. However, we need to make sure in PR #380 that how the spec is written does not preclude this detached in the future before going to 1.0, then will change the milestone to 1.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants