Skip to content
ecdsa.com

JWK thumbprint · Java

How to compute a JWK thumbprint (RFC 7638) in Java

In Java, Nimbus JOSE + JWT computes a JWK thumbprint with JWK.computeThumbprint(), for keys parsed from JWK JSON or from PEM, and returns the RFC 9278 URI form with computeThumbprintURI(). The run reproduces the published RFC 7638 and RFC 8037 thumbprints.

Tested with com.nimbusds:nimbus-jose-jwt 10.10 (OpenJDK 25.0.4.1 (Temurin)) and org.bouncycastle:bcpkix-jdk18on 1.86 (PEM parsing for JWK.parseFromPEMEncodedObjects).

Thumbprint.java — RFC 7638 thumbprints from JWK files and PEM keys with Nimbus
import com.nimbusds.jose.jwk.JWK;
import java.nio.file.Files;
import java.nio.file.Path;
public class Thumbprint {
public static void main(String[] args) throws Exception {
// From a JWK: computeThumbprint() hashes the required members only (SHA-256)
for (String file : new String[] {"ec.jwk.json", "rsa.jwk.json", "okp.jwk.json"}) {
JWK jwk = JWK.parse(Files.readString(Path.of(file)));
System.out.println(file + ": " + jwk.computeThumbprint());
}
// From a PEM public key (this parser needs Bouncy Castle's bcpkix on the class path)
for (String file : new String[] {"ec.pub.pem", "rsa.pub.pem"}) {
JWK jwk = JWK.parseFromPEMEncodedObjects(Files.readString(Path.of(file)));
System.out.println(file + ": " + jwk.computeThumbprint());
}
System.out.println(JWK.parse(Files.readString(Path.of("ec.jwk.json"))).computeThumbprintURI()); // RFC 9278
}
}

How it works

  1. JWK.parse(json) returns an ECKey, RSAKey or OctetKeyPair; kid, use and alg are kept but play no part in the thumbprint.
  2. computeThumbprint() uses SHA-256 and returns a Base64URL whose toString() is the thumbprint; computeThumbprint("SHA-384") selects another hash.
  3. JWK.parseFromPEMEncodedObjects(pem) reads PEM public keys, private keys and certificates.
  4. computeThumbprintURI() gives the RFC 9278 urn:ietf:params:oauth:jwk-thumbprint:sha-256:… form.

Gotchas

  • parseFromPEMEncodedObjects needs Bouncy Castle (bcpkix-jdk18on, with bcprov and bcutil) on the class path; without it the call fails with NoClassDefFoundError: org/bouncycastle/openssl/jcajce/JcaPEMKeyConverter. Nimbus declares these dependencies as optional.
  • That PEM parser reads RSA and EC keys only: an Ed25519 PEM fails with JOSEException: Unsupported algorithm of PEM-encoded key: EdDSA. Read Ed25519 keys with the JDK (KeyFactory.getInstance("Ed25519")) and build an OctetKeyPair from the 32 raw bytes.
  • A common kid choice is the thumbprint itself: new ECKey.Builder(…).keyIDFromThumbprint().build() sets it in one step.
  • computeThumbprint() on a private JWK gives the same value as on its public part — useful, but publish jwk.toPublicJWK(), never the private JWK.

Related recipes