Files
skills/docs/security-stack/crypto/crypto-rsa/src/jwk/thumbprint.md
2026-05-29 08:20:56 +01:00

2.9 KiB

jwk/thumbprint

Purpose

Compute the JWK Thumbprint of an RSA public key per RFC 7638 §3.2. The thumbprint is a deterministic hash over the canonical JSON form of the public-key members (e, kty, n in alphabetical order with no whitespace), giving every RSA key a stable identifier independent of its wire format. Used downstream for kid derivation, key rotation diffing, and key-pinning protocols.

Features

  • RFC 7638 §3.2 conformant — RSA member ordering e, kty, n
  • Default SHA-256 hash; SHA-1 / SHA-384 / SHA-512 supported via hash option
  • Accepts both canonical RsaPublicKey and RsaJwk shapes
  • Hand-built canonical JSON byte string (does NOT use JSON.stringify — member order is implementation-defined for that API)
  • Worked-example matched against the RFC 7638 §3.1 reference value "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs"
  • jwkThumbprintBase64Url convenience returns the URL-safe base64 encoding directly
  • All thrown errors are CryptoRsaError with INVALID_KEY / UNSUPPORTED_HASH

Usage: Basic Example

import { jwkThumbprint } from "@suaveplan/crypto-rsa/jwk";

const fingerprint = jwkThumbprint(publicKey);
// 32 bytes (SHA-256 default)

Usage: Advanced Example

The kid JWK member is conventionally set to the base64url-encoded SHA-256 thumbprint. Combine jwkThumbprintBase64Url with serializeRsaPublicKeyJwk to populate it on emit:

import {
    jwkThumbprintBase64Url,
    serializeRsaPublicKeyJwk,
} from "@suaveplan/crypto-rsa";

const baseJwk = serializeRsaPublicKeyJwk(publicKey);
const jwkWithKid = {
    ...baseJwk,
    kid: jwkThumbprintBase64Url(publicKey),
};

API Reference

jwkThumbprint(key, options?)

  • key: RsaPublicKey | RsaJwk — public key or JWK
  • options.hash?: RsaHashAlgorithm — defaults to "SHA-256"
  • returns Uint8Array — digest bytes
  • throws CryptoRsaError(CRYPTO_RSA.UNSUPPORTED_HASH) on bad hash; CRYPTO_RSA.INVALID_KEY on missing e or n

jwkThumbprintBase64Url(key, options?)

Convenience: returns toBase64Url(jwkThumbprint(key, options)).

JwkThumbprintOptions

  • hash?: RsaHashAlgorithm

Implementation Notes

  • The canonical JSON byte string is '{"e":"<b64u(e)>","kty":"RSA","n":"<b64u(n)>"}'. Members are alphabetically ordered per RFC 7638 §3.2; only the three required members participate in the digest.
  • JSON.stringify is NOT used because member-order in object iteration is implementation-defined for non-integer keys; constructing the byte string by hand is the only correctness-stable approach.
  • When the input is a RsaPublicKey (canonical bigint form), the implementation routes through serializeRsaPublicKeyJwk to obtain the base64url members, then concatenates the canonical JSON shape.
  • Hash algorithm validation runs BEFORE member-validity checks so consumers see UNSUPPORTED_HASH on bad hashes regardless of key validity — useful for fail-fast configuration validators.