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 this 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.*;

KeyPairGenerator gen = KeyPairGenerator.getInstance("EC");
gen.initialize(Curve.P_256K.toECParameterSpec());
KeyPair kp = gen.generateKeyPair();

ECPublicKey publicKey = (ECPublicKey)kp.getPublic();
ECPrivateKey privateKey = (ECPrivateKey)kp.getPrivate();

To export the public EC key in JWK format with an UUID as key ID:

JWK jwk = new ECKey.Builder(Curve.P_256K, publicKey)
    .keyID(UUID.randomUUID().toString())
    .build();

To sign a JWT with ES256K on the secp256k1 curve:

import java.security.interfaces.*;
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(JWSAlgorithm.ES256K), claimsSet);

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

// 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(publicKey)));

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