Skip to content

Commit 5c7e056

Browse files
committed
Resolves #940.
Adding request/result parameters and builders for usage outside of the impl module.
1 parent c6744e3 commit 5c7e056

28 files changed

+765
-55
lines changed

api/src/main/java/io/jsonwebtoken/Jwts.java

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,27 @@
2020
import io.jsonwebtoken.lang.Classes;
2121
import io.jsonwebtoken.lang.Registry;
2222
import io.jsonwebtoken.security.AeadAlgorithm;
23+
import io.jsonwebtoken.security.AeadRequest;
24+
import io.jsonwebtoken.security.AeadResult;
25+
import io.jsonwebtoken.security.DecryptAeadRequest;
26+
import io.jsonwebtoken.security.DecryptionKeyRequest;
2327
import io.jsonwebtoken.security.KeyAlgorithm;
2428
import io.jsonwebtoken.security.KeyPairBuilderSupplier;
29+
import io.jsonwebtoken.security.KeyRequest;
2530
import io.jsonwebtoken.security.MacAlgorithm;
2631
import io.jsonwebtoken.security.Password;
32+
import io.jsonwebtoken.security.Request;
2733
import io.jsonwebtoken.security.SecretKeyAlgorithm;
2834
import io.jsonwebtoken.security.SecureDigestAlgorithm;
35+
import io.jsonwebtoken.security.SecureRequest;
2936
import io.jsonwebtoken.security.SignatureAlgorithm;
37+
import io.jsonwebtoken.security.VerifyDigestRequest;
38+
import io.jsonwebtoken.security.VerifySecureDigestRequest;
3039
import io.jsonwebtoken.security.X509Builder;
3140

3241
import javax.crypto.SecretKey;
42+
import java.io.InputStream;
43+
import java.io.OutputStream;
3344
import java.security.Key;
3445
import java.security.PrivateKey;
3546
import java.security.PublicKey;
@@ -82,6 +93,18 @@ public static final class ENC {
8293
private static final String IMPL_CLASSNAME = "io.jsonwebtoken.impl.security.StandardEncryptionAlgorithms";
8394
private static final Registry<String, AeadAlgorithm> REGISTRY = Classes.newInstance(IMPL_CLASSNAME);
8495

96+
// @since 0.13.0
97+
private static final Supplier<AeadRequest.Builder> REQUEST_BUILDER_SUPPLIER =
98+
Classes.newInstance("io.jsonwebtoken.impl.security.DefaultAeadRequest$Builder$Supplier");
99+
100+
// @since 0.13.0
101+
private static final Supplier<DecryptAeadRequest.Builder> DECRYPT_REQUEST_BUILDER_SUPPLIER =
102+
Classes.newInstance("io.jsonwebtoken.impl.security.DefaultDecryptAeadRequest$Builder$Supplier");
103+
104+
// @since 0.13.0
105+
private static final Supplier<AeadResult.Builder> RESULT_BUILDER_SUPPLIER =
106+
Classes.newInstance("io.jsonwebtoken.impl.security.DefaultAeadResult$Builder$Supplier");
107+
85108
/**
86109
* Returns all standard JWA <a href="https://www.rfc-editor.org/rfc/rfc7518.html#section-5">Cryptographic
87110
* Algorithms for Content Encryption</a> defined in the
@@ -139,6 +162,42 @@ private ENC() {
139162
* algorithm requires a 256-bit (32 byte) key.
140163
*/
141164
public static final AeadAlgorithm A256GCM = get().forKey("A256GCM");
165+
166+
/**
167+
* Returns a new builder to create {@link AeadRequest}s used for AEAD encryption via
168+
* {@link AeadAlgorithm#encrypt(AeadRequest, AeadResult)}
169+
*
170+
* @return a new builder to create {@link AeadRequest}s used for AEAD encryption via
171+
* {@link AeadAlgorithm#encrypt(AeadRequest, AeadResult)}
172+
* @since 0.13.0
173+
*/
174+
public static AeadRequest.Builder request() {
175+
return REQUEST_BUILDER_SUPPLIER.get();
176+
}
177+
178+
/**
179+
* Returns a new builder to create {@link DecryptAeadRequest}s used for AEAD decryption via
180+
* {@link AeadAlgorithm#decrypt(DecryptAeadRequest, OutputStream)}
181+
*
182+
* @return a new builder to create {@link DecryptAeadRequest}s used for AEAD decryption via
183+
* {@link AeadAlgorithm#decrypt(DecryptAeadRequest, OutputStream)}
184+
* @since 0.13.0
185+
*/
186+
public static DecryptAeadRequest.Builder decryptRequest() {
187+
return DECRYPT_REQUEST_BUILDER_SUPPLIER.get();
188+
}
189+
190+
/**
191+
* Returns a new builder to create {@link AeadResult}s used to store AEAD encryption results when calling
192+
* {@link AeadAlgorithm#encrypt(AeadRequest, AeadResult)}
193+
*
194+
* @return a new builder to create {@link AeadResult}s used to store AEAD encryption results when calling
195+
* {@link AeadAlgorithm#encrypt(AeadRequest, AeadResult)}
196+
* @since 0.13.0
197+
*/
198+
public static AeadResult.Builder result() {
199+
return RESULT_BUILDER_SUPPLIER.get();
200+
}
142201
}
143202

