JJWT API - JSON Web Token library API for Java and Android
—
This document covers key management, JSON Web Key (JWK) support, and cryptographic algorithm interfaces in JJWT API.
The Keys class provides utilities for key generation and secure key management.
public final class Keys {
// HMAC Key Generation
public static SecretKey hmacShaKeyFor(byte[] bytes);
// Key Generation (deprecated but available)
@Deprecated
public static SecretKey secretKeyFor(SignatureAlgorithm alg);
@Deprecated
public static KeyPair keyPairFor(SignatureAlgorithm alg);
// Password Creation
public static Password password(char[] password);
// Key Builders
public static SecretKeyBuilder builder(SecretKey key);
public static PrivateKeyBuilder builder(PrivateKey key);
}import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.Jwts;
import javax.crypto.SecretKey;
// Generate secure keys for different algorithms
SecretKey hs256Key = Keys.secretKeyFor(Jwts.SIG.HS256);
SecretKey hs384Key = Keys.secretKeyFor(Jwts.SIG.HS384);
SecretKey hs512Key = Keys.secretKeyFor(Jwts.SIG.HS512);
// Generate encryption keys
SecretKey aes128Key = Keys.secretKeyFor(Jwts.ENC.A128GCM);
SecretKey aes256Key = Keys.secretKeyFor(Jwts.ENC.A256GCM);
// Create key from existing bytes (must be appropriate length)
byte[] keyBytes = new byte[32]; // 256 bits for HS256
new SecureRandom().nextBytes(keyBytes);
SecretKey hmacKey = Keys.hmacShaKeyFor(keyBytes);
// Create password for PBES2 algorithms
char[] passwordChars = "mySecurePassword".toCharArray();
Password password = Keys.password(passwordChars);The Jwks class provides comprehensive JSON Web Key (JWK) support including creation, parsing, and management.
public final class Jwks {
// JWK Factory Methods
public static DynamicJwkBuilder<?, ?> builder();
public static JwkParserBuilder parser();
public static JwkSetBuilder set();
public static JwkSetParserBuilder setParser();
// JSON Conversion
public static String json(PublicJwk<?> publicJwk);
public static String UNSAFE_JSON(Jwk<?> jwk);
// Standard Curves
public static final class CRV {
public static final Curve P256;
public static final Curve P384;
public static final Curve P521;
public static final Curve Ed25519;
public static final Curve Ed448;
public static final Curve X25519;
public static final Curve X448;
}
// Standard Hash Algorithms
public static final class HASH {
public static final HashAlgorithm SHA256;
public static final HashAlgorithm SHA384;
public static final HashAlgorithm SHA512;
public static final HashAlgorithm SHA3_256;
public static final HashAlgorithm SHA3_384;
public static final HashAlgorithm SHA3_512;
}
// Standard Key Operations
public static final class OP {
public static final KeyOperation SIGN;
public static final KeyOperation VERIFY;
public static final KeyOperation ENCRYPT;
public static final KeyOperation DECRYPT;
public static final KeyOperation WRAP_KEY;
public static final KeyOperation UNWRAP_KEY;
public static final KeyOperation DERIVE_KEY;
public static final KeyOperation DERIVE_BITS;
}
}public interface Jwk<K extends Key> extends Map<String, Object> {
// Standard Parameters
String getId();
String getType();
Set<KeyOperation> getOperations();
String getAlgorithm();
String getPublicKeyUse();
// X.509 Certificate Chain
Set<String> getX509CertificateChain();
String getX509CertificateSha1Thumbprint();
String getX509CertificateSha256Thumbprint();
// Key Conversion
K toKey();
// Standard Parameter Names
String TYPE = "kty";
String PUBLIC_KEY_USE = "use";
String KEY_OPERATIONS = "key_ops";
String ALGORITHM = "alg";
String KEY_ID = "kid";
String X509_CERTIFICATE_CHAIN = "x5c";
String X509_CERTIFICATE_SHA1_THUMBPRINT = "x5t";
String X509_CERTIFICATE_SHA256_THUMBPRINT = "x5t#S256";
}// Symmetric Key JWK
public interface SecretJwk extends Jwk<SecretKey> {
// Inherits all Jwk methods
}
// Public Key JWK Base
public interface PublicJwk<K extends PublicKey> extends Jwk<K> {
// Inherits all Jwk methods
}
// Private Key JWK Base
public interface PrivateJwk<K extends PrivateKey, L extends PublicJwk<? extends PublicKey>, M extends KeyPair<? extends PublicKey, K>> extends Jwk<K> {
L toPublicJwk();
M toKeyPair();
}
// RSA JWKs
public interface RsaPublicJwk extends PublicJwk<RSAPublicKey>, AsymmetricJwk<RSAPublicKey, RSAPrivateKey> {
// RSA-specific methods
}
public interface RsaPrivateJwk extends PrivateJwk<RSAPrivateKey, RsaPublicJwk, KeyPair<RSAPublicKey, RSAPrivateKey>>, AsymmetricJwk<RSAPublicKey, RSAPrivateKey> {
// RSA private key specific methods
}
// EC JWKs
public interface EcPublicJwk extends PublicJwk<ECPublicKey>, AsymmetricJwk<ECPublicKey, ECPrivateKey> {
Curve getCurve();
}
public interface EcPrivateJwk extends PrivateJwk<ECPrivateKey, EcPublicJwk, KeyPair<ECPublicKey, ECPrivateKey>>, AsymmetricJwk<ECPublicKey, ECPrivateKey> {
Curve getCurve();
}
// Octet Key Pair JWKs (Ed25519, Ed448, X25519, X448)
public interface OctetPublicJwk<K extends PublicKey> extends PublicJwk<K> {
Curve getCurve();
}
public interface OctetPrivateJwk<K extends PrivateKey, L extends OctetPublicJwk<? extends PublicKey>> extends PrivateJwk<K, L, KeyPair<? extends PublicKey, K>> {
Curve getCurve();
}public interface DynamicJwkBuilder<K extends Key, J extends Jwk<K>> extends JwkBuilder<K, J> {
// Auto-detects key type and provides appropriate builder
DynamicJwkBuilder<K, J> key(K key);
}// Secret JWK Builder
public interface SecretJwkBuilder extends JwkBuilder<SecretKey, SecretJwk> {
SecretJwkBuilder key(SecretKey key);
}
// RSA JWK Builders
public interface RsaPublicJwkBuilder extends AsymmetricJwkBuilder<RSAPublicKey, RSAPrivateKey, RsaPublicJwk, RsaPublicJwkBuilder> {
RsaPublicJwkBuilder key(RSAPublicKey key);
}
public interface RsaPrivateJwkBuilder extends PrivateJwkBuilder<RSAPrivateKey, RsaPublicJwk, KeyPair<RSAPublicKey, RSAPrivateKey>, RsaPrivateJwk, RsaPrivateJwkBuilder> {
RsaPrivateJwkBuilder key(RSAPrivateKey key);
}
// EC JWK Builders
public interface EcPublicJwkBuilder extends AsymmetricJwkBuilder<ECPublicKey, ECPrivateKey, EcPublicJwk, EcPublicJwkBuilder> {
EcPublicJwkBuilder key(ECPublicKey key);
EcPublicJwkBuilder curve(Curve curve);
}
public interface EcPrivateJwkBuilder extends PrivateJwkBuilder<ECPrivateKey, EcPublicJwk, KeyPair<ECPublicKey, ECPrivateKey>, EcPrivateJwk, EcPrivateJwkBuilder> {
EcPrivateJwkBuilder key(ECPrivateKey key);
EcPrivateJwkBuilder curve(Curve curve);
}import io.jsonwebtoken.security.Jwks;
import io.jsonwebtoken.security.RsaPrivateJwk;
import io.jsonwebtoken.security.EcPublicJwk;
import java.security.KeyPairGenerator;
import java.security.KeyPair;
// Generate RSA key pair
KeyPairGenerator rsaGenerator = KeyPairGenerator.getInstance("RSA");
rsaGenerator.initialize(2048);
KeyPair rsaKeyPair = rsaGenerator.generateKeyPair();
// Create RSA private JWK
RsaPrivateJwk rsaJwk = Jwks.builder()
.key(rsaKeyPair.getPrivate())
.keyId("rsa-key-1")
.algorithm("RS256")
.operations(Jwks.OP.SIGN)
.build();
// Create EC public JWK
KeyPairGenerator ecGenerator = KeyPairGenerator.getInstance("EC");
ecGenerator.initialize(256);
KeyPair ecKeyPair = ecGenerator.generateKeyPair();
EcPublicJwk ecJwk = Jwks.builder()
.key((ECPublicKey) ecKeyPair.getPublic())
.keyId("ec-key-1")
.curve(Jwks.CRV.P256)
.operations(Jwks.OP.VERIFY)
.build();
// Convert JWK to JSON (safe for public keys)
String rsaPublicJson = Jwks.json(rsaJwk.toPublicJwk());
String ecPublicJson = Jwks.json(ecJwk);
// Convert to Java Key
RSAPrivateKey rsaPrivateKey = rsaJwk.toKey();
ECPublicKey ecPublicKey = ecJwk.toKey();public interface JwkSet extends Map<String, Object> {
Set<Jwk<?>> getKeys();
// Standard Parameter Names
String KEYS = "keys";
}public interface JwkSetBuilder extends Builder<JwkSet> {
JwkSetBuilder add(Jwk<?> jwk);
JwkSetBuilder add(Collection<? extends Jwk<?>> jwks);
JwkSetBuilder keys(Collection<? extends Jwk<?>> jwks);
JwkSet build();
}import io.jsonwebtoken.security.JwkSet;
import io.jsonwebtoken.security.Jwks;
// Create JWK Set with multiple keys
JwkSet jwkSet = Jwks.set()
.add(rsaJwk.toPublicJwk())
.add(ecJwk)
.build();
// Convert to JSON
String jwkSetJson = Jwks.json(jwkSet);
// Access keys
Set<Jwk<?>> keys = jwkSet.getKeys();
for (Jwk<?> jwk : keys) {
System.out.println("Key ID: " + jwk.getId());
System.out.println("Key Type: " + jwk.getType());
}public interface JwkParserBuilder extends Builder<JwkParser> {
JwkParserBuilder provider(Provider provider);
JwkParserBuilder deserializer(Deserializer<Map<String, ?>> deserializer);
JwkParser build();
}public interface JwkSetParserBuilder extends Builder<JwkSetParser> {
JwkSetParserBuilder provider(Provider provider);
JwkSetParserBuilder deserializer(Deserializer<Map<String, ?>> deserializer);
JwkSetParser build();
}import io.jsonwebtoken.security.Jwks;
import io.jsonwebtoken.security.Jwk;
import io.jsonwebtoken.security.JwkSet;
// Parse single JWK from JSON
String jwkJson = "{ \"kty\": \"RSA\", \"kid\": \"key1\", ... }";
Jwk<?> parsedJwk = Jwks.parser()
.build()
.parse(jwkJson);
// Parse JWK Set from JSON
String jwkSetJson = "{ \"keys\": [ { \"kty\": \"RSA\", ... }, { \"kty\": \"EC\", ... } ] }";
JwkSet parsedJwkSet = Jwks.parser()
.build()
.parseSet(jwkSetJson);
// Access parsed keys
for (Jwk<?> jwk : parsedJwkSet.getKeys()) {
System.out.println("Parsed key: " + jwk.getId());
}public interface SignatureAlgorithm extends SecureDigestAlgorithm<PrivateKey, PublicKey>, KeyPairBuilderSupplier {
// Digital signature algorithms (RS256, PS256, ES256, EdDSA, etc.)
}
public interface MacAlgorithm extends SecureDigestAlgorithm<SecretKey, SecretKey>, KeyBuilderSupplier<SecretKey> {
// Message Authentication Code algorithms (HS256, HS384, HS512)
}public interface AeadAlgorithm extends Identifiable {
// Authenticated Encryption with Associated Data
String getId();
// AEAD Operations
AeadResult encrypt(AeadRequest request) throws SecurityException;
DecryptAeadRequest decrypt(DecryptAeadRequest request) throws SecurityException;
}
public interface KeyAlgorithm<E extends Key, D extends Key> extends Identifiable {
// Key Management Algorithms
String getId();
// Key Management Operations
KeyResult getEncryptionKey(KeyRequest<E> request) throws SecurityException;
SecretKey getDecryptionKey(DecryptionKeyRequest<D> request) throws SecurityException;
}import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.SignatureAlgorithm;
import io.jsonwebtoken.security.MacAlgorithm;
// Use specific algorithms
SignatureAlgorithm rs256 = Jwts.SIG.RS256;
MacAlgorithm hs256 = Jwts.SIG.HS256;
// Generate appropriate keys for algorithms
RSAPrivateKey rsaKey = rs256.keyPair().build().getPrivate();
SecretKey macKey = hs256.key().build();
// Use in JWT operations
String rsaJwt = Jwts.builder()
.subject("user")
.signWith(rsaKey, rs256)
.compact();
String macJwt = Jwts.builder()
.subject("user")
.signWith(macKey, hs256)
.compact();public class SecurityException extends JwtException {
// Base security exception
}
public class KeyException extends SecurityException {
// General key-related errors
}
public class InvalidKeyException extends KeyException {
// Invalid key format or content
}
public class WeakKeyException extends KeyException {
// Key strength insufficient for algorithm
}
public class UnsupportedKeyException extends KeyException {
// Key type not supported for operation
}
public class MalformedKeyException extends KeyException {
// Key format is malformed
}
public class MalformedKeySetException extends SecurityException {
// JWK Set format is malformed
}
public class SignatureException extends SecurityException {
// Signature operation failed
}JJWT automatically validates key strength according to JWA specifications:
// These will throw WeakKeyException if keys are too short
SecretKey weakKey = Keys.hmacShaKeyFor(new byte[16]); // Only 128 bits for HS256
SecretKey strongKey = Keys.hmacShaKeyFor(new byte[32]); // 256 bits - OK
// Automatic validation during JWT creation
try {
String jwt = Jwts.builder()
.subject("user")
.signWith(weakKey, Jwts.SIG.HS256) // May throw WeakKeyException
.compact();
} catch (WeakKeyException e) {
System.err.println("Key too weak: " + e.getMessage());
}JJWT supports all standard elliptic curves:
// NIST P-curves
Curve p256 = Jwks.CRV.P256; // secp256r1
Curve p384 = Jwks.CRV.P384; // secp384r1
Curve p521 = Jwks.CRV.P521; // secp521r1
// Edwards curves
Curve ed25519 = Jwks.CRV.Ed25519; // EdDSA signing
Curve ed448 = Jwks.CRV.Ed448; // EdDSA signing
// Montgomery curves
Curve x25519 = Jwks.CRV.X25519; // ECDH key agreement
Curve x448 = Jwks.CRV.X448; // ECDH key agreementAll security operations support custom JCA Providers:
Provider customProvider = new CustomSecurityProvider();
// Use custom provider for key generation
SecretKey key = Keys.builder(existingKey)
.provider(customProvider)
.build();
// Use custom provider for JWT operations
String jwt = Jwts.builder()
.provider(customProvider)
.subject("user")
.signWith(key)
.compact();
// Use custom provider for parsing
JwtParser parser = Jwts.parser()
.provider(customProvider)
.verifyWith(key)
.build();Install with Tessl CLI
npx tessl i tessl/maven-io-jsonwebtoken--jjwt-api