Direct JSON Web Encryption (JWE) with a shared symmetric key

The simplest kind of JSON Web Encryption (JWE) is direct encryption with a symmetric AES key, hence the algorithm designation dir. Sender and recipient must share the same secret key, established by some out-of-band mechanism, unless you have a use case where the plain text is encrypted to self.

If you need public (asymmetric) key encryption, check out the available RSA and ECDH algorithms for JWE.

Direct encryption works with any of the six standard available content encryption algorithms (set by the "enc" JWE header parameter). These are grouped into two classes authenticated encryption with AES/CBC/HMAC/SHA and authenticated encryption with AES/GCM.

The AES key length must match the expected for the selected JWE encryption. If that condition isn't met the library will throw a JOSE exception when encryption is attempted.

Content encryption class JWE enc identifier Key bitlength
A192CBC-HS384 384
A256CBC-HS512 512
A128CBC+HS256 (deprecated) 256
A256CBC+HS512 (deprecated) 512
A192GCM 192
A256GCM 256

The required AES key length for a particular JWE encryption method can also be obtained programmatically:

// Get the expected key length for JWE enc "A128CBC-HS256"
int keyBitLength = EncryptionMethod.A128CBC_HS256.cekBitLength();

// Generate key
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
SecretKey key = keyGen.generateKey();

Example direct encryption with AES GCM using a symmetric 128 bit key:

import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.*;

// Generate symmetric 128 bit AES key
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
SecretKey key = keyGen.generateKey();

// Create the header
JWEHeader header = new JWEHeader(JWEAlgorithm.DIR, EncryptionMethod.A128GCM);

// Set the plain text
Payload payload = new Payload("Hello world!");

// Create the JWE object and encrypt it
JWEObject jweObject = new JWEObject(header, payload);
jweObject.encrypt(new DirectEncrypter(key));

// Serialise to compact JOSE form...
String jweString = jweObject.serialize();

// Parse into JWE object again...
jweObject = JWEObject.parse(jweString);

// Decrypt
jweObject.decrypt(new DirectDecrypter(key);

// Get the plain text
payload = jweObject.getPayload();
assertEquals("Hello world!", payload.toString());


Don't forget to refer to the security considerations on key lifetimes in section 8.2 and AES GCM in section 8.4 of the JSON Web Algorithm (JWA) spec when using direct encryption.