144203
/**
@@ -162,6 +221,14 @@ public static final class SIG {
162221
private static final String IMPL_CLASSNAME = "io.jsonwebtoken.impl.security.StandardSecureDigestAlgorithms";
163222
private static final Registry<String, SecureDigestAlgorithm<?, ?>> REGISTRY = Classes.newInstance(IMPL_CLASSNAME);
164223

224+
// @since 0.13.0
225+
private static final Supplier<SecureRequest.Builder<InputStream, ?>> REQUEST_BUILDER_SUPPLIER =
226+
Classes.newInstance("io.jsonwebtoken.impl.security.DefaultSecureRequest$Builder$Supplier");
227+
228+
// @since 0.13.0
229+
private static final Supplier<VerifySecureDigestRequest.Builder<?>> VERIFY_REQUEST_BUILDER_SUPPLIER =
230+
Classes.newInstance("io.jsonwebtoken.impl.security.DefaultVerifySecureDigestRequest$Builder$Supplier");
231+
165232
//prevent instantiation
166233
private SIG() {
167234
}
@@ -302,6 +369,34 @@ private SIG() {
302369
* classpath.</b></p>
303370
*/
304371
public static final SignatureAlgorithm EdDSA = Jwts.get(REGISTRY, "EdDSA");
372+
373+
/**
374+
* Returns a new builder to create {@link SecureRequest}s used to compute a mac or signature via
375+
* {@link SecureDigestAlgorithm#digest(Request)}.
376+
*
377+
* @param <K> the type of key used by the algorithm to compute the mac or signature.
378+
* @return a new builder to create {@link SecureRequest}s used to compute a mac or signature via
379+
* {@link SecureDigestAlgorithm#digest(Request)}.
380+
* @since 0.13.0
381+
*/
382+
@SuppressWarnings("unchecked")
383+
public static <K extends Key> SecureRequest.Builder<InputStream, K> request() {
384+
return (SecureRequest.Builder<InputStream, K>) REQUEST_BUILDER_SUPPLIER.get();
385+
}
386+
387+
/**
388+
* Returns a new builder to create {@link VerifySecureDigestRequest}s used to verify a mac or signature via
389+
* {@link SecureDigestAlgorithm#verify(VerifyDigestRequest)}.
390+
*
391+
* @param <K> the type of key used by the algorithm to verify the mac or signature.
392+
* @return a new builder to create {@link VerifySecureDigestRequest}s used to verify a mac or signature via
393+
* {@link SecureDigestAlgorithm#verify(VerifyDigestRequest)}.
394+
* @since 0.13.0
395+
*/
396+
@SuppressWarnings("unchecked")
397+
public static <K extends Key> VerifySecureDigestRequest.Builder<K> verifyRequest() {
398+
return (VerifySecureDigestRequest.Builder<K>) VERIFY_REQUEST_BUILDER_SUPPLIER.get();
399+
}
305400
}
306401

