- edited description
Errors when using MultiEncrypter/MultiDecrypter with only one recipient
Hi,
in our use case we use the library to encrypt JSON messages for one or more recipients and to decrypt them for recipients accordingly.
I noticed that if the MultiEncrypter is used with only one recipient, an invalid JWE is generated. The information about the encryption algorithm used is lost in the generated JWE.
The following example can be used to reproduce the bug:
ECKey jwk = new ECKeyGenerator(Curve.P_256)
.keyUse(KeyUse.ENCRYPTION)
.algorithm(JWEAlgorithm.ECDH_ES_A128KW)
.generate();
JWEObjectJSON jwe = new JWEObjectJSON(
new JWEHeader(EncryptionMethod.A128GCM),
new Payload("Hello, world!"));
jwe.encrypt(new MultiEncrypter(new JWKSet(jwk)));
jwe.decrypt(new MultiDecrypter(jwk));
The generated JWE looks like:
{
"ciphertext": "OUpEYZQnnXTFs7jVSQ",
"protected": "eyJlbmMiOiJBMTI4R0NNIn0", // decoded: {"enc":"A128GCM"}
"recipients": [
{
"encrypted_key": "e2dzatT-zlIQNL5AkkI2Hx2nEwkZTJbB"
}
],
"tag": "9OWSTMmBHPLQYbB7wfWcSQ",
"iv": "4VSnYkuEHxilo1P-"
}
This leads to the following error, when trying to decrypt the JWE:
Exception in thread "main" com.nimbusds.jose.JOSEException: The algorithm "alg" header parameter must not be null
at com.nimbusds.jose.crypto.impl.JWEHeaderValidation.getAlgorithmAndEnsureNotNull(JWEHeaderValidation.java:50)
at com.nimbusds.jose.crypto.MultiDecrypter.decrypt(MultiDecrypter.java:322)
at com.nimbusds.jose.JWEObjectJSON.decrypt(JWEObjectJSON.java:556)
at example.Main.main(Main.java:33)
I’m using the latest version 9.39.1 with openjdk-17.
I would also be willing to help with the solution, but I'm not sure where the right place would be. As I understand it, the JWEObjectJSON should ensure that the algorithm is drawn from either the protectedHeader or the unprotectedHeader during encryption.
During my first analyses, when I tried to understand the problem, I also noticed that the MultiDecrypter also has problems if there is only one recipient and the algorithm is stored in the unprotected header. As far as I understand the RFC 7516, this should be valid.
The following code will throw the same exception:
ECKey jwk = new ECKeyGenerator(Curve.P_256)
.keyUse(KeyUse.ENCRYPTION)
.algorithm(JWEAlgorithm.ECDH_ES_A128KW)
.generate();
String jweString = """
{
"ciphertext": "9xhMUKE7p4q8om4XqQ",
"protected": "eyJlbmMiOiJBMTI4R0NNIn0",
"recipients": [
{
"encrypted_key": "cy4kUzylYaPdQ70p-zgyIRulcxFPNyqK",
"header": {
"epk": {
"kty": "EC",
"crv": "P-256",
"x": "M4IGUyaltmdmVEtJRU-fsWigsye4nVoIV8by7QVG5vw",
"y": "g_WhCLmDpy86cktOuIVFUAnvZiS-rioFZkYg3E8oSus"
},
"alg": "ECDH-ES+A128KW",
"kid": "NNPVrleSyhpC1S99mM3YrY5WjyTpYYHHM6uHSMICrBw"
}
}
],
"tag": "H8yHJrhVAJ5wxWsqaLtvKQ",
"iv": "4YxtWzvhh5sZLTv1"
}
""";
JWEObjectJSON jwe = JWEObjectJSON.parse(jweString);
jwe.decrypt(new MultiDecrypter(jwk));
Comments (3)
-
reporter -
- changed status to open
Hello Theo,
Thank you for reporting this issue.
The Multi Encrypter / Decrypter functionality in the lib was an external contribution. We don't use at connect2id, but did spend some time after it was recevied to improve the quality so that it matches the standard of the library. It looks like a significant bug looking at your discovery.
-
Hello,
I believe this is because these two classes, along with JWEObjectJSON, attempt to place recipients into the encryptedKey variable during encryption and decryption,
but they don't handle the case where there is only one recipient well.
If you need some quick fixes, maybe overrideMultiEncrypter.encrypt()
and just change the line 294
fromif (recipients.size() > 1)
toif (!recipients.isEmpty())
, then the encryption part should be fine.
For the decryption part, maybe overrideJWEObjectJSON.getEncryptedKey()
, and remove the part for only one recipient at lines 339 to 341,
though this will make the method somewhat pointless, as it just encodes the recipients. - Log in to comment