com.nimbusds.jose.jwk.ECKey Maven / Gradle / Ivy
Show all versions of nimbus-jose-jwt Show documentation
/*
* nimbus-jose-jwt
*
* Copyright 2012-2024, Connect2id Ltd.
*
* 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 com.nimbusds.jose.jwk;
import com.nimbusds.jose.Algorithm;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.crypto.utils.ECChecks;
import com.nimbusds.jose.util.Base64;
import com.nimbusds.jose.util.Base64URL;
import com.nimbusds.jose.util.BigIntegerUtils;
import com.nimbusds.jose.util.JSONObjectUtils;
import net.jcip.annotations.Immutable;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
import java.math.BigInteger;
import java.net.URI;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.*;
import java.text.ParseException;
import java.util.*;
/**
* Public and private {@link KeyType#EC Elliptic Curve} JSON Web Key (JWK).
* This class is immutable.
*
* Supported curves:
*
*
* - {@link Curve#P_256 P-256}
*
- {@link Curve#SECP256K1 secp256k1}
*
- {@link Curve#P_384 P-384}
*
- {@link Curve#P_521 P-512}
*
*
* Provides EC JWK import from / export to the following standard Java
* interfaces and classes:
*
*
* - {@link java.security.interfaces.ECPublicKey}
*
- {@link java.security.interfaces.ECPrivateKey}
*
- {@link java.security.PrivateKey} for an EC key in a PKCS#11 store
*
- {@link java.security.KeyPair}
*
*
* Example JSON object representation of a public EC JWK:
*
*
* {
* "kty" : "EC",
* "crv" : "P-256",
* "x" : "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
* "y" : "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
* "use" : "enc",
* "kid" : "1"
* }
*
*
* Example JSON object representation of a private EC JWK:
*
*
* {
* "kty" : "EC",
* "crv" : "P-256",
* "x" : "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
* "y" : "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
* "d" : "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE",
* "use" : "enc",
* "kid" : "1"
* }
*
*
* Use the builder to create a new EC JWK:
*
*
* ECKey key = new ECKey.Builder(Curve.P_256, x, y)
* .keyUse(KeyUse.SIGNATURE)
* .keyID("1")
* .build();
*
*
* @author Vladimir Dzhuvinov
* @author Justin Richer
* @version 2024-04-27
*/
@Immutable
public final class ECKey extends JWK implements AsymmetricJWK, CurveBasedJWK {
private static final long serialVersionUID = 1L;
/**
* Supported EC curves.
*/
public static final Set SUPPORTED_CURVES = Collections.unmodifiableSet(
new HashSet<>(Arrays.asList(Curve.P_256, Curve.SECP256K1, Curve.P_384, Curve.P_521))
);
/**
* Builder for constructing Elliptic Curve JWKs.
*
* Example usage:
*
*
* ECKey key = new ECKey.Builder(Curve.P521, x, y)
* .d(d)
* .algorithm(JWSAlgorithm.ES512)
* .keyID("1")
* .build();
*
*/
public static class Builder {
/**
* The curve name.
*/
private final Curve crv;
/**
* The public 'x' EC coordinate.
*/
private final Base64URL x;
/**
* The public 'y' EC coordinate.
*/
private final Base64URL y;
/**
* The private 'd' EC coordinate, optional.
*/
private Base64URL d;
/**
* The private EC key, as PKCS#11 handle, optional.
*/
private PrivateKey priv;
/**
* The key use, optional.
*/
private KeyUse use;
/**
* The key operations, optional.
*/
private Set ops;
/**
* The intended JOSE algorithm for the key, optional.
*/
private Algorithm alg;
/**
* The key ID, optional.
*/
private String kid;
/**
* X.509 certificate URL, optional.
*/
private URI x5u;
/**
* X.509 certificate SHA-1 thumbprint, optional.
*/
@Deprecated
private Base64URL x5t;
/**
* X.509 certificate SHA-256 thumbprint, optional.
*/
private Base64URL x5t256;
/**
* The X.509 certificate chain, optional.
*/
private List x5c;
/**
* The key expiration time, optional.
*/
private Date exp;
/**
* The key not-before time, optional.
*/
private Date nbf;
/**
* The key issued-at time, optional.
*/
private Date iat;
/**
* The key revocation, optional.
*/
private KeyRevocation revocation;
/**
* Reference to the underlying key store, {@code null} if none.
*/
private KeyStore ks;
/**
* Creates a new Elliptic Curve JWK builder.
*
* @param crv The cryptographic curve. Must not be
* {@code null}.
* @param x The public 'x' coordinate for the elliptic curve
* point. It is represented as the Base64URL
* encoding of the coordinate's big endian
* representation. Must not be {@code null}.
* @param y The public 'y' coordinate for the elliptic curve
* point. It is represented as the Base64URL
* encoding of the coordinate's big endian
* representation. Must not be {@code null}.
*/
public Builder(final Curve crv, final Base64URL x, final Base64URL y) {
this.crv = Objects.requireNonNull(crv, "The curve must not be null");
this.x = Objects.requireNonNull(x, "The x coordinate must not be null");
this.y = Objects.requireNonNull(y, "The y coordinate must not be null");
}
/**
* Creates a new Elliptic Curve JWK builder.
*
* @param crv The cryptographic curve. Must not be
* {@code null}.
* @param pub The public EC key to represent. Must not be
* {@code null}.
*/
public Builder(final Curve crv, final ECPublicKey pub) {
this(crv,
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()),
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()));
}
/**
* Creates a new Elliptic Curve JWK builder.
*
* @param ecJWK The EC JWK to start with. Must not be
* {@code null}.
*/
public Builder(final ECKey ecJWK) {
crv = ecJWK.crv;
x = ecJWK.x;
y = ecJWK.y;
d = ecJWK.d;
priv = ecJWK.privateKey;
use = ecJWK.getKeyUse();
ops = ecJWK.getKeyOperations();
alg = ecJWK.getAlgorithm();
kid = ecJWK.getKeyID();
x5u = ecJWK.getX509CertURL();
x5t = ecJWK.getX509CertThumbprint();
x5t256 = ecJWK.getX509CertSHA256Thumbprint();
x5c = ecJWK.getX509CertChain();
exp = ecJWK.getExpirationTime();
nbf = ecJWK.getNotBeforeTime();
iat = ecJWK.getIssueTime();
revocation = ecJWK.getKeyRevocation();
ks = ecJWK.getKeyStore();
}
/**
* Sets the private 'd' coordinate for the elliptic curve
* point. The alternative method is {@link #privateKey}.
*
* @param d The private 'd' coordinate. It is represented as
* the Base64URL encoding of the coordinate's big
* endian representation. {@code null} if not
* specified (for a public key or private key
* specified otherwise).
*
* @return This builder.
*/
public Builder d(final Base64URL d) {
this.d = d;
return this;
}
/**
* Sets the private Elliptic Curve key. The alternative method
* is {@link #d}.
*
* @param priv The private EC key, used to obtain the private
* 'd' coordinate for the elliptic curve point.
* {@code null} if not specified (for a public
* key or private key specified otherwise).
*
* @return This builder.
*/
public Builder privateKey(final ECPrivateKey priv) {
if (priv != null) {
this.d = encodeCoordinate(priv.getParams().getCurve().getField().getFieldSize(), priv.getS());
} else {
this.d = null;
}
return this;
}
/**
* Sets the private EC key, typically for a key located in a
* PKCS#11 store that doesn't expose the private key parameters
* (such as a smart card or HSM).
*
* @param priv The private EC key reference. Its algorithm must
* be "EC". {@code null} if not specified (for a
* public key or private key specified otherwise).
*
* @return This builder.
*/
public Builder privateKey(final PrivateKey priv) {
if (priv instanceof ECPrivateKey) {
// We have the key material, set d coordinate instead
return privateKey((ECPrivateKey) priv);
}
if (priv != null && ! "EC".equalsIgnoreCase(priv.getAlgorithm())) {
throw new IllegalArgumentException("The private key algorithm must be EC");
}
this.priv = priv;
return this;
}
/**
* Sets the use ({@code use}) of the JWK.
*
* @param use The key use, {@code null} if not specified or if
* the key is intended for signing as well as
* encryption.
*
* @return This builder.
*/
public Builder keyUse(final KeyUse use) {
this.use = use;
return this;
}
/**
* Sets the operations ({@code key_ops}) of the JWK.
*
* @param ops The key operations, {@code null} if not
* specified.
*
* @return This builder.
*/
public Builder keyOperations(final Set ops) {
this.ops = ops;
return this;
}
/**
* Sets the intended JOSE algorithm ({@code alg}) for the JWK.
*
* @param alg The intended JOSE algorithm, {@code null} if not
* specified.
*
* @return This builder.
*/
public Builder algorithm(final Algorithm alg) {
this.alg = alg;
return this;
}
/**
* Sets the ID ({@code kid}) of the JWK. The key ID can be used
* to match a specific key. This can be used, for instance, to
* choose a key within a {@link JWKSet} during key rollover.
* The key ID may also correspond to a JWS/JWE {@code kid}
* header parameter value.
*
* @param kid The key ID, {@code null} if not specified.
*
* @return This builder.
*/
public Builder keyID(final String kid) {
this.kid = kid;
return this;
}
/**
* Sets the ID ({@code kid}) of the JWK to its SHA-256 JWK
* thumbprint (RFC 7638). The key ID can be used to match a
* specific key. This can be used, for instance, to choose a
* key within a {@link JWKSet} during key rollover. The key ID
* may also correspond to a JWS/JWE {@code kid} header
* parameter value.
*
* @return This builder.
*
* @throws JOSEException If the SHA-256 hash algorithm is not
* supported.
*/
public Builder keyIDFromThumbprint()
throws JOSEException {
return keyIDFromThumbprint("SHA-256");
}
/**
* Sets the ID ({@code kid}) of the JWK to its JWK thumbprint
* (RFC 7638). The key ID can be used to match a specific key.
* This can be used, for instance, to choose a key within a
* {@link JWKSet} during key rollover. The key ID may also
* correspond to a JWS/JWE {@code kid} header parameter value.
*
* @param hashAlg The hash algorithm for the JWK thumbprint
* computation. Must not be {@code null}.
*
* @return This builder.
*
* @throws JOSEException If the hash algorithm is not
* supported.
*/
public Builder keyIDFromThumbprint(final String hashAlg)
throws JOSEException {
// Put mandatory params in sorted order
LinkedHashMap requiredParams = new LinkedHashMap<>();
requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE, crv.toString());
requiredParams.put(JWKParameterNames.KEY_TYPE, KeyType.EC.getValue());
requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE_X_COORDINATE, x.toString());
requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE_Y_COORDINATE, y.toString());
this.kid = ThumbprintUtils.compute(hashAlg, requiredParams).toString();
return this;
}
/**
* Sets the X.509 certificate URL ({@code x5u}) of the JWK.
*
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
*
* @return This builder.
*/
public Builder x509CertURL(final URI x5u) {
this.x5u = x5u;
return this;
}
/**
* Sets the X.509 certificate SHA-1 thumbprint ({@code x5t}) of
* the JWK.
*
* @param x5t The X.509 certificate SHA-1 thumbprint,
* {@code null} if not specified.
*
* @return This builder.
*/
@Deprecated
public Builder x509CertThumbprint(final Base64URL x5t) {
this.x5t = x5t;
return this;
}
/**
* Sets the X.509 certificate SHA-256 thumbprint
* ({@code x5t#S256}) of the JWK.
*
* @param x5t256 The X.509 certificate SHA-256 thumbprint,
* {@code null} if not specified.
*
* @return This builder.
*/
public Builder x509CertSHA256Thumbprint(final Base64URL x5t256) {
this.x5t256 = x5t256;
return this;
}
/**
* Sets the X.509 certificate chain ({@code x5c}) of the JWK.
*
* @param x5c The X.509 certificate chain as a unmodifiable
* list, {@code null} if not specified.
*
* @return This builder.
*/
public Builder x509CertChain(final List x5c) {
this.x5c = x5c;
return this;
}
/**
* Sets the expiration time ({@code exp}) of the JWK.
*
* @param exp The expiration time, {@code null} if not
* specified.
*
* @return This builder.
*/
public Builder expirationTime(final Date exp) {
this.exp = exp;
return this;
}
/**
* Sets the not-before time ({@code nbf}) of the JWK.
*
* @param nbf The not-before time, {@code null} if not
* specified.
*
* @return This builder.
*/
public Builder notBeforeTime(final Date nbf) {
this.nbf = nbf;
return this;
}
/**
* Sets the issued-at time ({@code iat}) of the JWK.
*
* @param iat The issued-at time, {@code null} if not
* specified.
*
* @return This builder.
*/
public Builder issueTime(final Date iat) {
this.iat = iat;
return this;
}
/**
* Sets the revocation ({@code revoked}) of the JWK.
*
* @param revocation The key revocation, {@code null} if not
* specified.
*
* @return This builder.
*/
public Builder keyRevocation(final KeyRevocation revocation) {
this.revocation = revocation;
return this;
}
/**
* Sets the underlying key store.
*
* @param keyStore Reference to the underlying key store,
* {@code null} if none.
*
* @return This builder.
*/
public Builder keyStore(final KeyStore keyStore) {
this.ks = keyStore;
return this;
}
/**
* Builds a new Elliptic Curve JWK.
*
* @return The Elliptic Curve JWK.
*
* @throws IllegalStateException If the JWK parameters were
* inconsistently specified.
*/
public ECKey build() {
try {
if (d == null && priv == null) {
// Public key
return new ECKey(crv, x, y, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, revocation, ks);
}
if (priv != null) {
// PKCS#11 reference to private key
return new ECKey(crv, x, y, priv, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, revocation, ks);
}
// Public / private key pair with 'd'
return new ECKey(crv, x, y, d, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, revocation, ks);
} catch (IllegalArgumentException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
}
/**
* Returns the Base64URL encoding of the specified elliptic curve 'x',
* 'y' or 'd' coordinate, with leading zero padding up to the specified
* field size in bits.
*
* @param fieldSize The field size in bits.
* @param coordinate The elliptic curve coordinate. Must not be
* {@code null}.
*
* @return The Base64URL-encoded coordinate, with leading zero padding
* up to the curve's field size.
*/
public static Base64URL encodeCoordinate(final int fieldSize, final BigInteger coordinate) {
final byte[] notPadded = BigIntegerUtils.toBytesUnsigned(coordinate);
int bytesToOutput = (fieldSize + 7)/8;
if (notPadded.length >= bytesToOutput) {
// Greater-than check to prevent exception on malformed
// key below
return Base64URL.encode(notPadded);
}
final byte[] padded = new byte[bytesToOutput];
System.arraycopy(notPadded, 0, padded, bytesToOutput - notPadded.length, notPadded.length);
return Base64URL.encode(padded);
}
/**
* The curve name.
*/
private final Curve crv;
/**
* The public 'x' EC coordinate.
*/
private final Base64URL x;
/**
* The public 'y' EC coordinate.
*/
private final Base64URL y;
/**
* The private 'd' EC coordinate.
*/
private final Base64URL d;
/**
* Private PKCS#11 key handle.
*/
private final PrivateKey privateKey;
/**
* Ensures the specified 'x' and 'y' public coordinates are on the
* given curve.
*
* @param crv The curve. Must not be {@code null}.
* @param x The public 'x' coordinate. Must not be {@code null}.
* @param y The public 'y' coordinate. Must not be {@code null}.
*/
private static void ensurePublicCoordinatesOnCurve(final Curve crv, final Base64URL x, final Base64URL y) {
if (! SUPPORTED_CURVES.contains(crv)) {
throw new IllegalArgumentException("Unknown / unsupported curve: " + crv);
}
if (! ECChecks.isPointOnCurve(x.decodeToBigInteger(), y.decodeToBigInteger(), crv.toECParameterSpec())) {
throw new IllegalArgumentException("Invalid EC JWK: The 'x' and 'y' public coordinates are not on the " + crv + " curve");
}
}
/**
* Creates a new public Elliptic Curve JSON Web Key (JWK) with the
* specified parameters.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param x The public 'x' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding of
* the coordinate's big endian representation. Must not
* be {@code null}.
* @param y The public 'y' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding of
* the coordinate's big endian representation. Must not
* be {@code null}.
* @param use The key use, {@code null} if not specified or if the
* key is intended for signing as well as encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key, {@code null}
* if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint, {@code null}
* if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null}
* if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param ks Reference to the underlying key store, {@code null} if
* not specified.
*/
@Deprecated
public ECKey(final Curve crv, final Base64URL x, final Base64URL y,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final KeyStore ks) {
this(crv, x, y, use, ops, alg, kid, x5u, x5t, x5t256, x5c, null, null, null, ks);
}
/**
* Creates a new public / private Elliptic Curve JSON Web Key (JWK)
* with the specified parameters.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param x The public 'x' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding of
* the coordinate's big endian representation. Must not
* be {@code null}.
* @param y The public 'y' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding of
* the coordinate's big endian representation. Must not
* be {@code null}.
* @param d The private 'd' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding of
* the coordinate's big endian representation. Must not
* be {@code null}.
* @param use The key use, {@code null} if not specified or if the
* key is intended for signing as well as encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key, {@code null}
* if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint, {@code null}
* if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null}
* if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param ks Reference to the underlying key store, {@code null} if
* not specified.
*/
@Deprecated
public ECKey(final Curve crv, final Base64URL x, final Base64URL y, final Base64URL d,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final KeyStore ks) {
this(crv, x, y, d, use, ops, alg, kid, x5u, x5t, x5t256, x5c, null, null, null, ks);
}
/**
* Creates a new public / private Elliptic Curve JSON Web Key (JWK)
* with the specified parameters. The private key is specified by its
* PKCS#11 handle.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param x The public 'x' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding of
* the coordinate's big endian representation. Must not
* be {@code null}.
* @param y The public 'y' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding of
* the coordinate's big endian representation. Must not
* be {@code null}.
* @param priv The private key as a PKCS#11 handle, {@code null} if
* not specified.
* @param use The key use, {@code null} if not specified or if the
* key is intended for signing as well as encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key, {@code null}
* if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint, {@code null}
* if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null}
* if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param ks Reference to the underlying key store, {@code null} if
* not specified.
*/
@Deprecated
public ECKey(final Curve crv, final Base64URL x, final Base64URL y, final PrivateKey priv,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final KeyStore ks) {
this(crv, x, y, priv, use, ops, alg, kid, x5u, x5t, x5t256, x5c, null, null, null, ks);
}
/**
* Creates a new public Elliptic Curve JSON Web Key (JWK) with the
* specified parameters.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param pub The public EC key to represent. Must not be
* {@code null}.
* @param use The key use, {@code null} if not specified or if the
* key is intended for signing as well as encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key, {@code null}
* if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint, {@code null}
* if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null}
* if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param ks Reference to the underlying key store, {@code null} if
* not specified.
*/
@Deprecated
public ECKey(final Curve crv, final ECPublicKey pub,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final KeyStore ks) {
this(crv,
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()),
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()),
use, ops, alg, kid,
x5u, x5t, x5t256, x5c,
null, null, null,
ks);
}
/**
* Creates a new public / private Elliptic Curve JSON Web Key (JWK)
* with the specified parameters.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param pub The public EC key to represent. Must not be
* {@code null}.
* @param priv The private EC key to represent. Must not be
* {@code null}.
* @param use The key use, {@code null} if not specified or if the
* key is intended for signing as well as encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key, {@code null}
* if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint, {@code null}
* if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null}
* if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param ks Reference to the underlying key store, {@code null} if
* not specified.
*/
@Deprecated
public ECKey(final Curve crv, final ECPublicKey pub, final ECPrivateKey priv,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final KeyStore ks) {
this(crv,
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()),
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()),
encodeCoordinate(priv.getParams().getCurve().getField().getFieldSize(), priv.getS()),
use, ops, alg, kid,
x5u, x5t, x5t256, x5c,
null, null, null,
ks);
}
/**
* Creates a new public / private Elliptic Curve JSON Web Key (JWK)
* with the specified parameters. The private key is specified by its
* PKCS#11 handle.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param pub The public EC key to represent. Must not be
* {@code null}.
* @param priv The private key as a PKCS#11 handle, {@code null} if
* not specified.
* @param use The key use, {@code null} if not specified or if the
* key is intended for signing as well as encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key, {@code null}
* if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint, {@code null}
* if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null}
* if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param ks Reference to the underlying key store, {@code null} if
* not specified.
*/
@Deprecated
public ECKey(final Curve crv, final ECPublicKey pub, final PrivateKey priv,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final KeyStore ks) {
this(
crv,
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()),
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()),
priv,
use, ops, alg, kid, x5u, x5t, x5t256, x5c,
null, null, null,
ks);
}
/**
* Creates a new public Elliptic Curve JSON Web Key (JWK) with the
* specified parameters.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param x The public 'x' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding of
* the coordinate's big endian representation. Must not
* be {@code null}.
* @param y The public 'y' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding of
* the coordinate's big endian representation. Must not
* be {@code null}.
* @param use The key use, {@code null} if not specified or if the
* key is intended for signing as well as encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key, {@code null}
* if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint, {@code null}
* if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null}
* if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param exp The key expiration time, {@code null} if not
* specified.
* @param nbf The key not-before time, {@code null} if not
* specified.
* @param iat The key issued-at time, {@code null} if not specified.
* @param ks Reference to the underlying key store, {@code null} if
* not specified.
*/
@Deprecated
public ECKey(final Curve crv, final Base64URL x, final Base64URL y,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final Date exp, final Date nbf, final Date iat,
final KeyStore ks) {
this(crv, x, y, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, null, ks);
}
// JWK public
/**
* Creates a new public Elliptic Curve JSON Web Key (JWK) with the
* specified parameters.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param x The public 'x' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding
* of the coordinate's big endian representation.
* Must not be {@code null}.
* @param y The public 'y' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding
* of the coordinate's big endian representation.
* Must not be {@code null}.
* @param use The key use, {@code null} if not specified or if
* the key is intended for signing as well as
* encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key,
* {@code null} if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint,
* {@code null} if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint,
* {@code null} if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param exp The key expiration time, {@code null} if not
* specified.
* @param nbf The key not-before time, {@code null} if not
* specified.
* @param iat The key issued-at time, {@code null} if not
* specified.
* @param revocation The key revocation, {@code null} if not specified.
* @param ks Reference to the underlying key store,
* {@code null} if not specified.
*/
public ECKey(final Curve crv, final Base64URL x, final Base64URL y,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final Date exp, final Date nbf, final Date iat, final KeyRevocation revocation,
final KeyStore ks) {
super(KeyType.EC, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, revocation, ks);
this.crv = Objects.requireNonNull(crv, "The curve must not be null");
this.x = Objects.requireNonNull(x, "The x coordinate must not be null");
this.y = Objects.requireNonNull(y, "The y coordinate must not be null");
ensurePublicCoordinatesOnCurve(crv, x, y);
ensureMatches(getParsedX509CertChain());
this.d = null;
this.privateKey = null;
}
/**
* Creates a new public / private Elliptic Curve JSON Web Key (JWK)
* with the specified parameters.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param x The public 'x' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding of
* the coordinate's big endian representation. Must not
* be {@code null}.
* @param y The public 'y' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding of
* the coordinate's big endian representation. Must not
* be {@code null}.
* @param d The private 'd' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding of
* the coordinate's big endian representation. Must not
* be {@code null}.
* @param use The key use, {@code null} if not specified or if the
* key is intended for signing as well as encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key, {@code null}
* if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint, {@code null}
* if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null}
* if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param exp The key expiration time, {@code null} if not
* specified.
* @param nbf The key not-before time, {@code null} if not
* specified.
* @param iat The key issued-at time, {@code null} if not specified.
* @param ks Reference to the underlying key store, {@code null} if
* not specified.
*/
@Deprecated
public ECKey(final Curve crv, final Base64URL x, final Base64URL y, final Base64URL d,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final Date exp, final Date nbf, final Date iat,
final KeyStore ks) {
this(crv, x, y, d, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, null, ks);
}
// JWK public + private
/**
* Creates a new public / private Elliptic Curve JSON Web Key (JWK)
* with the specified parameters.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param x The public 'x' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding
* of the coordinate's big endian representation.
* Must not be {@code null}.
* @param y The public 'y' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding
* of the coordinate's big endian representation.
* Must not be {@code null}.
* @param d The private 'd' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding
* of the coordinate's big endian representation.
* Must not be {@code null}.
* @param use The key use, {@code null} if not specified or if
* the key is intended for signing as well as
* encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key,
* {@code null} if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint,
* {@code null} if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint,
* {@code null} if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param exp The key expiration time, {@code null} if not
* specified.
* @param nbf The key not-before time, {@code null} if not
* specified.
* @param iat The key issued-at time, {@code null} if not
* specified.
* @param revocation The key revocation, {@code null} if not specified.
* @param ks Reference to the underlying key store,
* {@code null} if not specified.
*/
public ECKey(final Curve crv, final Base64URL x, final Base64URL y, final Base64URL d,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final Date exp, final Date nbf, final Date iat, final KeyRevocation revocation,
final KeyStore ks) {
super(KeyType.EC, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, revocation, ks);
this.crv = Objects.requireNonNull(crv, "The curve must not be null");
this.x = Objects.requireNonNull(x, "The x coordinate must not be null");
this.y = Objects.requireNonNull(y, "The y coordinate must not be null");
ensurePublicCoordinatesOnCurve(crv, x, y);
ensureMatches(getParsedX509CertChain());
this.d = Objects.requireNonNull(d, "The d coordinate must not be null");
this.privateKey = null;
}
/**
* Creates a new public / private Elliptic Curve JSON Web Key (JWK)
* with the specified parameters. The private key is specified by its
* PKCS#11 handle.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param x The public 'x' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding of
* the coordinate's big endian representation. Must not
* be {@code null}.
* @param y The public 'y' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding of
* the coordinate's big endian representation. Must not
* be {@code null}.
* @param priv The private key as a PKCS#11 handle, {@code null} if
* not specified.
* @param use The key use, {@code null} if not specified or if the
* key is intended for signing as well as encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key, {@code null}
* if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint, {@code null}
* if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null}
* if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param exp The key expiration time, {@code null} if not
* specified.
* @param nbf The key not-before time, {@code null} if not
* specified.
* @param iat The key issued-at time, {@code null} if not specified.
* @param ks Reference to the underlying key store, {@code null} if
* not specified.
*/
@Deprecated
public ECKey(final Curve crv, final Base64URL x, final Base64URL y, final PrivateKey priv,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final Date exp, final Date nbf, final Date iat,
final KeyStore ks) {
this(crv, x, y, priv, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, null, ks);
}
// JWK public + private handle
/**
* Creates a new public / private Elliptic Curve JSON Web Key (JWK)
* with the specified parameters. The private key is specified by its
* PKCS#11 handle.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param x The public 'x' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding
* of the coordinate's big endian representation.
* Must not be {@code null}.
* @param y The public 'y' coordinate for the elliptic curve
* point. It is represented as the Base64URL encoding
* of the coordinate's big endian representation.
* Must not be {@code null}.
* @param priv The private key as a PKCS#11 handle, {@code null}
* if not specified.
* @param use The key use, {@code null} if not specified or if
* the key is intended for signing as well as
* encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key,
* {@code null} if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint,
* {@code null} if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint,
* {@code null} if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param exp The key expiration time, {@code null} if not
* specified.
* @param nbf The key not-before time, {@code null} if not
* specified.
* @param iat The key issued-at time, {@code null} if not
* specified.
* @param revocation The key revocation, {@code null} if not specified.
* @param ks Reference to the underlying key store,
* {@code null} if not specified.
*/
public ECKey(final Curve crv, final Base64URL x, final Base64URL y, final PrivateKey priv,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final Date exp, final Date nbf, final Date iat, final KeyRevocation revocation,
final KeyStore ks) {
super(KeyType.EC, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, revocation, ks);
this.crv = Objects.requireNonNull(crv, "The curve must not be null");
this.x = Objects.requireNonNull(x, "The x coordinate must not be null");
this.y = Objects.requireNonNull(y, "The y coordinate must not be null");
ensurePublicCoordinatesOnCurve(crv, x, y);
ensureMatches(getParsedX509CertChain());
d = null;
this.privateKey = priv;
}
/**
* Creates a new public Elliptic Curve JSON Web Key (JWK) with the
* specified parameters.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param pub The public EC key to represent. Must not be
* {@code null}.
* @param use The key use, {@code null} if not specified or if the
* key is intended for signing as well as encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key, {@code null}
* if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint, {@code null}
* if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null}
* if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param exp The key expiration time, {@code null} if not
* specified.
* @param nbf The key not-before time, {@code null} if not
* specified.
* @param iat The key issued-at time, {@code null} if not specified.
* @param ks Reference to the underlying key store, {@code null} if
* not specified.
*/
@Deprecated
public ECKey(final Curve crv, final ECPublicKey pub,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final Date exp, final Date nbf, final Date iat,
final KeyStore ks) {
this(crv, pub, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, null, ks);
}
// Java public
/**
* Creates a new public Elliptic Curve JSON Web Key (JWK) with the
* specified parameters.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param pub The public EC key to represent. Must not be
* {@code null}.
* @param use The key use, {@code null} if not specified or if
* the key is intended for signing as well as
* encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key,
* {@code null} if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint,
* {@code null} if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint,
* {@code null} if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param exp The key expiration time, {@code null} if not
* specified.
* @param nbf The key not-before time, {@code null} if not
* specified.
* @param iat The key issued-at time, {@code null} if not
* specified.
* @param revocation The key revocation, {@code null} if not specified.
* @param ks Reference to the underlying key store,
* {@code null} if not specified.
*/
public ECKey(final Curve crv, final ECPublicKey pub,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final Date exp, final Date nbf, final Date iat, final KeyRevocation revocation,
final KeyStore ks) {
this(crv,
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()),
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()),
use, ops, alg, kid,
x5u, x5t, x5t256, x5c,
exp, nbf, iat, revocation,
ks);
}
/**
* Creates a new public / private Elliptic Curve JSON Web Key (JWK)
* with the specified parameters.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param pub The public EC key to represent. Must not be
* {@code null}.
* @param priv The private EC key to represent. Must not be
* {@code null}.
* @param use The key use, {@code null} if not specified or if the
* key is intended for signing as well as encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key, {@code null}
* if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint, {@code null}
* if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null}
* if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param exp The key expiration time, {@code null} if not
* specified.
* @param nbf The key not-before time, {@code null} if not
* specified.
* @param iat The key issued-at time, {@code null} if not specified.
* @param ks Reference to the underlying key store, {@code null} if
* not specified.
*/
@Deprecated
public ECKey(final Curve crv, final ECPublicKey pub, final ECPrivateKey priv,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final Date exp, final Date nbf, final Date iat,
final KeyStore ks) {
this(crv, pub, priv, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, null, ks);
}
// Java public + private
/**
* Creates a new public / private Elliptic Curve JSON Web Key (JWK)
* with the specified parameters.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param pub The public EC key to represent. Must not be
* {@code null}.
* @param priv The private EC key to represent. Must not be
* {@code null}.
* @param use The key use, {@code null} if not specified or if
* the key is intended for signing as well as
* encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key,
* {@code null} if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint,
* {@code null} if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint,
* {@code null} if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param exp The key expiration time, {@code null} if not
* specified.
* @param nbf The key not-before time, {@code null} if not
* specified.
* @param iat The key issued-at time, {@code null} if not
* specified.
* @param revocation The key revocation, {@code null} if not specified.
* @param ks Reference to the underlying key store,
* {@code null} if not specified.
*/
public ECKey(final Curve crv, final ECPublicKey pub, final ECPrivateKey priv,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final Date exp, final Date nbf, final Date iat, final KeyRevocation revocation,
final KeyStore ks) {
this(crv,
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()),
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()),
encodeCoordinate(priv.getParams().getCurve().getField().getFieldSize(), priv.getS()),
use, ops, alg, kid,
x5u, x5t, x5t256, x5c,
exp, nbf, iat, revocation,
ks);
}
/**
* Creates a new public / private Elliptic Curve JSON Web Key (JWK)
* with the specified parameters. The private key is specified by its
* PKCS#11 handle.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param pub The public EC key to represent. Must not be
* {@code null}.
* @param priv The private key as a PKCS#11 handle, {@code null} if
* not specified.
* @param use The key use, {@code null} if not specified or if the
* key is intended for signing as well as encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key, {@code null}
* if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint, {@code null}
* if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null}
* if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param exp The key expiration time, {@code null} if not
* specified.
* @param nbf The key not-before time, {@code null} if not
* specified.
* @param iat The key issued-at time, {@code null} if not specified.
* @param ks Reference to the underlying key store, {@code null} if
* not specified.
*/
@Deprecated
public ECKey(final Curve crv, final ECPublicKey pub, final PrivateKey priv,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final Date exp, final Date nbf, final Date iat,
final KeyStore ks) {
this(
crv,
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()),
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()),
priv,
use, ops, alg, kid, x5u, x5t, x5t256, x5c,
exp, nbf, iat,
ks);
}
// Java public + private handle
/**
* Creates a new public / private Elliptic Curve JSON Web Key (JWK)
* with the specified parameters. The private key is specified by its
* PKCS#11 handle.
*
* @param crv The cryptographic curve. Must not be {@code null}.
* @param pub The public EC key to represent. Must not be
* {@code null}.
* @param priv The private key as a PKCS#11 handle, {@code null}
* if not specified.
* @param use The key use, {@code null} if not specified or if
* the key is intended for signing as well as
* encryption.
* @param ops The key operations, {@code null} if not specified.
* @param alg The intended JOSE algorithm for the key,
* {@code null} if not specified.
* @param kid The key ID, {@code null} if not specified.
* @param x5u The X.509 certificate URL, {@code null} if not
* specified.
* @param x5t The X.509 certificate SHA-1 thumbprint,
* {@code null} if not specified.
* @param x5t256 The X.509 certificate SHA-256 thumbprint,
* {@code null} if not specified.
* @param x5c The X.509 certificate chain, {@code null} if not
* specified.
* @param exp The key expiration time, {@code null} if not
* specified.
* @param nbf The key not-before time, {@code null} if not
* specified.
* @param iat The key issued-at time, {@code null} if not
* specified.
* @param revocation The key revocation, {@code null} if not specified.
* @param ks Reference to the underlying key store,
* {@code null} if not specified.
*/
public ECKey(final Curve crv, final ECPublicKey pub, final PrivateKey priv,
final KeyUse use, final Set ops, final Algorithm alg, final String kid,
final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List x5c,
final Date exp, final Date nbf, final Date iat, final KeyRevocation revocation,
final KeyStore ks) {
this(
crv,
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()),
encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()),
priv,
use, ops, alg, kid, x5u, x5t, x5t256, x5c,
exp, nbf, iat, revocation,
ks);
}
@Override
public Curve getCurve() {
return crv;
}
/**
* Gets the public 'x' coordinate for the elliptic curve point.
*
* @return The 'x' coordinate. It is represented as the Base64URL
* encoding of the coordinate's big endian representation.
*/
public Base64URL getX() {
return x;
}
/**
* Gets the public 'y' coordinate for the elliptic curve point.
*
* @return The 'y' coordinate. It is represented as the Base64URL
* encoding of the coordinate's big endian representation.
*/
public Base64URL getY() {
return y;
}
/**
* Gets the private 'd' coordinate for the elliptic curve point. It is
* represented as the Base64URL encoding of the coordinate's big endian
* representation.
*
* @return The 'd' coordinate. It is represented as the Base64URL
* encoding of the coordinate's big endian representation.
* {@code null} if not specified (for a public key).
*/
public Base64URL getD() {
return d;
}
/**
* Returns a standard {@code java.security.interfaces.ECPublicKey}
* representation of this Elliptic Curve JWK. Uses the default JCA
* provider.
*
* @return The public Elliptic Curve key.
*
* @throws JOSEException If EC is not supported by the underlying Java
* Cryptography (JCA) provider or if the JWK
* parameters are invalid for a public EC key.
*/
public ECPublicKey toECPublicKey()
throws JOSEException {
return toECPublicKey(null);
}
/**
* Returns a standard {@code java.security.interfaces.ECPublicKey}
* representation of this Elliptic Curve JWK.
*
* @param provider The JCA provider to use, {@code null} implies the
* default.
*
* @return The public Elliptic Curve key.
*
* @throws JOSEException If EC is not supported by the underlying Java
* Cryptography (JCA) provider or if the JWK
* parameters are invalid for a public EC key.
*/
public ECPublicKey toECPublicKey(final Provider provider)
throws JOSEException {
ECParameterSpec spec = crv.toECParameterSpec();
if (spec == null) {
throw new JOSEException("Couldn't get EC parameter spec for curve " + crv);
}
ECPoint w = new ECPoint(x.decodeToBigInteger(), y.decodeToBigInteger());
ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(w, spec);
try {
KeyFactory keyFactory;
if (provider == null) {
keyFactory = KeyFactory.getInstance("EC");
} else {
keyFactory = KeyFactory.getInstance("EC", provider);
}
return (ECPublicKey) keyFactory.generatePublic(publicKeySpec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new JOSEException(e.getMessage(), e);
}
}
/**
* Returns a standard {@code java.security.interfaces.ECPrivateKey}
* representation of this Elliptic Curve JWK. Uses the default JCA
* provider.
*
* @return The private Elliptic Curve key, {@code null} if not
* specified by this JWK.
*
* @throws JOSEException If EC is not supported by the underlying Java
* Cryptography (JCA) provider or if the JWK
* parameters are invalid for a private EC key.
*/
public ECPrivateKey toECPrivateKey()
throws JOSEException {
return toECPrivateKey(null);
}
/**
* Returns a standard {@code java.security.interfaces.ECPrivateKey}
* representation of this Elliptic Curve JWK.
*
* @param provider The JCA provider to use, {@code null} implies the
* default.
*
* @return The private Elliptic Curve key, {@code null} if not
* specified by this JWK.
*
* @throws JOSEException If EC is not supported by the underlying Java
* Cryptography (JCA) provider or if the JWK
* parameters are invalid for a private EC key.
*/
public ECPrivateKey toECPrivateKey(final Provider provider)
throws JOSEException {
if (d == null) {
// No private 'd' param
return null;
}
ECParameterSpec spec = crv.toECParameterSpec();
if (spec == null) {
throw new JOSEException("Couldn't get EC parameter spec for curve " + crv);
}
ECPrivateKeySpec privateKeySpec = new ECPrivateKeySpec(d.decodeToBigInteger(), spec);
try {
KeyFactory keyFactory;
if (provider == null) {
keyFactory = KeyFactory.getInstance("EC");
} else {
keyFactory = KeyFactory.getInstance("EC", provider);
}
return (ECPrivateKey) keyFactory.generatePrivate(privateKeySpec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new JOSEException(e.getMessage(), e);
}
}
@Override
public PublicKey toPublicKey()
throws JOSEException {
return toECPublicKey();
}
@Override
public PrivateKey toPrivateKey()
throws JOSEException {
PrivateKey prv = toECPrivateKey();
if (prv != null) {
// Return private EC key with key material
return prv;
}
// Return private EC key as PKCS#11 handle, or null
return privateKey;
}
/**
* Returns a standard {@code java.security.KeyPair} representation of
* this Elliptic Curve JWK. Uses the default JCA provider.
*
* @return The Elliptic Curve key pair. The private Elliptic Curve key
* will be {@code null} if not specified.
*
* @throws JOSEException If EC is not supported by the underlying Java
* Cryptography (JCA) provider or if the JWK
* parameters are invalid for a public and / or
* private EC key.
*/
@Override
public KeyPair toKeyPair()
throws JOSEException {
return toKeyPair(null);
}
/**
* Returns a standard {@code java.security.KeyPair} representation of
* this Elliptic Curve JWK.
*
* @param provider The JCA provider to use, {@code null} implies the
* default.
*
* @return The Elliptic Curve key pair. The private Elliptic Curve key
* will be {@code null} if not specified.
*
* @throws JOSEException If EC is not supported by the underlying Java
* Cryptography (JCA) provider or if the JWK
* parameters are invalid for a public and / or
* private EC key.
*/
public KeyPair toKeyPair(final Provider provider)
throws JOSEException {
if (privateKey != null) {
// Private key as PKCS#11 handle
return new KeyPair(toECPublicKey(provider), privateKey);
} else {
return new KeyPair(toECPublicKey(provider), toECPrivateKey(provider));
}
}
@Override
public boolean matches(final X509Certificate cert) {
ECPublicKey certECKey;
try {
certECKey = (ECPublicKey) getParsedX509CertChain().get(0).getPublicKey();
} catch (ClassCastException ex) {
return false;
}
// Compare Big Ints, base64url encoding may have padding!
// https://tools.ietf.org/html/rfc7518#section-6.2.1.2
if (! getX().decodeToBigInteger().equals(certECKey.getW().getAffineX())) {
return false;
}
return getY().decodeToBigInteger().equals(certECKey.getW().getAffineY());
}
/**
* Calls {@link #matches(X509Certificate)} for the first X.509
* certificate in the specified chain.
*
* @param chain The X.509 certificate chain, {@code null} if not
* specified.
*
* @throws IllegalArgumentException If a certificate chain is specified
* and the first certificate in it
* doesn't match.
*/
private void ensureMatches(final List chain) {
if (chain == null)
return;
if (! matches(chain.get(0)))
throw new IllegalArgumentException("The public subject key info of the first X.509 certificate in the chain must match the JWK type and public parameters");
}
@Override
public LinkedHashMap getRequiredParams() {
// Put mandatory params in sorted order
LinkedHashMap requiredParams = new LinkedHashMap<>();
requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE, crv.toString());
requiredParams.put(JWKParameterNames.KEY_TYPE, getKeyType().getValue());
requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE_X_COORDINATE, x.toString());
requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE_Y_COORDINATE, y.toString());
return requiredParams;
}
@Override
public boolean isPrivate() {
return d != null || privateKey != null;
}
@Override
public int size() {
ECParameterSpec ecParameterSpec = crv.toECParameterSpec();
if (ecParameterSpec == null) {
throw new UnsupportedOperationException("Couldn't determine field size for curve " + crv.getName());
}
return ecParameterSpec.getCurve().getField().getFieldSize();
}
/**
* Returns a copy of this Elliptic Curve JWK with any private values
* removed.
*
* @return The copied public Elliptic Curve JWK.
*/
@Override
public ECKey toPublicJWK() {
return new ECKey(
getCurve(), getX(), getY(),
getKeyUse(), getKeyOperations(), getAlgorithm(), getKeyID(),
getX509CertURL(), getX509CertThumbprint(), getX509CertSHA256Thumbprint(), getX509CertChain(),
getExpirationTime(), getNotBeforeTime(), getIssueTime(), getKeyRevocation(),
getKeyStore());
}
@Override
public Map toJSONObject() {
Map o = super.toJSONObject();
// Append EC specific attributes
o.put(JWKParameterNames.ELLIPTIC_CURVE, crv.toString());
o.put(JWKParameterNames.ELLIPTIC_CURVE_X_COORDINATE, x.toString());
o.put(JWKParameterNames.ELLIPTIC_CURVE_Y_COORDINATE, y.toString());
if (d != null) {
o.put(JWKParameterNames.ELLIPTIC_CURVE_PRIVATE_KEY, d.toString());
}
return o;
}
/**
* Parses a public / private Elliptic Curve JWK from the specified JSON
* object string representation.
*
* @param s The JSON object string to parse. Must not be {@code null}.
*
* @return The public / private Elliptic Curve JWK.
*
* @throws ParseException If the string couldn't be parsed to an
* Elliptic Curve JWK.
*/
public static ECKey parse(final String s)
throws ParseException {
return parse(JSONObjectUtils.parse(s));
}
/**
* Parses a public / private Elliptic Curve JWK from the specified JSON
* object representation.
*
* @param jsonObject The JSON object to parse. Must not be
* {@code null}.
*
* @return The public / private Elliptic Curve JWK.
*
* @throws ParseException If the JSON object couldn't be parsed to an
* Elliptic Curve JWK.
*/
public static ECKey parse(final Map jsonObject)
throws ParseException {
// Check key type
if (! KeyType.EC.equals(JWKMetadata.parseKeyType(jsonObject))) {
throw new ParseException("The key type \"kty\" must be EC", 0);
}
// Parse the mandatory public key parameters
Curve crv;
try {
crv = Curve.parse(JSONObjectUtils.getString(jsonObject, JWKParameterNames.ELLIPTIC_CURVE));
} catch (IllegalArgumentException e) {
throw new ParseException(e.getMessage(), 0);
}
Base64URL x = JSONObjectUtils.getBase64URL(jsonObject, JWKParameterNames.ELLIPTIC_CURVE_X_COORDINATE);
Base64URL y = JSONObjectUtils.getBase64URL(jsonObject, JWKParameterNames.ELLIPTIC_CURVE_Y_COORDINATE);
// Get optional private key
Base64URL d = JSONObjectUtils.getBase64URL(jsonObject, JWKParameterNames.ELLIPTIC_CURVE_PRIVATE_KEY);
try {
if (d == null) {
// Public key
return new ECKey(crv, x, y,
JWKMetadata.parseKeyUse(jsonObject),
JWKMetadata.parseKeyOperations(jsonObject),
JWKMetadata.parseAlgorithm(jsonObject),
JWKMetadata.parseKeyID(jsonObject),
JWKMetadata.parseX509CertURL(jsonObject),
JWKMetadata.parseX509CertThumbprint(jsonObject),
JWKMetadata.parseX509CertSHA256Thumbprint(jsonObject),
JWKMetadata.parseX509CertChain(jsonObject),
JWKMetadata.parseExpirationTime(jsonObject),
JWKMetadata.parseNotBeforeTime(jsonObject),
JWKMetadata.parseIssueTime(jsonObject),
JWKMetadata.parseKeyRevocation(jsonObject),
null);
} else {
// Key pair
return new ECKey(crv, x, y, d,
JWKMetadata.parseKeyUse(jsonObject),
JWKMetadata.parseKeyOperations(jsonObject),
JWKMetadata.parseAlgorithm(jsonObject),
JWKMetadata.parseKeyID(jsonObject),
JWKMetadata.parseX509CertURL(jsonObject),
JWKMetadata.parseX509CertThumbprint(jsonObject),
JWKMetadata.parseX509CertSHA256Thumbprint(jsonObject),
JWKMetadata.parseX509CertChain(jsonObject),
JWKMetadata.parseExpirationTime(jsonObject),
JWKMetadata.parseNotBeforeTime(jsonObject),
JWKMetadata.parseIssueTime(jsonObject),
JWKMetadata.parseKeyRevocation(jsonObject),
null);
}
} catch (Exception ex) {
// Missing x or y, conflicting 'use' and 'key_ops'
throw new ParseException(ex.getMessage(), 0);
}
}
/**
* Parses a public Elliptic Curve JWK from the specified X.509
* certificate. Requires BouncyCastle.
*
* Important: The X.509 certificate is not
* validated!
*
*
Sets the following JWK parameters:
*
*
* - The curve is obtained from the subject public key info
* algorithm parameters.
*
- The JWK use inferred by {@link KeyUse#from}.
*
- The JWK ID from the X.509 serial number (in base 10).
*
- The JWK X.509 certificate chain (this certificate only).
*
- The JWK X.509 certificate SHA-256 thumbprint.
*
*
* @param cert The X.509 certificate. Must not be {@code null}.
*
* @return The public Elliptic Curve JWK.
*
* @throws JOSEException If parsing failed.
*/
public static ECKey parse(final X509Certificate cert)
throws JOSEException {
if (! (cert.getPublicKey() instanceof ECPublicKey)) {
throw new JOSEException("The public key of the X.509 certificate is not EC");
}
ECPublicKey publicKey = (ECPublicKey) cert.getPublicKey();
try {
JcaX509CertificateHolder certHolder = new JcaX509CertificateHolder(cert);
String oid = certHolder.getSubjectPublicKeyInfo().getAlgorithm().getParameters().toString();
Curve crv = Curve.forOID(oid);
if (crv == null) {
throw new JOSEException("Couldn't determine EC JWK curve for OID " + oid);
}
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
return new ECKey.Builder(crv, publicKey)
.keyUse(KeyUse.from(cert))
.keyID(cert.getSerialNumber().toString(10))
.x509CertChain(Collections.singletonList(Base64.encode(cert.getEncoded())))
.x509CertSHA256Thumbprint(Base64URL.encode(sha256.digest(cert.getEncoded())))
.expirationTime(cert.getNotAfter())
.notBeforeTime(cert.getNotBefore())
.build();
} catch (NoSuchAlgorithmException e) {
throw new JOSEException("Couldn't encode x5t parameter: " + e.getMessage(), e);
} catch (CertificateEncodingException e) {
throw new JOSEException("Couldn't encode x5c parameter: " + e.getMessage(), e);
}
}
/**
* Loads a public / private Elliptic Curve JWK from the specified JCA
* key store. Requires BouncyCastle.
*
* Important: The X.509 certificate is not
* validated!
*
* @param keyStore The key store. Must not be {@code null}.
* @param alias The alias. Must not be {@code null}.
* @param pin The pin to unlock the private key if any, empty or
* {@code null} if not required.
*
* @return The public / private Elliptic Curve JWK., {@code null} if no
* key with the specified alias was found.
*
* @throws KeyStoreException On a key store exception.
* @throws JOSEException If EC key loading failed.
*/
public static ECKey load(final KeyStore keyStore,
final String alias,
final char[] pin)
throws KeyStoreException, JOSEException {
Certificate cert = keyStore.getCertificate(alias);
if (!(cert instanceof X509Certificate)) {
return null;
}
X509Certificate x509Cert = (X509Certificate)cert;
if (! (x509Cert.getPublicKey() instanceof ECPublicKey)) {
throw new JOSEException("Couldn't load EC JWK: The key algorithm is not EC");
}
ECKey ecJWK = ECKey.parse(x509Cert);
// Let kid=alias
ecJWK = new ECKey.Builder(ecJWK).keyID(alias).keyStore(keyStore).build();
// Check for private counterpart
Key key;
try {
key = keyStore.getKey(alias, pin);
} catch (UnrecoverableKeyException | NoSuchAlgorithmException e) {
throw new JOSEException("Couldn't retrieve private EC key (bad pin?): " + e.getMessage(), e);
}
if (key instanceof ECPrivateKey) {
// Simple file based key store
return new ECKey.Builder(ecJWK)
.privateKey((ECPrivateKey)key)
.build();
} else if (key instanceof PrivateKey && "EC".equalsIgnoreCase(key.getAlgorithm())) {
// PKCS#11 store
return new ECKey.Builder(ecJWK)
.privateKey((PrivateKey)key)
.build();
} else {
return ecJWK;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ECKey)) return false;
if (!super.equals(o)) return false;
ECKey ecKey = (ECKey) o;
return Objects.equals(crv, ecKey.crv) &&
Objects.equals(x, ecKey.x) &&
Objects.equals(y, ecKey.y) &&
Objects.equals(d, ecKey.d) &&
Objects.equals(privateKey, ecKey.privateKey);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), crv, x, y, d, privateKey);
}
}