0
# Security and JWK Management
1
2
This document covers key management, JSON Web Key (JWK) support, and cryptographic algorithm interfaces in JJWT API.
3
4
## Key Utilities - Keys
5
6
The `Keys` class provides utilities for key generation and secure key management.
7
8
```java { .api }
9
public final class Keys {
10
// HMAC Key Generation
11
public static SecretKey hmacShaKeyFor(byte[] bytes);
12
13
// Key Generation (deprecated but available)
14
@Deprecated
15
public static SecretKey secretKeyFor(SignatureAlgorithm alg);
16
@Deprecated
17
public static KeyPair keyPairFor(SignatureAlgorithm alg);
18
19
// Password Creation
20
public static Password password(char[] password);
21
22
// Key Builders
23
public static SecretKeyBuilder builder(SecretKey key);
24
public static PrivateKeyBuilder builder(PrivateKey key);
25
}
26
```
27
28
### Key Generation Examples
29
30
```java
31
import io.jsonwebtoken.security.Keys;
32
import io.jsonwebtoken.Jwts;
33
import javax.crypto.SecretKey;
34
35
// Generate secure keys for different algorithms
36
SecretKey hs256Key = Keys.secretKeyFor(Jwts.SIG.HS256);
37
SecretKey hs384Key = Keys.secretKeyFor(Jwts.SIG.HS384);
38
SecretKey hs512Key = Keys.secretKeyFor(Jwts.SIG.HS512);
39
40
// Generate encryption keys
41
SecretKey aes128Key = Keys.secretKeyFor(Jwts.ENC.A128GCM);
42
SecretKey aes256Key = Keys.secretKeyFor(Jwts.ENC.A256GCM);
43
44
// Create key from existing bytes (must be appropriate length)
45
byte[] keyBytes = new byte[32]; // 256 bits for HS256
46
new SecureRandom().nextBytes(keyBytes);
47
SecretKey hmacKey = Keys.hmacShaKeyFor(keyBytes);
48
49
// Create password for PBES2 algorithms
50
char[] passwordChars = "mySecurePassword".toCharArray();
51
Password password = Keys.password(passwordChars);
52
```
53
54
## JWK Utilities - Jwks
55
56
The `Jwks` class provides comprehensive JSON Web Key (JWK) support including creation, parsing, and management.
57
58
```java { .api }
59
public final class Jwks {
60
// JWK Factory Methods
61
public static DynamicJwkBuilder<?, ?> builder();
62
public static JwkParserBuilder parser();
63
public static JwkSetBuilder set();
64
public static JwkSetParserBuilder setParser();
65
66
// JSON Conversion
67
public static String json(PublicJwk<?> publicJwk);
68
public static String UNSAFE_JSON(Jwk<?> jwk);
69
70
// Standard Curves
71
public static final class CRV {
72
public static final Curve P256;
73
public static final Curve P384;
74
public static final Curve P521;
75
public static final Curve Ed25519;
76
public static final Curve Ed448;
77
public static final Curve X25519;
78
public static final Curve X448;
79
}
80
81
// Standard Hash Algorithms
82
public static final class HASH {
83
public static final HashAlgorithm SHA256;
84
public static final HashAlgorithm SHA384;
85
public static final HashAlgorithm SHA512;
86
public static final HashAlgorithm SHA3_256;
87
public static final HashAlgorithm SHA3_384;
88
public static final HashAlgorithm SHA3_512;
89
}
90
91
// Standard Key Operations
92
public static final class OP {
93
public static final KeyOperation SIGN;
94
public static final KeyOperation VERIFY;
95
public static final KeyOperation ENCRYPT;
96
public static final KeyOperation DECRYPT;
97
public static final KeyOperation WRAP_KEY;
98
public static final KeyOperation UNWRAP_KEY;
99
public static final KeyOperation DERIVE_KEY;
100
public static final KeyOperation DERIVE_BITS;
101
}
102
}
103
```
104
105
## JWK Interfaces
106
107
### Base JWK Interface
108
109
```java { .api }
110
public interface Jwk<K extends Key> extends Map<String, Object> {
111
// Standard Parameters
112
String getId();
113
String getType();
114
Set<KeyOperation> getOperations();
115
String getAlgorithm();
116
String getPublicKeyUse();
117
118
// X.509 Certificate Chain
119
Set<String> getX509CertificateChain();
120
String getX509CertificateSha1Thumbprint();
121
String getX509CertificateSha256Thumbprint();
122
123
// Key Conversion
124
K toKey();
125
126
// Standard Parameter Names
127
String TYPE = "kty";
128
String PUBLIC_KEY_USE = "use";
129
String KEY_OPERATIONS = "key_ops";
130
String ALGORITHM = "alg";
131
String KEY_ID = "kid";
132
String X509_CERTIFICATE_CHAIN = "x5c";
133
String X509_CERTIFICATE_SHA1_THUMBPRINT = "x5t";
134
String X509_CERTIFICATE_SHA256_THUMBPRINT = "x5t#S256";
135
}
136
```
137
138
### Specific JWK Types
139
140
```java { .api }
141
// Symmetric Key JWK
142
public interface SecretJwk extends Jwk<SecretKey> {
143
// Inherits all Jwk methods
144
}
145
146
// Public Key JWK Base
147
public interface PublicJwk<K extends PublicKey> extends Jwk<K> {
148
// Inherits all Jwk methods
149
}
150
151
// Private Key JWK Base
152
public interface PrivateJwk<K extends PrivateKey, L extends PublicJwk<? extends PublicKey>, M extends KeyPair<? extends PublicKey, K>> extends Jwk<K> {
153
L toPublicJwk();
154
M toKeyPair();
155
}
156
157
// RSA JWKs
158
public interface RsaPublicJwk extends PublicJwk<RSAPublicKey>, AsymmetricJwk<RSAPublicKey, RSAPrivateKey> {
159
// RSA-specific methods
160
}
161
162
public interface RsaPrivateJwk extends PrivateJwk<RSAPrivateKey, RsaPublicJwk, KeyPair<RSAPublicKey, RSAPrivateKey>>, AsymmetricJwk<RSAPublicKey, RSAPrivateKey> {
163
// RSA private key specific methods
164
}
165
166
// EC JWKs
167
public interface EcPublicJwk extends PublicJwk<ECPublicKey>, AsymmetricJwk<ECPublicKey, ECPrivateKey> {
168
Curve getCurve();
169
}
170
171
public interface EcPrivateJwk extends PrivateJwk<ECPrivateKey, EcPublicJwk, KeyPair<ECPublicKey, ECPrivateKey>>, AsymmetricJwk<ECPublicKey, ECPrivateKey> {
172
Curve getCurve();
173
}
174
175
// Octet Key Pair JWKs (Ed25519, Ed448, X25519, X448)
176
public interface OctetPublicJwk<K extends PublicKey> extends PublicJwk<K> {
177
Curve getCurve();
178
}
179
180
public interface OctetPrivateJwk<K extends PrivateKey, L extends OctetPublicJwk<? extends PublicKey>> extends PrivateJwk<K, L, KeyPair<? extends PublicKey, K>> {
181
Curve getCurve();
182
}
183
```
184
185
## JWK Builders
186
187
### Dynamic JWK Builder
188
189
```java { .api }
190
public interface DynamicJwkBuilder<K extends Key, J extends Jwk<K>> extends JwkBuilder<K, J> {
191
// Auto-detects key type and provides appropriate builder
192
DynamicJwkBuilder<K, J> key(K key);
193
}
194
```
195
196
### Specific JWK Builders
197
198
```java { .api }
199
// Secret JWK Builder
200
public interface SecretJwkBuilder extends JwkBuilder<SecretKey, SecretJwk> {
201
SecretJwkBuilder key(SecretKey key);
202
}
203
204
// RSA JWK Builders
205
public interface RsaPublicJwkBuilder extends AsymmetricJwkBuilder<RSAPublicKey, RSAPrivateKey, RsaPublicJwk, RsaPublicJwkBuilder> {
206
RsaPublicJwkBuilder key(RSAPublicKey key);
207
}
208
209
public interface RsaPrivateJwkBuilder extends PrivateJwkBuilder<RSAPrivateKey, RsaPublicJwk, KeyPair<RSAPublicKey, RSAPrivateKey>, RsaPrivateJwk, RsaPrivateJwkBuilder> {
210
RsaPrivateJwkBuilder key(RSAPrivateKey key);
211
}
212
213
// EC JWK Builders
214
public interface EcPublicJwkBuilder extends AsymmetricJwkBuilder<ECPublicKey, ECPrivateKey, EcPublicJwk, EcPublicJwkBuilder> {
215
EcPublicJwkBuilder key(ECPublicKey key);
216
EcPublicJwkBuilder curve(Curve curve);
217
}
218
219
public interface EcPrivateJwkBuilder extends PrivateJwkBuilder<ECPrivateKey, EcPublicJwk, KeyPair<ECPublicKey, ECPrivateKey>, EcPrivateJwk, EcPrivateJwkBuilder> {
220
EcPrivateJwkBuilder key(ECPrivateKey key);
221
EcPrivateJwkBuilder curve(Curve curve);
222
}
223
```
224
225
### JWK Builder Usage Examples
226
227
```java
228
import io.jsonwebtoken.security.Jwks;
229
import io.jsonwebtoken.security.RsaPrivateJwk;
230
import io.jsonwebtoken.security.EcPublicJwk;
231
import java.security.KeyPairGenerator;
232
import java.security.KeyPair;
233
234
// Generate RSA key pair
235
KeyPairGenerator rsaGenerator = KeyPairGenerator.getInstance("RSA");
236
rsaGenerator.initialize(2048);
237
KeyPair rsaKeyPair = rsaGenerator.generateKeyPair();
238
239
// Create RSA private JWK
240
RsaPrivateJwk rsaJwk = Jwks.builder()
241
.key(rsaKeyPair.getPrivate())
242
.keyId("rsa-key-1")
243
.algorithm("RS256")
244
.operations(Jwks.OP.SIGN)
245
.build();
246
247
// Create EC public JWK
248
KeyPairGenerator ecGenerator = KeyPairGenerator.getInstance("EC");
249
ecGenerator.initialize(256);
250
KeyPair ecKeyPair = ecGenerator.generateKeyPair();
251
252
EcPublicJwk ecJwk = Jwks.builder()
253
.key((ECPublicKey) ecKeyPair.getPublic())
254
.keyId("ec-key-1")
255
.curve(Jwks.CRV.P256)
256
.operations(Jwks.OP.VERIFY)
257
.build();
258
259
// Convert JWK to JSON (safe for public keys)
260
String rsaPublicJson = Jwks.json(rsaJwk.toPublicJwk());
261
String ecPublicJson = Jwks.json(ecJwk);
262
263
// Convert to Java Key
264
RSAPrivateKey rsaPrivateKey = rsaJwk.toKey();
265
ECPublicKey ecPublicKey = ecJwk.toKey();
266
```
267
268
## JWK Sets
269
270
### JWK Set Interface
271
272
```java { .api }
273
public interface JwkSet extends Map<String, Object> {
274
Set<Jwk<?>> getKeys();
275
276
// Standard Parameter Names
277
String KEYS = "keys";
278
}
279
```
280
281
### JWK Set Builder
282
283
```java { .api }
284
public interface JwkSetBuilder extends Builder<JwkSet> {
285
JwkSetBuilder add(Jwk<?> jwk);
286
JwkSetBuilder add(Collection<? extends Jwk<?>> jwks);
287
JwkSetBuilder keys(Collection<? extends Jwk<?>> jwks);
288
JwkSet build();
289
}
290
```
291
292
### JWK Set Usage Example
293
294
```java
295
import io.jsonwebtoken.security.JwkSet;
296
import io.jsonwebtoken.security.Jwks;
297
298
// Create JWK Set with multiple keys
299
JwkSet jwkSet = Jwks.set()
300
.add(rsaJwk.toPublicJwk())
301
.add(ecJwk)
302
.build();
303
304
// Convert to JSON
305
String jwkSetJson = Jwks.json(jwkSet);
306
307
// Access keys
308
Set<Jwk<?>> keys = jwkSet.getKeys();
309
for (Jwk<?> jwk : keys) {
310
System.out.println("Key ID: " + jwk.getId());
311
System.out.println("Key Type: " + jwk.getType());
312
}
313
```
314
315
## JWK Parsing
316
317
### JWK Parser Builder
318
319
```java { .api }
320
public interface JwkParserBuilder extends Builder<JwkParser> {
321
JwkParserBuilder provider(Provider provider);
322
JwkParserBuilder deserializer(Deserializer<Map<String, ?>> deserializer);
323
JwkParser build();
324
}
325
```
326
327
### JWK Set Parser Builder
328
329
```java { .api }
330
public interface JwkSetParserBuilder extends Builder<JwkSetParser> {
331
JwkSetParserBuilder provider(Provider provider);
332
JwkSetParserBuilder deserializer(Deserializer<Map<String, ?>> deserializer);
333
JwkSetParser build();
334
}
335
```
336
337
### JWK Parsing Examples
338
339
```java
340
import io.jsonwebtoken.security.Jwks;
341
import io.jsonwebtoken.security.Jwk;
342
import io.jsonwebtoken.security.JwkSet;
343
344
// Parse single JWK from JSON
345
String jwkJson = "{ \"kty\": \"RSA\", \"kid\": \"key1\", ... }";
346
347
Jwk<?> parsedJwk = Jwks.parser()
348
.build()
349
.parse(jwkJson);
350
351
// Parse JWK Set from JSON
352
String jwkSetJson = "{ \"keys\": [ { \"kty\": \"RSA\", ... }, { \"kty\": \"EC\", ... } ] }";
353
354
JwkSet parsedJwkSet = Jwks.parser()
355
.build()
356
.parseSet(jwkSetJson);
357
358
// Access parsed keys
359
for (Jwk<?> jwk : parsedJwkSet.getKeys()) {
360
System.out.println("Parsed key: " + jwk.getId());
361
}
362
```
363
364
## Algorithm Interfaces
365
366
### Signature Algorithms
367
368
```java { .api }
369
public interface SignatureAlgorithm extends SecureDigestAlgorithm<PrivateKey, PublicKey>, KeyPairBuilderSupplier {
370
// Digital signature algorithms (RS256, PS256, ES256, EdDSA, etc.)
371
}
372
373
public interface MacAlgorithm extends SecureDigestAlgorithm<SecretKey, SecretKey>, KeyBuilderSupplier<SecretKey> {
374
// Message Authentication Code algorithms (HS256, HS384, HS512)
375
}
376
```
377
378
### Encryption Algorithms
379
380
```java { .api }
381
public interface AeadAlgorithm extends Identifiable {
382
// Authenticated Encryption with Associated Data
383
String getId();
384
385
// AEAD Operations
386
AeadResult encrypt(AeadRequest request) throws SecurityException;
387
DecryptAeadRequest decrypt(DecryptAeadRequest request) throws SecurityException;
388
}
389
390
public interface KeyAlgorithm<E extends Key, D extends Key> extends Identifiable {
391
// Key Management Algorithms
392
String getId();
393
394
// Key Management Operations
395
KeyResult getEncryptionKey(KeyRequest<E> request) throws SecurityException;
396
SecretKey getDecryptionKey(DecryptionKeyRequest<D> request) throws SecurityException;
397
}
398
```
399
400
### Algorithm Usage Examples
401
402
```java
403
import io.jsonwebtoken.Jwts;
404
import io.jsonwebtoken.security.SignatureAlgorithm;
405
import io.jsonwebtoken.security.MacAlgorithm;
406
407
// Use specific algorithms
408
SignatureAlgorithm rs256 = Jwts.SIG.RS256;
409
MacAlgorithm hs256 = Jwts.SIG.HS256;
410
411
// Generate appropriate keys for algorithms
412
RSAPrivateKey rsaKey = rs256.keyPair().build().getPrivate();
413
SecretKey macKey = hs256.key().build();
414
415
// Use in JWT operations
416
String rsaJwt = Jwts.builder()
417
.subject("user")
418
.signWith(rsaKey, rs256)
419
.compact();
420
421
String macJwt = Jwts.builder()
422
.subject("user")
423
.signWith(macKey, hs256)
424
.compact();
425
```
426
427
## Security Exception Hierarchy
428
429
```java { .api }
430
public class SecurityException extends JwtException {
431
// Base security exception
432
}
433
434
public class KeyException extends SecurityException {
435
// General key-related errors
436
}
437
438
public class InvalidKeyException extends KeyException {
439
// Invalid key format or content
440
}
441
442
public class WeakKeyException extends KeyException {
443
// Key strength insufficient for algorithm
444
}
445
446
public class UnsupportedKeyException extends KeyException {
447
// Key type not supported for operation
448
}
449
450
public class MalformedKeyException extends KeyException {
451
// Key format is malformed
452
}
453
454
public class MalformedKeySetException extends SecurityException {
455
// JWK Set format is malformed
456
}
457
458
public class SignatureException extends SecurityException {
459
// Signature operation failed
460
}
461
```
462
463
## Advanced Security Features
464
465
### Key Strength Validation
466
467
JJWT automatically validates key strength according to JWA specifications:
468
469
```java
470
// These will throw WeakKeyException if keys are too short
471
SecretKey weakKey = Keys.hmacShaKeyFor(new byte[16]); // Only 128 bits for HS256
472
SecretKey strongKey = Keys.hmacShaKeyFor(new byte[32]); // 256 bits - OK
473
474
// Automatic validation during JWT creation
475
try {
476
String jwt = Jwts.builder()
477
.subject("user")
478
.signWith(weakKey, Jwts.SIG.HS256) // May throw WeakKeyException
479
.compact();
480
} catch (WeakKeyException e) {
481
System.err.println("Key too weak: " + e.getMessage());
482
}
483
```
484
485
### Curve Support
486
487
JJWT supports all standard elliptic curves:
488
489
```java
490
// NIST P-curves
491
Curve p256 = Jwks.CRV.P256; // secp256r1
492
Curve p384 = Jwks.CRV.P384; // secp384r1
493
Curve p521 = Jwks.CRV.P521; // secp521r1
494
495
// Edwards curves
496
Curve ed25519 = Jwks.CRV.Ed25519; // EdDSA signing
497
Curve ed448 = Jwks.CRV.Ed448; // EdDSA signing
498
499
// Montgomery curves
500
Curve x25519 = Jwks.CRV.X25519; // ECDH key agreement
501
Curve x448 = Jwks.CRV.X448; // ECDH key agreement
502
```
503
504
### JCA Provider Support
505
506
All security operations support custom JCA Providers:
507
508
```java
509
Provider customProvider = new CustomSecurityProvider();
510
511
// Use custom provider for key generation
512
SecretKey key = Keys.builder(existingKey)
513
.provider(customProvider)
514
.build();
515
516
// Use custom provider for JWT operations
517
String jwt = Jwts.builder()
518
.provider(customProvider)
519
.subject("user")
520
.signWith(key)
521
.compact();
522
523
// Use custom provider for parsing
524
JwtParser parser = Jwts.parser()
525
.provider(customProvider)
526
.verifyWith(key)
527
.build();
528
```