- edited description
Error on JWE decryption - Wrong algorithm: AES or Rijndael required
Using the following code I get a BadJWEException when calling jwtProcessor.process()
Debugging, I ascertained that when decrypting the JWE it obtains the decryption key via the KeyConverter, which strips the algorithm type "AES" when it calls SecretJWK.toSecretKey(). Since the algorithm type is then "NONE" it fails decryption.
String hostId = "subject";
String sharedSecret = "SharedSecret";
byte[] salt = new byte[8];
new SecureRandom().nextBytes(salt);
SecretKey secretKey;
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(sharedSecret.toCharArray(), salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
} catch(NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new RuntimeException("couldn't generate key");
}
// create the JWT
JWSSigner signer;
try {
signer = new MACSigner(secretKey.getEncoded());
} catch(KeyLengthException e) {
throw new RuntimeException("signing key length issue", e);
}
JWTClaimsSet inputClaimsSet = new JWTClaimsSet.Builder()
.subject(hostId)
.expirationTime(new DateTime().plusSeconds(60).toDate())
.build();
SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), inputClaimsSet);
try {
signedJWT.sign(signer);
} catch(JOSEException e) {
throw new RuntimeException("signing issue", e);
}
JWEObject jweObject = new JWEObject(
new JWEHeader.Builder(JWEAlgorithm.DIR, EncryptionMethod.A256GCM)
.contentType("JWT")
.build(),
new Payload(signedJWT)
);
try {
jweObject.encrypt(new DirectEncrypter(secretKey.getEncoded()));
} catch (KeyLengthException e) {
throw new RuntimeException("encryption key length issue", e);
} catch (JOSEException e) {
throw new RuntimeException("encrypting issue", e);
}
String jweString = jweObject.serialize();
// parse the JWT
JWT jwt;
try {
jwt = JWTParser.parse(jweString);
} catch(ParseException e) {
throw new RuntimeException("could not parse token");
}
if (!(jwt instanceof EncryptedJWT)) {
throw new RuntimeException("encrypted JWT required");
}
ImmutableSecret secret = new ImmutableSecret(secretKey);
ConfigurableJWTProcessor jwtProcessor = new DefaultJWTProcessor();
JWEKeySelector jweKeySelector = new JWEDecryptionKeySelector(JWEAlgorithm.DIR, EncryptionMethod.A256GCM, secret);
jwtProcessor.setJWEKeySelector(jweKeySelector);
JWSKeySelector jwsKeySelector = new JWSVerificationKeySelector(JWSAlgorithm.HS256, secret);
jwtProcessor.setJWSKeySelector(jwsKeySelector);
JWTClaimsSet outputClaimsSet;
try {
outputClaimsSet = jwtProcessor.process((EncryptedJWT) jwt, null);
} catch(BadJOSEException | JOSEException e) {
throw new RuntimeException("could not parse");
}
Comments (5)
-
reporter -
- changed status to open
Thanks for reporting this in detail, we'll try to replicate here.
-
I'm looking at the snippet right now. There's no need to nest an HMAC JWT inside a JWE because encryption in JWE is always authenticated:
https://connect2id.com/products/nimbus-jose-jwt/algorithm-selection-guide
Encryption in JOSE is always authenticated, meaning that ciphertext’s integrity is protected from tampering. Authenticated encryption thus makes nesting an HMAC JWT inside a JSON Web Encryption (JWE) redundant; use just JWE encryption.
So you could use a simple
EncryptedJWT
. -
- changed status to resolved
Fixed in commit 4d09e36.
Will be pushed to maven central as v5.4 in a few minutes.
-
reporter Thank you for the prompt fix. It's working perfectly!
- Log in to comment