JSON Web Token (JWT) with EC signature

Elliptic curve based JSON Web Signatures (JWS) provide integrity, authenticity and non-repudation to JSON Web Tokens (JWT).

The EC keys should be of sufficient length to match the required level of security. Note that while EC signatures are shorter than an RSA signature of equivalent strength, they may take more CPU time to verify.

The Nimbus JOSE+JWT library supports all standard EC digital signature algorithms:

  • ES256 - EC P-256 DSA with SHA-256
  • ES384 - EC P-384 DSA with SHA-384
  • ES512 - EC P-521 DSA with SHA-512

The example uses the key ID ("kid") parameter of the JWS header to indicate the signing key and simplify key roll-over. The exact method by which the recipient establishes the public EC key candidate(s) to check the signature must be specified by the application's security protocol.

The JWT includes a set of claims or assertions, packaged in a JSON object. Note that the SignedJWT.verify method only checks the validity of the signature. The claims, which treatment is application specific, must therefore be subsequently checked by your application code.

Example code:

import java.util.Date;

import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.*;
import com.nimbusds.jose.jwk.*;
import com.nimbusds.jose.jwk.gen.*;
import com.nimbusds.jwt.*;


// Generate an EC key pair
ECKey ecJWK = new ECKeyGenerator(Curve.P_256)
    .keyID("123")
    .generate();
ECKey ecPublicJWK = ecJWK.toPublicJWK();

// Create the EC signer
JWSSigner signer = new ECDSASigner(ecJWK);

// Prepare JWT with claims set
JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
    .subject("alice")
    .issuer("https://c2id.com")
    .expirationTime(new Date(new Date().getTime() + 60 * 1000))
    .build();

SignedJWT signedJWT = new SignedJWT(
    new JWSHeader.Builder(JWSAlgorithm.ES256).keyID(ecJWK.getKeyID()).build(),
    claimsSet);

// Compute the EC signature
signedJWT.sign(signer);

// Serialize the JWS to compact form
String s = signedJWT.serialize();

// On the consumer side, parse the JWS and verify its EC signature
signedJWT = SignedJWT.parse(s);

JWSVerifier verifier = new ECDSAVerifier(ecPublicJWK);
assertTrue(signedJWT.verify(verifier));

// Retrieve / verify the JWT claims according to the app requirements
assertEquals("alice", signedJWT.getJWTClaimsSet().getSubject());
assertEquals("https://c2id.com", signedJWT.getJWTClaimsSet().getIssuer());
assertTrue(new Date().before(signedJWT.getJWTClaimsSet().getExpirationTime()));