307402
/**
@@ -323,6 +418,14 @@ public static final class KEY {
323418
private static final String IMPL_CLASSNAME = "io.jsonwebtoken.impl.security.StandardKeyAlgorithms";
324419
private static final Registry<String, KeyAlgorithm<?, ?>> REGISTRY = Classes.newInstance(IMPL_CLASSNAME);
325420

421+
// @since 0.13.0
422+
private static final Supplier<KeyRequest.Builder<?>> REQUEST_BUILDER_SUPPLIER =
423+
Classes.newInstance("io.jsonwebtoken.impl.security.DefaultKeyRequest$Builder$Supplier");
424+
425+
// @since 0.13.0
426+
private static final Supplier<DecryptionKeyRequest.Builder<?>> VERIFY_REQUEST_BUILDER_SUPPLIER =
427+
Classes.newInstance("io.jsonwebtoken.impl.security.DefaultDecryptionKeyRequest$Builder$Supplier");
428+
326429
/**
327430
* Returns all standard JWA standard <a href="https://www.rfc-editor.org/rfc/rfc7518.html#section-4">Cryptographic
328431
* Algorithms for Key Management</a>..
@@ -926,6 +1029,34 @@ public static final class KEY {
9261029
*/
9271030
public static final KeyAlgorithm<PublicKey, PrivateKey> ECDH_ES_A256KW = Jwts.get(REGISTRY, "ECDH-ES+A256KW");
9281031

1032+
/**
1033+
* Returns a new builder to create {@link KeyRequest}s used to get a JWE encryption key via
1034+
* {@link KeyAlgorithm#getEncryptionKey(KeyRequest)}.
1035+
*
1036+
* @param <K> the type of key used by the {@link KeyAlgorithm} to get a JWE encryption key.
1037+
* @return a new builder to create {@link KeyRequest}s used to get a JWE encryption key via
1038+
* {@link KeyAlgorithm#getEncryptionKey(KeyRequest)}.
1039+
* @since 0.13.0
1040+
*/
1041+
@SuppressWarnings("unchecked")
1042+
public static <K extends Key> KeyRequest.Builder<K> request() {
1043+
return (KeyRequest.Builder<K>) REQUEST_BUILDER_SUPPLIER.get();
1044+
}
1045+
1046+
/**
1047+
* Returns a new builder to create {@link DecryptionKeyRequest}s used to get a JWE decryption key via
1048+
* {@link KeyAlgorithm#getDecryptionKey(DecryptionKeyRequest)}.
1049+
*
1050+
* @param <K> the type of key used by the {@link KeyAlgorithm} to get a JWE decryption key.
1051+
* @return a new builder to create {@link DecryptionKeyRequest}s used to get a JWE decryption key via
1052+
* {@link KeyAlgorithm#getDecryptionKey(DecryptionKeyRequest)}.
1053+
* @since 0.13.0
1054+
*/
1055+
@SuppressWarnings("unchecked")
1056+
public static <K extends Key> DecryptionKeyRequest.Builder<K> decRequest() {
1057+
return (DecryptionKeyRequest.Builder<K>) VERIFY_REQUEST_BUILDER_SUPPLIER.get();
1058+
}
1059+
9291060
//prevent instantiation
9301061
private KEY() {
9311062
}

api/src/main/java/io/jsonwebtoken/security/AeadRequest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import javax.crypto.SecretKey;
1919
import java.io.InputStream;
20+
import java.io.OutputStream;
2021

2122
/**
2223
* A request to an {@link AeadAlgorithm} to perform authenticated encryption with a supplied symmetric
@@ -27,4 +28,33 @@
2728
* @since 0.12.0
2829
*/
2930
public interface AeadRequest extends SecureRequest<InputStream, SecretKey>, AssociatedDataSupplier {
31+
32+
/**
33+
* Named parameters (setters) used to configure an {@link AeadRequest AeadRequest} instance.
34+
*
35+
* @param <M> the instance type returned for method chaining.
36+
* @since 0.13.0
37+
*/
38+
interface Params<M extends Params<M>> extends SecureRequest.Params<InputStream, SecretKey, M> {
39+
40+
/**
41+
* Sets any &quot;associated data&quot; that must be integrity protected (but not encrypted) when performing
42+
* <a href="https://en.wikipedia.org/wiki/Authenticated_encryption">AEAD encryption or decryption</a>.
43+
*
44+
* @param aad the {@code InputStream} containing any associated data that must be integrity protected or
45+
* verified during AEAD encryption or decryption.
46+
* @return the instance for method chaining.
47+
* @see AeadAlgorithm#encrypt(AeadRequest, AeadResult)
48+
* @see AeadAlgorithm#decrypt(DecryptAeadRequest, OutputStream)
49+
*/
50+
M associatedData(InputStream aad);
51+
}
52+
53+
/**
54+
* A builder for creating new immutable {@link AeadRequest} instances.
55+
*
56+
* @since 0.13.0
57+
*/
58+
interface Builder extends Params<Builder>, io.jsonwebtoken.lang.Builder<AeadRequest> {
59+
}
3060
}

