JwksDecryptionKeyResolver does not support resolving OKP keys for ECDH-ES (or ECDH-ES with key wrapping)

Issue #218 closed
Erin created an issue

I’m trying to use JwksDecryptionKeyResolver with an OctetKeyPairJsonWebKey decryption key to decrypt a signed and encrypted JWT using Ed25519 and X25519. I’ve tried the most obvious usage I can think of, but the key resolver will not select the key, even when the key ID is an exact match.

I’ve attached some code that can be used to reproduce the issue.

I’ve done some debugging, and it seems like the issue is caused by the key type being explicitly set to "EC" in the filter created internally by JwksDecryptionKeyResolver. This is because the key type is pulled from the algorithm, and both EcdhKeyAgreementAlgorithm and EcdhKeyAgreementWithAesKeyWrapAlgorithm have a fixed key type of EllipticCurveJsonWebKey.KEY_TYPE.

As far as I understand, OKP keys are also a valid choice for ECDH-ES. Is there any way to get around this without writing a custom decryption key resolver?

Comments (8)

  1. Brian Campbell repo owner

    Hi Erin - Thanks for finding/raising this and the debugging and detailed explanation. There’s indeed a defect here, which looks like something that was overlooked when adding X25519 etc support from RFC 8037 with #72. Unfortunately, fixing it is going to be a little awkward because RFC 8037 kinda breaks the assumption from the original JOSE RFCs that an alg implied a single kty. But I’ll try and do something that’s not too ugly.

    In the meantime, I’m afraid a custom decryption key resolver is probably what you’ll have to do. Here’s a simple example of one in a snippet of the reproduction code you provided:

          ...
    
                    new JwtConsumerBuilder()
                            .setDecryptionKeyResolver(new DecryptionKeyResolver() {
    
                                private final List<JsonWebKey> jsonWebKeys = List.of(encryptionKey);
    
                                @Override
                                public Key resolveKey(JsonWebEncryption jwe, List<JsonWebStructure> nestingContext) throws UnresolvableKeyException {
                                    SimpleJwkFilter filter = new SimpleJwkFilter();
                                    String kid = jwe.getKeyIdHeaderValue();
                                    if (kid != null)
                                    {
                                        filter.setKid(kid, SimpleJwkFilter.VALUE_REQUIRED);
                                    }
                                    List<JsonWebKey> filtered = filter.filter(jsonWebKeys);
                                    return ((PublicJsonWebKey) filtered.get(0)).getPrivateKey();
                                }
                            })
                            // Uncomment the following line to demonstrate that the token is valid
                            // .setDecryptionKey(encryptionKey.getPrivateKey())
                            .setVerificationKeyResolver(new JwksVerificationKeyResolver(List.of(signingKey)))
    
           ...
    

  2. Log in to comment