Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

While JWS Compact is optimized and represents a concatenation of up to 3 Base64URL values, JWS JSON is an open JSON container, see Appendix 6.

...

The above code produces a JWS JSON sequence containing two signatures, similarly to this example. If the sequence contains a single signature only then the JWS JSON 'signatures' array will contain a single 'signature' element, or the whole sequence can be flattened with instead with the actual 'signatures' array dropped. JwsJsonProducer  does not produce the flattened sequence when only a single signature is used by default because 3rd party JWS JSON consumers may only be able to process the sequences with the 'signatures' array, so pass a 'supportFlattened' flag to JwsJsonProducer if needed. 

...

Once you have decided which key and content encryption algorithms need to be supported you can initialize JwsEncryptionProvider and JwsDecryptionProvider which do the actual JWE encryption/decryption work by coordinating with the key and content encryption providers. CXF ships JweEncryption (JwsEncryptionProvider) and JweDecryption (JweDecryptionProvider) helpers, simply pass them the preferred key and content encryption providers and have the content encrypted or decrypted.

JweEncryption and JweDecryption help with creating and processing JWE Compact sequences (see the next section).  JweEncryption can also help with streaming JWE JSON sequences (see JAX-RS JWE filters section).

Note that AesCbcHmacJweEncryption and AesCbcHmacJweDecryption providers supporting AES_CBC_HMAC_SHA2 contet encryption are extending JweEncryption and JweDecryption respectively. They implement the content encryption internally but do accept preferred key encryption/decryption providers.

...

