Skip to content
Connect2id

JWS with HMAC protection

This is an example how to create and verify a JWS encoded object with a hash-based message authentication code (HMAC). The producer and consumer must posses a shared secret, negotiated through some out-of-band mechanism before the JWS-protected object is communicated (unless the producer secures the JWS object for itself).

The payload is a simple “Hello, world!” string but can also be a JSON string or BASE64URL encoded data.

The Nimbus JOSE+JWT library supports all standard JWS algorithms for HMAC protection (note the minimum secret length requirement):

  • HS256 - HMAC with SHA-256, requires 256+ bit secret
  • HS384 - HMAC with SHA-384, requires 384+ bit secret
  • HS512 - HMAC with SHA-512, requires 512+ bit secret

Example code:

import java.security.SecureRandom;

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


// Generate random 256-bit (32-byte) shared secret
SecureRandom random = new SecureRandom();
byte[] sharedSecret = new byte[32];
random.nextBytes(sharedSecret);

// Create HMAC signer
JWSSigner signer = new MACSigner(sharedSecret);

// Prepare JWS object with "Hello, world!" payload
JWSObject jwsObject = new JWSObject(new JWSHeader(JWSAlgorithm.HS256), new Payload("Hello, world!"));

// Apply the HMAC
jwsObject.sign(signer);

// To serialize to compact form, produces something like
// eyJhbGciOiJIUzI1NiJ9.SGVsbG8sIHdvcmxkIQ.onO9Ihudz3WkiauDO2Uhyuz0Y18UASXlSc1eS0NkWyA
String s = jwsObject.serialize();

// To parse the JWS and verify it, e.g. on client-side
jwsObject = JWSObject.parse(s);

JWSVerifier verifier = new MACVerifier(sharedSecret);

assertTrue(jwsObject.verify(verifier));

assertEquals("Hello, world!", jwsObject.getPayload().toString());