Direct JWE encryption

Release 2.14 of the Nimbus JOSE + JWT library adds support for direct JWE encryption using shared symmetric keys. Our particular use case for that is to secure the transfer of identity data between an on-premise user authentication agent and an OpenID Connect provider service that we’re currently developing.

Direct JWE encryption comes in handy when you have control over both communication endpoints and wish to save the overhead of issuing public / private key pairs, such as RSA, and then wrapping / unwrapping them for the actual encryption / decryption.

Direct encryption is represented by setting the algorithm (alg) header parameter to dir and then specifying the actual encryption method to apply on the plain text, e.g. 128-bit AES/GCM:

{ "alg":"dir", "enc":"A128GCM" }

Programmaticaly you can create the header like this:

import com.nimbusds.jose.*;
JWEHeader header = new JWEHeader(JWEAlgorithm.DIR, EncryptionMethod.A128GCM);

You can then complete the JWE object construction:

JWEObject jweObj = new JWEObject(header, new Payload("Hello world!"));

To encrypt the JWE object you need a key with the matching length for A128GCM encryption, that is 128 bits or 16 bytes. The key must be shared between sender and recipient and kept secret, of course.

import com.nimbusds.jose.crypto.*;

byte[16] key = { ... };
DirectEncrypter encrypter = new DirectEncrypter(key);

// You can now use the encrypter on one or more JWE objects
// that you wish to secure
jweObject.encrypt(encrypter);
String jweString = jweObject.serialize();

The resulting JWE object string will then look similar to this:

eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..0CxTyOgMw0nsG-KS.BJkGEk8LW3qOOU6v.dkNwv-fbQOgoOuYr6Kg74g

Notice that the encrypted key part (the second part) of the JWE string is missing. RSA and ECC encryption will have it, but direct encryption not.

To decrypt the JWE string on the other end you need the same symmetric key.

jweObject = JWEObject.parse(jweString);
JWEDecrypter decrypter = new DirectDecrypter(key);
jweObject.decrypt(decrypter);

// Prints "Hello world!"
System.out.println(jweObject.getPayload());

The Nimbus JOSE + JWT library supports all standard encryption methods for direct JWE:

  • A128CBC+HS256 – requires 256 bit symmetric key
  • A256CBC+HS512 – requires 512 bit symmetric key
  • A128GCM – requires 128 bit symmetric key
  • A256GCM – requires 256 bit symmetric key