JSON Web Token (JWT) with ES256K (secp256k1) signature

Support for EC DSA signatures on the secp256k1 curve, which is used in Bitcoin and Ethereum, was added in version 5.9 of the Nimbus JOSE+JWT library.

  • JWS algorithm: ES256K
  • JWK curve name: P-256K

Note that while the secp256k1 curve itself is standard, the above names for the JWS algorithm and curve are not (yet) included in the JOSE algorithm registry.

If you need to generate an EC key pair on the secp256k1 curve:

import java.security.*;
import java.security.interfaces.*;
import com.nimbusds.jose.jwk.*;
import com.nimbusds.jose.jwk.gen.*;

// Generate EC key pair
ECKey ecJWK = new ECKeyGenerator(Curve.P_256K)
    .keyID("123")
    .generate();

// Get the public EC key, used by recipients to validate the signatures
ECKey ecPublicJWK = ecJWK.toPublicJWK();

To sign a JWT with ES256K on the secp256k1 curve:

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


// Sample JWT claims
JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
    .subject("alice")
    .build();

// Create JWT for ES256K alg
SignedJWT jwt = new SignedJWT(
    new JWSHeader.Builder(JWSAlgorithm.ES256K).keyID(ecJWK.getKeyID()).build(),
    claimsSet);

// Sign with private EC key
jwt.sign(new ECDSASigner(ecJWK));

// Output the JWT
System.out.println(jwt.serialize());

// With line break for clarity:
// eyJhbGciOiJFUzI1NksifQ.eyJzdWIiOiJhbGljZSJ9.iLSiShv3BXI_s7CYioHw5I8GWbsfDWvQ
// uhh-M7t_A_G4PDhmv_R2snWUjeZS5224dSuUM2WOfgoT_Ww38aDmXg

To validate the ES256K signature:

import java.security.interfaces.*;
import com.nimbusds.jose.crypto.*;
import com.nimbusds.jwt.*;


// Parse signed JWT
SignedJWT jwt = SignedJWT.parse("eyJhbGciOiJFUzI1NksifQ.eyJzdWIiOiJhbGljZSJ9.iLSiShv3BXI_s7CYioHw5I8GWbsfDWvQuhh-M7t_A_G4PDhmv_R2snWUjeZS5224dSuUM2WOfgoT_Ww38aDmXg");

// Verify the ES256K signature with the public EC key
assertTrue(jwt.verify(new ECDSAVerifier(ecPublicJWK)));

// Output the JWT claims: {"sub":"alice"}
System.out.println(jwt.getJWTClaimsSet().toJSONObject());