JweCompactProducer and JweCompactConsumer offer a basic support for creating and consuming compact JWE sequences. In most cases you will likely prefer to use JweEncryption ( and JweDecryption instead: JweEncryption uses JweCompactProducer internally when its encrypt method is called (getEncryptedOutput will be discussed in the JAX-RS JWE filters section), and JweDecryption ( accepts only JWE Compact and uses JweCompactConsumer internally).

JweJwtCompactProducer and JwsJwtCompactConsumer help with directly encrypting typed JWT Tokens.

Here is the example of doing AES Key Wrap and AES CBC HMAC and AES Key Wrap in CXF:

Code Block
languagejava
titleCXF Jwe AesWrapAesCbcHMac
final String specPlainText = "Live long and prosper.";
        
byte[]AesWrapKeyEncryptionAlgorithm cekEncryptionKeykeyEncryption = Base64UrlUtility.decodenew AesWrapKeyEncryptionAlgorithm(KEY_ENCRYPTION_KEY_A3);
        
AesWrapKeyEncryptionAlgorithm keyEncryption = new AesWrapKeyEncryptionAlgorithm(cekEncryptionKey, KeyAlgorithm.A128KW);
JweEncryptionProvider encryption = new AesCbcHmacJweEncryption(ContentAlgorithm.A128CBC_HS256,
                                                               keyEncryption);
String jweContent = encryption.encrypt(specPlainText.getBytes("UTF-8"), null);
        
AesWrapKeyDecryptionAlgorithm keyDecryption = new AesWrapKeyDecryptionAlgorithm(cekEncryptionKey);
JweDecryptionProvider decryption = new AesCbcHmacJweDecryption(keyDecryption);
String decryptedText = decryption.decrypt(jweContent).getContentText();
assertEquals(specPlainText, decryptedText);

 

...

Here is another example using RSA-OAEP key encryption and AES-GCM content encryption:

Code Block
languagejava
titleCXF Jwe RsaOaepAesGcm
final String content = "Live long and prosper.";
// Load public RSA key from the JWK Key set stored on the disk
InputStream is = JsonWebKeyTest.class.getResourceAsStream(fileName);
JsonWebKeys keySet = JwkUtils.readJwkSet(is);
JsonWebKey jwkPublicRsaKey = keySet.getKey("Public RSA Key");
KeyEncryptionProvider keyEncryptionAlgo = JweUtils.getKeyEncryptionProvider(jwkPublicRsaKey); 
ContentEncryptionProvider contentEncryptionAlgo = JweUtils.getContentEncryptionProvider(ContentAlgorithm.A256GCM);
JweEncryptionProvider encryptor = new JweEncryption(keyEncryptionAlgo, contentEncryptionAlgo);

// or simply
// JweEncryptionProvider encryptor = JweUtils.createJweEncryptionProvider(jwkPublicRsaKey, ContentAlgorithm.A256GCM);

String jweOut = encryptor.encrypt(content.getBytes(StandardCharsets.UTF_8), null); 

// Load Private RSA Key from Java JKS Store
PrivateKey privateRsaKey = 
    CryptoUtils.loadPrivateKey(keyStoreLocation, keyStorePassword, privateKeyPassword, keyAlias, KeyStore.getDefaultType());

JweDecryptionProvider decryptor = JweUtils.createJweDecryptionProvider(jwkPrivateRsaKey, ContentAlgorithm.A256GCM);
String decryptedText = decryption.decrypt(jweContent).getContentText();
assertEquals(content, decryptedText);

JWE JSON

While JWE Compact is optimized and represents a concatenation of 5 Base64URL values, JWE JSON is an open JSON container, see Appendix A4.

The most interesting feature of JWE JSON is that allows a content be encrypted by multiple key encryption keys, with te resulting sequence targeted at multiple recipients. For example,  the immediate consumer will decrypt the content with its own key decryption key, forward the payload to the next consumer, etc.  

JweJsonProducer and JweJsonConsumer support producing and consuming JWS JSON sequences.

Here is the code example:

Code Block
languagejava
titleCXF JweJson
final String text = "The true sign of intelligence is not knowledge but imagination.";
SecretKey wrapperKey1 = CryptoUtils.createSecretKeySpec(WRAPPER_BYTES1, "AES");
SecretKey wrapperKey2 = CryptoUtils.createSecretKeySpec(WRAPPER_BYTES2, "AES");
        
JweHeaders protectedHeaders = new JweHeaders(ContentAlgorithm.A128GCM);
JweHeaders sharedUnprotectedHeaders = new JweHeaders();
sharedUnprotectedHeaders.setJsonWebKeysUrl("https://server.example.com/keys.jwks");
sharedUnprotectedHeaders.setKeyEncryptionAlgorithm(KeyAlgorithm.A128KW);
        
ContentEncryptionProvider contentEncryption = JweUtils.getContentEncryptionProvider(ContentAlgorithm.A128GCM);
        
KeyEncryptionProvider keyEncryption1 = JweUtils.getSecretKeyEncryptionAlgorithm(wrapperKey1, KeyAlgorithm.A128KW);
JweEncryptionProvider jweEnc1 = new JweEncryption(keyEncryption1, contentEncryption);

KeyEncryptionProvider keyEncryption2 = JweUtils.getSecretKeyEncryptionAlgorithm(wrapperKey2, KeyAlgorithm.A128KW);
JweEncryptionProvider jweEnc2 = new JweEncryption(keyEncryption2, contentEncryption);

List<JweEncryptionProvider> jweList = new LinkedList<JweEncryptionProvider>();
jweList.add(jweEnc1);
jweList.add(jweEnc2);
        
JweJsonProducer p = new JweJsonProducer(protectedHeaders,
                                        sharedUnprotectedHeaders,
                                        StringUtils.toBytesUTF8(text),
                                        StringUtils.toBytesUTF8(EXTRA_AAD_SOURCE),
                                        false);
String jweJsonOut = p.encryptWith(jweList);

// first consumer:
JweDecryptionProvider jweDecrypt = JweUtils.createJweDecryptionProvider(wrapperKey1, 
                                                                 KeyAlgorithm.A128KW, 
                                                                 ContentAlgorithm.A128GCM);
JweJsonConsumer c = new JweJsonConsumer(jweJsonOut);
// the consumer will iterate over JWE entries and will try to find the one which can be decrypted with this decryptor
// which is always precise if only a single receipient entry is available
// or do consumer.getRecipientsMap() returning a list of entries and their metadata to do a more precise selection.

String content = consumer.decryptWith(jweDecrypt).getContent();

If the sequence contains a single recipient entry only then the JWE JSON 'recipients' array will contain a single entry, or the whole sequence can be flattened instead with the actual 'recipients' array dropped. JweJsonProducer  does not produce the flattened sequence when only a single encryption is done by default because 3rd party JWE JSON consumers may only be able to process the sequences with the 'recipients' array, so pass a 'canBeFlat' flag to JwEJsonProducer if needed

Does it make sense to use JWE JSON if you do not plan to do multiple encryptions ? Most likely you will prefer JWE Compact if only a single recipient is targeted.

JSON Web Token

JWT (JSON Web Token) is a collection of claims in JSON format. It offers a standard JSON container for representing various properties or claims.

...