api/src/main/java/io/jsonwebtoken/security/AeadResult.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
*
2525
* @since 0.12.0
2626
*/
27-
public interface AeadResult {
27+
public interface AeadResult extends DigestSupplier, IvSupplier {
2828

2929
/**
3030
* Returns the {@code OutputStream} the AeadAlgorithm will use to write the resulting ciphertext during
@@ -50,4 +50,23 @@ public interface AeadResult {
5050
* @return the AeadResult for method chaining.
5151
*/
5252
AeadResult setIv(byte[] iv);
53+
54+
/**
55+
* A builder for creating new {@link AeadResult} instances.
56+
*
57+
* @since 0.13.0
58+
*/
59+
interface Builder extends io.jsonwebtoken.lang.Builder<AeadResult> {
60+
61+
/**
62+
* Sets the {@code OutputStream} the AeadAlgorithm will use to write the resulting ciphertext during
63+
* encryption or plaintext during decryption.
64+
*
65+
* @param out the {@code OutputStream} the AeadAlgorithm will use to write the resulting ciphertext during
66+
* encryption or plaintext during decryption.
67+
* @return the builder for instance chaining.
68+
*/
69+
Builder out(OutputStream out);
70+
}
71+
5372
}

api/src/main/java/io/jsonwebtoken/security/DecryptAeadRequest.java

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,43 @@
1818
import javax.crypto.SecretKey;
1919

2020
/**
21-
* A request to an {@link AeadAlgorithm} to decrypt ciphertext and perform integrity-protection with a supplied
21+
* A request to an {@link AeadAlgorithm} to decrypt ciphertext with integrity verification with a supplied
2222
* decryption {@link SecretKey}. Extends both {@link IvSupplier} and {@link DigestSupplier} to
2323
* ensure the respective required IV and AAD tag returned from an {@link AeadResult} are available for decryption.
2424
*
2525
* @since 0.12.0
2626
*/
2727
public interface DecryptAeadRequest extends AeadRequest, IvSupplier, DigestSupplier {
28+
29+
/**
30+
* Named parameters (setters) used to configure an {@link AeadRequest AeadRequest} instance.
31+
*
32+
* @since 0.13.0
33+
*/
34+
interface Params<M extends Params<M>> extends AeadRequest.Params<M> {
35+
36+
/**
37+
* Sets the required initialization vector used during AEAD decryption.
38+
*
39+
* @param iv the required initialization vector used during AEAD decryption.
40+
*/
41+
M iv(byte[] iv);
42+
43+
/**
44+
* Sets the required AEAD Authentication Tag used to verify message authenticity during AEAD decryption.
45+
*
46+
* @param digest the required AEAD Authentication Tag used to verify message authenticity during AEAD decryption.
47+
* @return the instance for method chaining.
48+
*/
49+
M digest(byte[] digest);
50+
}
51+
52+
/**
53+
* A builder for creating new immutable {@link DecryptAeadRequest} instances.
54+
*
55+
* @since 0.13.0
56+
*/
57+
interface Builder extends io.jsonwebtoken.lang.Builder<DecryptAeadRequest>, Params<Builder> {
58+
}
59+
2860
}

api/src/main/java/io/jsonwebtoken/security/DecryptionKeyRequest.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,30 @@
3535
* {@code JWE Encrypted Key} (such as an initialization vector, authentication tag, ephemeral key, etc) is expected
3636
* to be available in the JWE protected header, accessible via {@link #getHeader()}.</p>
3737
*
38-
* @param <K> the type of {@link Key} used during the request to obtain the resulting decryption key.
38+
* @param <K> the type of key used by the {@link KeyAlgorithm} to obtain the JWE Content Encryption Key (CEK).
39+
* @see KeyAlgorithm#getDecryptionKey(DecryptionKeyRequest)
3940
* @since 0.12.0
4041
*/
4142
public interface DecryptionKeyRequest<K extends Key> extends SecureRequest<byte[], K>, KeyRequest<byte[]> {
43+
44+
/**
45+
* Named parameters (setters) used to configure a {@link DecryptionKeyRequest DecryptionKeyRequest}
46+
* instance.
47+
*
48+
* @param <K> the type of key used by the {@link KeyAlgorithm} to obtain the JWE Content Encryption Key (CEK).
49+
* @param <M> the instance type returned for method chaining.
50+
* @since 0.13.0
51+
*/
52+
interface Params<K extends Key, M extends Params<K, M>> extends KeyRequest.Params<byte[], M>,
53+
SecureRequest.Params<byte[], K, M> {
54+
}
55+
56+
/**
57+
* A builder for creating new immutable {@link DecryptionKeyRequest} instances.
58+
*
59+
* @param <K> the type of key used by the {@link KeyAlgorithm} to obtain the JWE Content Encryption Key (CEK).
60+
* @since 0.13.0
61+
*/
62+
interface Builder<K extends Key> extends Params<K, Builder<K>>, io.jsonwebtoken.lang.Builder<DecryptionKeyRequest<K>> {
63+
}
4264
}

api/src/main/java/io/jsonwebtoken/security/Jwks.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
import java.util.function.Supplier;
2424

25+
import java.io.InputStream;
26+
2527
/**
2628
* Utility methods for creating
2729
* <a href="https://www.rfc-editor.org/rfc/rfc7517.html">JWKs (JSON Web Keys)</a> with a type-safe builder.
@@ -289,6 +291,14 @@ public static final class HASH {
289291
private static final String IMPL_CLASSNAME = "io.jsonwebtoken.impl.security.StandardHashAlgorithms";
290292
private static final Registry<String, HashAlgorithm> REGISTRY = Classes.newInstance(IMPL_CLASSNAME);
291293

294+
// @since 0.13.0
295+
private static final Supplier<Request.Builder<InputStream>> REQUEST_BUILDER_SUPPLIER =
296+
Classes.newInstance("io.jsonwebtoken.impl.security.DefaultRequest$Builder$Supplier");
297+
298+
// @since 0.13.0
299+
private static final Supplier<VerifyDigestRequest.Builder> VERIFY_REQUEST_BUILDER_SUPPLIER =
300+
Classes.newInstance("io.jsonwebtoken.impl.security.DefaultVerifyDigestRequest$Builder$Supplier");
301+
292302
/**
293303
* Returns a registry of various (<em>but not all</em>)
294304
* <a href="https://www.iana.org/assignments/named-information/named-information.xhtml#hash-alg">IANA Hash
@@ -358,6 +368,30 @@ public static Registry<String, HashAlgorithm> get() {
358368
*/
359369
public static final HashAlgorithm SHA3_512 = get().forKey("sha3-512");
360370

371+
/**
372+
* Returns a new {@link Request.Builder} for creating {@link Request}s to compute a digest via
373+
* {@link HashAlgorithm#digest(Request)}.
374+
*
375+
* @return a new {@link Request.Builder} for creating {@link Request}s to compute a digest via
376+
* {@link HashAlgorithm#digest(Request)}.
377+
* @since 0.13.0
378+
*/
379+
public static Request.Builder<InputStream> request() {
380+
return REQUEST_BUILDER_SUPPLIER.get();
381+
}
382+
383+
/**
384+
* Returns a new {@link VerifyDigestRequest.Builder} for creating {@link VerifyDigestRequest}s to verify a
385+
* digest via {@link HashAlgorithm#verify(VerifyDigestRequest)}.
386+
*
387+
* @return a new {@link VerifyDigestRequest.Builder} for creating {@link VerifyDigestRequest}s to verify a
388+
* digest via {@link HashAlgorithm#verify(VerifyDigestRequest)}.
389+
* @since 0.13.0
390+
*/
391+
public static VerifyDigestRequest.Builder verifyRequest() {
392+
return VERIFY_REQUEST_BUILDER_SUPPLIER.get();
393+
}
394+
361395
//prevent instantiation
362396
private HASH() {
363397
}

0 commit comments

Comments
 (0)