io.jsonwebtoken.security.DynamicJwkBuilder Maven / Gradle / Ivy
/*
* Copyright (C) 2021 jsonwebtoken.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.jsonwebtoken.security;
import javax.crypto.SecretKey;
import java.security.Key;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.List;
/**
* A {@link JwkBuilder} that coerces to a more type-specific builder based on the {@link Key} that will be
* represented as a JWK.
*
* @param the type of Java {@link Key} represented by the created {@link Jwk}.
* @param the type of {@link Jwk} created by the builder
* @since 0.12.0
*/
public interface DynamicJwkBuilder> extends JwkBuilder> {
/**
* Ensures the builder will create a {@link PublicJwk} for the specified Java {@link X509Certificate} chain.
* The first {@code X509Certificate} in the chain (at array index 0) MUST contain a {@link PublicKey}
* instance when calling the certificate's {@link X509Certificate#getPublicKey() getPublicKey()} method.
*
* This method is provided for congruence with the other {@code chain} methods and is expected to be used when
* the calling code has a variable {@code PublicKey} reference. Based on the argument type, it will
* delegate to one of the following methods if possible:
*
* - {@link #rsaChain(List)}
* - {@link #ecChain(List)}
* - {@link #octetChain(List)}
*
*
* If the specified {@code chain} argument is not capable of being supported by one of those methods, an
* {@link UnsupportedKeyException} will be thrown.
*
* Type Parameters
*
* In addition to the public key type A
, the public key's associated private key type
* B
is parameterized as well. This ensures that any subsequent call to the builder's
* {@link PublicJwkBuilder#privateKey(PrivateKey) privateKey} method will be type-safe. For example:
*
* Jwks.builder().<EdECPublicKey, EdECPrivateKey>chain(edECPublicKeyX509CertificateChain)
* .privateKey(aPrivateKey) // <-- must be an EdECPrivateKey instance
* ... etc ...
* .build();
*
* @param the type of {@link PublicKey} provided by the created public JWK.
* @param the type of {@link PrivateKey} that may be paired with the {@link PublicKey} to produce a
* {@link PrivateJwk} if desired.
* @param chain the {@link X509Certificate} chain to inspect to find the {@link PublicKey} to represent as a
* {@link PublicJwk}.
* @return the builder coerced as a {@link PublicJwkBuilder} for continued method chaining.
* @throws UnsupportedKeyException if the specified key is not a supported type and cannot be used to delegate to
* other {@code key} methods.
* @see PublicJwk
* @see PrivateJwk
*/
PublicJwkBuilder chain(List chain)
throws UnsupportedKeyException;
/**
* Ensures the builder will create a {@link SecretJwk} for the specified Java {@link SecretKey}.
*
* @param key the {@link SecretKey} to represent as a {@link SecretJwk}.
* @return the builder coerced as a {@link SecretJwkBuilder}.
*/
SecretJwkBuilder key(SecretKey key);
/**
* Ensures the builder will create an {@link RsaPublicJwk} for the specified Java {@link RSAPublicKey}.
*
* @param key the {@link RSAPublicKey} to represent as a {@link RsaPublicJwk}.
* @return the builder coerced as an {@link RsaPublicJwkBuilder}.
*/
RsaPublicJwkBuilder key(RSAPublicKey key);
/**
* Ensures the builder will create an {@link RsaPrivateJwk} for the specified Java {@link RSAPrivateKey}. If
* possible, it is recommended to also call the resulting builder's
* {@link RsaPrivateJwkBuilder#publicKey(PublicKey) publicKey} method with the private key's matching
* {@link PublicKey} for better performance. See the
* {@link RsaPrivateJwkBuilder#publicKey(PublicKey) publicKey} and {@link PrivateJwk} JavaDoc for more
* information.
*
* @param key the {@link RSAPublicKey} to represent as a {@link RsaPublicJwk}.
* @return the builder coerced as an {@link RsaPrivateJwkBuilder}.
*/
RsaPrivateJwkBuilder key(RSAPrivateKey key);
/**
* Ensures the builder will create an {@link EcPublicJwk} for the specified Java {@link ECPublicKey}.
*
* @param key the {@link ECPublicKey} to represent as a {@link EcPublicJwk}.
* @return the builder coerced as an {@link EcPublicJwkBuilder}.
*/
EcPublicJwkBuilder key(ECPublicKey key);
/**
* Ensures the builder will create an {@link EcPrivateJwk} for the specified Java {@link ECPrivateKey}. If
* possible, it is recommended to also call the resulting builder's
* {@link EcPrivateJwkBuilder#publicKey(PublicKey) publicKey} method with the private key's matching
* {@link PublicKey} for better performance. See the
* {@link EcPrivateJwkBuilder#publicKey(PublicKey) publicKey} and {@link PrivateJwk} JavaDoc for more
* information.
*
* @param key the {@link ECPublicKey} to represent as an {@link EcPublicJwk}.
* @return the builder coerced as a {@link EcPrivateJwkBuilder}.
*/
EcPrivateJwkBuilder key(ECPrivateKey key);
/**
* Ensures the builder will create a {@link PublicJwk} for the specified Java {@link PublicKey} argument. This
* method is provided for congruence with the other {@code key} methods and is expected to be used when
* the calling code has an untyped {@code PublicKey} reference. Based on the argument type, it will delegate to one
* of the following methods if possible:
*
* - {@link #key(RSAPublicKey)}
* - {@link #key(ECPublicKey)}
* - {@link #octetKey(PublicKey)}
*
*
* If the specified {@code key} argument is not capable of being supported by one of those methods, an
* {@link UnsupportedKeyException} will be thrown.
*
* Type Parameters
*
* In addition to the public key type A
, the public key's associated private key type
* B
is parameterized as well. This ensures that any subsequent call to the builder's
* {@link PublicJwkBuilder#privateKey(PrivateKey) privateKey} method will be type-safe. For example:
*
* Jwks.builder().<EdECPublicKey, EdECPrivateKey>key(anEdECPublicKey)
* .privateKey(aPrivateKey) // <-- must be an EdECPrivateKey instance
* ... etc ...
* .build();
*
* @param the type of {@link PublicKey} provided by the created public JWK.
* @param the type of {@link PrivateKey} that may be paired with the {@link PublicKey} to produce a
* {@link PrivateJwk} if desired.
* @param key the {@link PublicKey} to represent as a {@link PublicJwk}.
* @return the builder coerced as a {@link PublicJwkBuilder} for continued method chaining.
* @throws UnsupportedKeyException if the specified key is not a supported type and cannot be used to delegate to
* other {@code key} methods.
* @see PublicJwk
* @see PrivateJwk
*/
PublicJwkBuilder key(A key) throws UnsupportedKeyException;
/**
* Ensures the builder will create a {@link PrivateJwk} for the specified Java {@link PrivateKey} argument. This
* method is provided for congruence with the other {@code key} methods and is expected to be used when
* the calling code has an untyped {@code PrivateKey} reference. Based on the argument type, it will delegate to one
* of the following methods if possible:
*
* - {@link #key(RSAPrivateKey)}
* - {@link #key(ECPrivateKey)}
* - {@link #octetKey(PrivateKey)}
*
*
* If the specified {@code key} argument is not capable of being supported by one of those methods, an
* {@link UnsupportedKeyException} will be thrown.
*
* Type Parameters
*
* In addition to the private key type B
, the private key's associated public key type
* A
is parameterized as well. This ensures that any subsequent call to the builder's
* {@link PrivateJwkBuilder#publicKey(PublicKey) publicKey} method will be type-safe. For example:
*
* Jwks.builder().<EdECPublicKey, EdECPrivateKey>key(anEdECPrivateKey)
* .publicKey(aPublicKey) // <-- must be an EdECPublicKey instance
* ... etc ...
* .build();
*
* @param the type of {@link PublicKey} paired with the {@code key} argument to produce the {@link PrivateJwk}.
* @param the type of the {@link PrivateKey} argument.
* @param key the {@link PrivateKey} to represent as a {@link PrivateJwk}.
* @return the builder coerced as a {@link PrivateJwkBuilder} for continued method chaining.
* @throws UnsupportedKeyException if the specified key is not a supported type and cannot be used to delegate to
* other {@code key} methods.
* @see PublicJwk
* @see PrivateJwk
*/
PrivateJwkBuilder key(B key) throws UnsupportedKeyException;
/**
* Ensures the builder will create a {@link PrivateJwk} for the specified Java {@link KeyPair} argument. This
* method is provided for congruence with the other {@code keyPair} methods and is expected to be used when
* the calling code has a variable {@code PrivateKey} reference. Based on the argument's {@code PrivateKey} type,
* it will delegate to one of the following methods if possible:
*
* - {@link #key(RSAPrivateKey)}
* - {@link #key(ECPrivateKey)}
* - {@link #octetKey(PrivateKey)}
*
* and automatically set the resulting builder's {@link PrivateJwkBuilder#publicKey(PublicKey) publicKey} with
* the pair's {@code PublicKey}.
*
* If the specified {@code key} argument is not capable of being supported by one of those methods, an
* {@link UnsupportedKeyException} will be thrown.
*
* Type Parameters
*
* In addition to the private key type B
, the private key's associated public key type
* A
is parameterized as well. This ensures that any subsequent call to the builder's
* {@link PrivateJwkBuilder#publicKey(PublicKey) publicKey} method will be type-safe. For example:
*
* Jwks.builder().<EdECPublicKey, EdECPrivateKey>keyPair(anEdECKeyPair)
* .publicKey(aPublicKey) // <-- must be an EdECPublicKey instance
* ... etc ...
* .build();
*
* @param the {@code keyPair} argument's {@link PublicKey} type
* @param the {@code keyPair} argument's {@link PrivateKey} type
* @param keyPair the {@code KeyPair} containing the public and private key
* @return the builder coerced as a {@link PrivateJwkBuilder} for continued method chaining.
* @throws UnsupportedKeyException if the specified {@code KeyPair}'s keys are not supported and cannot be used to
* delegate to other {@code key} methods.
* @see PublicJwk
* @see PrivateJwk
*/
PrivateJwkBuilder keyPair(KeyPair keyPair)
throws UnsupportedKeyException;
/**
* Ensures the builder will create an {@link OctetPublicJwk} for the specified Edwards-curve {@code PublicKey}
* argument. The {@code PublicKey} must be an instance of one of the following:
*
* - java.security.interfaces.XECPublicKey, introduced in JDK 11
* - java.security.interfaces.EdECPublicKey, introduced in JDK 15
* - A {@code PublicKey} with a valid Edwards Curve DER {@link Key#getEncoded() encoding}, such as those
* provided by BouncyCastle on earlier JDKs.
*
*
* Type Parameters
*
* In addition to the public key type A
, the public key's associated private key type
* B
is parameterized as well. This ensures that any subsequent call to the builder's
* {@link PublicJwkBuilder#privateKey(PrivateKey) privateKey} method will be type-safe. For example:
*
* Jwks.builder().<EdECPublicKey, EdECPrivateKey>key(anEdECPublicKey)
* .privateKey(aPrivateKey) // <-- must be an EdECPrivateKey instance
* ... etc ...
* .build();
*
* @param the type of Edwards-curve {@link PublicKey} provided by the created public JWK.
* @param the type of Edwards-curve {@link PrivateKey} that may be paired with the {@link PublicKey} to produce
* an {@link OctetPrivateJwk} if desired.
* @param key the Edwards-curve {@link PublicKey} to represent as an {@link OctetPublicJwk}.
* @return the builder coerced as a {@link OctetPublicJwkBuilder} for continued method chaining.
* @throws UnsupportedKeyException if the specified key is not a supported Edwards-curve key.
* @see java.security.interfaces.XECPublicKey
* @see java.security.interfaces.EdECPublicKey
*/
OctetPublicJwkBuilder octetKey(A key);
/**
* Ensures the builder will create an {@link OctetPrivateJwk} for the specified Edwards-curve {@code PrivateKey}
* argument. The {@code PrivateKey} must be an instance of one of the following:
*
* -
* java.security.interfaces.XECPrivateKey, introduced in JDK 11
* -
* java.security.interfaces.EdECPrivateKey, introduced in JDK 15
* - A {@code PrivateKey} with a valid Edwards Curve DER {@link Key#getEncoded() encoding}, such as those
* provided by BouncyCastle on earlier JDKs.
*
*
* Type Parameters
*
* In addition to the private key type B
, the private key's associated public key type
* A
is parameterized as well. This ensures that any subsequent call to the builder's
* {@link PrivateJwkBuilder#publicKey(PublicKey) publicKey} method will be type-safe. For example:
*
* Jwks.builder().<EdECPublicKey, EdECPrivateKey>key(anEdECPrivateKey)
* .publicKey(aPublicKey) // <-- must be an EdECPublicKey instance
* ... etc ...
* .build();
*
* @param the type of the Edwards-curve {@link PrivateKey} argument.
* @param the type of Edwards-curve {@link PublicKey} paired with the {@code key} argument to produce the
* {@link OctetPrivateJwk}.
* @param key the Edwards-curve {@link PrivateKey} to represent as an {@link OctetPrivateJwk}.
* @return the builder coerced as an {@link OctetPrivateJwkBuilder} for continued method chaining.
* @throws UnsupportedKeyException if the specified key is not a supported Edwards-curve key.
* @see java.security.interfaces.XECPrivateKey
* @see java.security.interfaces.EdECPrivateKey
*/
OctetPrivateJwkBuilder octetKey(A key);
/**
* Ensures the builder will create an {@link OctetPublicJwk} for the specified Java {@link X509Certificate} chain.
* The first {@code X509Certificate} in the chain (at list index 0) MUST
* {@link X509Certificate#getPublicKey() contain} an Edwards-curve public key as defined by
* {@link #octetKey(PublicKey)}.
*
* @param the type of Edwards-curve {@link PublicKey} contained in the first {@code X509Certificate}.
* @param the type of Edwards-curve {@link PrivateKey} that may be paired with the {@link PublicKey} to produce
* an {@link OctetPrivateJwk} if desired.
* @param chain the {@link X509Certificate} chain to inspect to find the Edwards-curve {@code PublicKey} to
* represent as an {@link OctetPublicJwk}.
* @return the builder coerced as an {@link OctetPublicJwkBuilder} for continued method chaining.
*/
OctetPublicJwkBuilder octetChain(List chain);
/**
* Ensures the builder will create an {@link OctetPrivateJwk} for the specified Java Edwards-curve
* {@link KeyPair}. The pair's {@link KeyPair#getPublic() public key} MUST be an
* Edwards-curve public key as defined by {@link #octetKey(PublicKey)}. The pair's
* {@link KeyPair#getPrivate() private key} MUST be an Edwards-curve private key as defined by
* {@link #octetKey(PrivateKey)}.
*
* @param the type of Edwards-curve {@link PublicKey} contained in the key pair.
* @param the type of the Edwards-curve {@link PrivateKey} contained in the key pair.
* @param keyPair the Edwards-curve {@link KeyPair} to represent as an {@link OctetPrivateJwk}.
* @return the builder coerced as an {@link OctetPrivateJwkBuilder} for continued method chaining.
* @throws IllegalArgumentException if the {@code keyPair} does not contain Edwards-curve public and private key
* instances.
*/
OctetPrivateJwkBuilder octetKeyPair(KeyPair keyPair);
/**
* Ensures the builder will create an {@link EcPublicJwk} for the specified Java {@link X509Certificate} chain.
* The first {@code X509Certificate} in the chain (at list index 0) MUST contain an {@link ECPublicKey}
* instance when calling the certificate's {@link X509Certificate#getPublicKey() getPublicKey()} method.
*
* @param chain the {@link X509Certificate} chain to inspect to find the {@link ECPublicKey} to represent as a
* {@link EcPublicJwk}.
* @return the builder coerced as an {@link EcPublicJwkBuilder}.
*/
EcPublicJwkBuilder ecChain(List chain);
/**
* Ensures the builder will create an {@link EcPrivateJwk} for the specified Java Elliptic Curve
* {@link KeyPair}. The pair's {@link KeyPair#getPublic() public key} MUST be an
* {@link ECPublicKey} instance. The pair's {@link KeyPair#getPrivate() private key} MUST be an
* {@link ECPrivateKey} instance.
*
* @param keyPair the EC {@link KeyPair} to represent as an {@link EcPrivateJwk}.
* @return the builder coerced as an {@link EcPrivateJwkBuilder}.
* @throws IllegalArgumentException if the {@code keyPair} does not contain {@link ECPublicKey} and
* {@link ECPrivateKey} instances.
*/
EcPrivateJwkBuilder ecKeyPair(KeyPair keyPair) throws IllegalArgumentException;
/**
* Ensures the builder will create an {@link RsaPublicJwk} for the specified Java {@link X509Certificate} chain.
* The first {@code X509Certificate} in the chain (at list index 0) MUST contain an {@link RSAPublicKey}
* instance when calling the certificate's {@link X509Certificate#getPublicKey() getPublicKey()} method.
*
* @param chain the {@link X509Certificate} chain to inspect to find the {@link RSAPublicKey} to represent as a
* {@link RsaPublicJwk}.
* @return the builder coerced as an {@link RsaPublicJwkBuilder}.
*/
RsaPublicJwkBuilder rsaChain(List chain);
/**
* Ensures the builder will create an {@link RsaPrivateJwk} for the specified Java RSA
* {@link KeyPair}. The pair's {@link KeyPair#getPublic() public key} MUST be an
* {@link RSAPublicKey} instance. The pair's {@link KeyPair#getPrivate() private key} MUST be an
* {@link RSAPrivateKey} instance.
*
* @param keyPair the RSA {@link KeyPair} to represent as an {@link RsaPrivateJwk}.
* @return the builder coerced as an {@link RsaPrivateJwkBuilder}.
* @throws IllegalArgumentException if the {@code keyPair} does not contain {@link RSAPublicKey} and
* {@link RSAPrivateKey} instances.
*/
RsaPrivateJwkBuilder rsaKeyPair(KeyPair keyPair) throws IllegalArgumentException;
}