001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2024, Connect2id Ltd. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.jose.jwk; 019 020 021import com.nimbusds.jose.Algorithm; 022import com.nimbusds.jose.JOSEException; 023import com.nimbusds.jose.crypto.utils.ECChecks; 024import com.nimbusds.jose.util.Base64; 025import com.nimbusds.jose.util.Base64URL; 026import com.nimbusds.jose.util.BigIntegerUtils; 027import com.nimbusds.jose.util.JSONObjectUtils; 028import net.jcip.annotations.Immutable; 029import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; 030 031import java.math.BigInteger; 032import java.net.URI; 033import java.security.*; 034import java.security.cert.Certificate; 035import java.security.cert.CertificateEncodingException; 036import java.security.cert.X509Certificate; 037import java.security.interfaces.ECPrivateKey; 038import java.security.interfaces.ECPublicKey; 039import java.security.spec.*; 040import java.text.ParseException; 041import java.util.*; 042 043 044/** 045 * Public and private {@link KeyType#EC Elliptic Curve} JSON Web Key (JWK). 046 * This class is immutable. 047 * 048 * <p>Supported curves: 049 * 050 * <ul> 051 * <li>{@link Curve#P_256 P-256} 052 * <li>{@link Curve#SECP256K1 secp256k1} 053 * <li>{@link Curve#P_384 P-384} 054 * <li>{@link Curve#P_521 P-512} 055 * </ul> 056 * 057 * <p>Provides EC JWK import from / export to the following standard Java 058 * interfaces and classes: 059 * 060 * <ul> 061 * <li>{@link java.security.interfaces.ECPublicKey} 062 * <li>{@link java.security.interfaces.ECPrivateKey} 063 * <li>{@link java.security.PrivateKey} for an EC key in a PKCS#11 store 064 * <li>{@link java.security.KeyPair} 065 * </ul> 066 * 067 * <p>Example JSON object representation of a public EC JWK: 068 * 069 * <pre> 070 * { 071 * "kty" : "EC", 072 * "crv" : "P-256", 073 * "x" : "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", 074 * "y" : "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", 075 * "use" : "enc", 076 * "kid" : "1" 077 * } 078 * </pre> 079 * 080 * <p>Example JSON object representation of a private EC JWK: 081 * 082 * <pre> 083 * { 084 * "kty" : "EC", 085 * "crv" : "P-256", 086 * "x" : "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", 087 * "y" : "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", 088 * "d" : "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE", 089 * "use" : "enc", 090 * "kid" : "1" 091 * } 092 * </pre> 093 * 094 * <p>Use the builder to create a new EC JWK: 095 * 096 * <pre> 097 * ECKey key = new ECKey.Builder(Curve.P_256, x, y) 098 * .keyUse(KeyUse.SIGNATURE) 099 * .keyID("1") 100 * .build(); 101 * </pre> 102 * 103 * @author Vladimir Dzhuvinov 104 * @author Justin Richer 105 * @version 2024-10-31 106 */ 107@Immutable 108public final class ECKey extends JWK implements AsymmetricJWK, CurveBasedJWK { 109 110 111 private static final long serialVersionUID = 1L; 112 113 114 /** 115 * Supported EC curves. 116 */ 117 public static final Set<Curve> SUPPORTED_CURVES = Collections.unmodifiableSet( 118 new HashSet<>(Arrays.asList(Curve.P_256, Curve.SECP256K1, Curve.P_384, Curve.P_521)) 119 ); 120 121 122 /** 123 * Builder for constructing Elliptic Curve JWKs. 124 * 125 * <p>Example usage: 126 * 127 * <pre> 128 * ECKey key = new ECKey.Builder(Curve.P521, x, y) 129 * .d(d) 130 * .algorithm(JWSAlgorithm.ES512) 131 * .keyID("1") 132 * .build(); 133 * </pre> 134 */ 135 public static class Builder { 136 137 138 /** 139 * The curve name. 140 */ 141 private final Curve crv; 142 143 144 /** 145 * The public 'x' EC coordinate. 146 */ 147 private final Base64URL x; 148 149 150 /** 151 * The public 'y' EC coordinate. 152 */ 153 private final Base64URL y; 154 155 156 /** 157 * The private 'd' EC coordinate, optional. 158 */ 159 private Base64URL d; 160 161 162 /** 163 * The private EC key, as PKCS#11 handle, optional. 164 */ 165 private PrivateKey priv; 166 167 168 /** 169 * The key use, optional. 170 */ 171 private KeyUse use; 172 173 174 /** 175 * The key operations, optional. 176 */ 177 private Set<KeyOperation> ops; 178 179 180 /** 181 * The intended JOSE algorithm for the key, optional. 182 */ 183 private Algorithm alg; 184 185 186 /** 187 * The key ID, optional. 188 */ 189 private String kid; 190 191 192 /** 193 * X.509 certificate URL, optional. 194 */ 195 private URI x5u; 196 197 198 /** 199 * X.509 certificate SHA-1 thumbprint, optional. 200 */ 201 @Deprecated 202 private Base64URL x5t; 203 204 205 /** 206 * X.509 certificate SHA-256 thumbprint, optional. 207 */ 208 private Base64URL x5t256; 209 210 211 /** 212 * The X.509 certificate chain, optional. 213 */ 214 private List<Base64> x5c; 215 216 217 /** 218 * The key expiration time, optional. 219 */ 220 private Date exp; 221 222 223 /** 224 * The key not-before time, optional. 225 */ 226 private Date nbf; 227 228 229 /** 230 * The key issued-at time, optional. 231 */ 232 private Date iat; 233 234 235 /** 236 * The key revocation, optional. 237 */ 238 private KeyRevocation revocation; 239 240 241 /** 242 * Reference to the underlying key store, {@code null} if none. 243 */ 244 private KeyStore ks; 245 246 247 /** 248 * Creates a new Elliptic Curve JWK builder. 249 * 250 * @param crv The cryptographic curve. Must not be 251 * {@code null}. 252 * @param x The public 'x' coordinate for the elliptic curve 253 * point. It is represented as the Base64URL 254 * encoding of the coordinate's big endian 255 * representation. Must not be {@code null}. 256 * @param y The public 'y' coordinate for the elliptic curve 257 * point. It is represented as the Base64URL 258 * encoding of the coordinate's big endian 259 * representation. Must not be {@code null}. 260 */ 261 public Builder(final Curve crv, final Base64URL x, final Base64URL y) { 262 263 this.crv = Objects.requireNonNull(crv, "The curve must not be null"); 264 this.x = Objects.requireNonNull(x, "The x coordinate must not be null"); 265 this.y = Objects.requireNonNull(y, "The y coordinate must not be null"); 266 } 267 268 269 /** 270 * Creates a new Elliptic Curve JWK builder. 271 * 272 * @param crv The cryptographic curve. Must not be 273 * {@code null}. 274 * @param pub The public EC key to represent. Must not be 275 * {@code null}. 276 */ 277 public Builder(final Curve crv, final ECPublicKey pub) { 278 279 this(crv, 280 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()), 281 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY())); 282 } 283 284 285 /** 286 * Creates a new Elliptic Curve JWK builder. 287 * 288 * @param ecJWK The EC JWK to start with. Must not be 289 * {@code null}. 290 */ 291 public Builder(final ECKey ecJWK) { 292 293 crv = ecJWK.crv; 294 x = ecJWK.x; 295 y = ecJWK.y; 296 d = ecJWK.d; 297 priv = ecJWK.privateKey; 298 use = ecJWK.getKeyUse(); 299 ops = ecJWK.getKeyOperations(); 300 alg = ecJWK.getAlgorithm(); 301 kid = ecJWK.getKeyID(); 302 x5u = ecJWK.getX509CertURL(); 303 x5t = ecJWK.getX509CertThumbprint(); 304 x5t256 = ecJWK.getX509CertSHA256Thumbprint(); 305 x5c = ecJWK.getX509CertChain(); 306 exp = ecJWK.getExpirationTime(); 307 nbf = ecJWK.getNotBeforeTime(); 308 iat = ecJWK.getIssueTime(); 309 revocation = ecJWK.getKeyRevocation(); 310 ks = ecJWK.getKeyStore(); 311 } 312 313 314 /** 315 * Sets the private 'd' coordinate for the elliptic curve 316 * point. The alternative method is {@link #privateKey}. 317 * 318 * @param d The private 'd' coordinate. It is represented as 319 * the Base64URL encoding of the coordinate's big 320 * endian representation. {@code null} if not 321 * specified (for a public key or private key 322 * specified otherwise). 323 * 324 * @return This builder. 325 */ 326 public Builder d(final Base64URL d) { 327 328 this.d = d; 329 return this; 330 } 331 332 333 /** 334 * Sets the private Elliptic Curve key. The alternative method 335 * is {@link #d}. 336 * 337 * @param priv The private EC key, used to obtain the private 338 * 'd' coordinate for the elliptic curve point. 339 * {@code null} if not specified (for a public 340 * key or private key specified otherwise). 341 * 342 * @return This builder. 343 */ 344 public Builder privateKey(final ECPrivateKey priv) { 345 346 if (priv != null) { 347 this.d = encodeCoordinate(priv.getParams().getCurve().getField().getFieldSize(), priv.getS()); 348 } else { 349 this.d = null; 350 } 351 352 return this; 353 } 354 355 356 /** 357 * Sets the private EC key, typically for a key located in a 358 * PKCS#11 store that doesn't expose the private key parameters 359 * (such as a smart card or HSM). 360 * 361 * @param priv The private EC key reference. Its algorithm must 362 * be "EC". {@code null} if not specified (for a 363 * public key or private key specified otherwise). 364 * 365 * @return This builder. 366 */ 367 public Builder privateKey(final PrivateKey priv) { 368 369 if (priv instanceof ECPrivateKey) { 370 // We have the key material, set d coordinate instead 371 return privateKey((ECPrivateKey) priv); 372 } 373 374 if (priv != null && ! "EC".equalsIgnoreCase(priv.getAlgorithm())) { 375 throw new IllegalArgumentException("The private key algorithm must be EC"); 376 } 377 378 this.priv = priv; 379 return this; 380 } 381 382 383 /** 384 * Sets the use ({@code use}) of the JWK. 385 * 386 * @param use The key use, {@code null} if not specified or if 387 * the key is intended for signing as well as 388 * encryption. 389 * 390 * @return This builder. 391 */ 392 public Builder keyUse(final KeyUse use) { 393 394 this.use = use; 395 return this; 396 } 397 398 399 /** 400 * Sets the operations ({@code key_ops}) of the JWK. 401 * 402 * @param ops The key operations, {@code null} if not 403 * specified. 404 * 405 * @return This builder. 406 */ 407 public Builder keyOperations(final Set<KeyOperation> ops) { 408 409 this.ops = ops; 410 return this; 411 } 412 413 414 /** 415 * Sets the intended JOSE algorithm ({@code alg}) for the JWK. 416 * 417 * @param alg The intended JOSE algorithm, {@code null} if not 418 * specified. 419 * 420 * @return This builder. 421 */ 422 public Builder algorithm(final Algorithm alg) { 423 424 this.alg = alg; 425 return this; 426 } 427 428 /** 429 * Sets the ID ({@code kid}) of the JWK. The key ID can be used 430 * to match a specific key. This can be used, for instance, to 431 * choose a key within a {@link JWKSet} during key rollover. 432 * The key ID may also correspond to a JWS/JWE {@code kid} 433 * header parameter value. 434 * 435 * @param kid The key ID, {@code null} if not specified. 436 * 437 * @return This builder. 438 */ 439 public Builder keyID(final String kid) { 440 441 this.kid = kid; 442 return this; 443 } 444 445 446 /** 447 * Sets the ID ({@code kid}) of the JWK to its SHA-256 JWK 448 * thumbprint (RFC 7638). The key ID can be used to match a 449 * specific key. This can be used, for instance, to choose a 450 * key within a {@link JWKSet} during key rollover. The key ID 451 * may also correspond to a JWS/JWE {@code kid} header 452 * parameter value. 453 * 454 * @return This builder. 455 * 456 * @throws JOSEException If the SHA-256 hash algorithm is not 457 * supported. 458 */ 459 public Builder keyIDFromThumbprint() 460 throws JOSEException { 461 462 return keyIDFromThumbprint("SHA-256"); 463 } 464 465 466 /** 467 * Sets the ID ({@code kid}) of the JWK to its JWK thumbprint 468 * (RFC 7638). The key ID can be used to match a specific key. 469 * This can be used, for instance, to choose a key within a 470 * {@link JWKSet} during key rollover. The key ID may also 471 * correspond to a JWS/JWE {@code kid} header parameter value. 472 * 473 * @param hashAlg The hash algorithm for the JWK thumbprint 474 * computation. Must not be {@code null}. 475 * 476 * @return This builder. 477 * 478 * @throws JOSEException If the hash algorithm is not 479 * supported. 480 */ 481 public Builder keyIDFromThumbprint(final String hashAlg) 482 throws JOSEException { 483 484 // Put mandatory params in sorted order 485 LinkedHashMap<String,String> requiredParams = new LinkedHashMap<>(); 486 requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE, crv.toString()); 487 requiredParams.put(JWKParameterNames.KEY_TYPE, KeyType.EC.getValue()); 488 requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE_X_COORDINATE, x.toString()); 489 requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE_Y_COORDINATE, y.toString()); 490 this.kid = ThumbprintUtils.compute(hashAlg, requiredParams).toString(); 491 return this; 492 } 493 494 495 /** 496 * Sets the X.509 certificate URL ({@code x5u}) of the JWK. 497 * 498 * @param x5u The X.509 certificate URL, {@code null} if not 499 * specified. 500 * 501 * @return This builder. 502 */ 503 public Builder x509CertURL(final URI x5u) { 504 505 this.x5u = x5u; 506 return this; 507 } 508 509 510 /** 511 * Sets the X.509 certificate SHA-1 thumbprint ({@code x5t}) of 512 * the JWK. 513 * 514 * @param x5t The X.509 certificate SHA-1 thumbprint, 515 * {@code null} if not specified. 516 * 517 * @return This builder. 518 */ 519 @Deprecated 520 public Builder x509CertThumbprint(final Base64URL x5t) { 521 522 this.x5t = x5t; 523 return this; 524 } 525 526 527 /** 528 * Sets the X.509 certificate SHA-256 thumbprint 529 * ({@code x5t#S256}) of the JWK. 530 * 531 * @param x5t256 The X.509 certificate SHA-256 thumbprint, 532 * {@code null} if not specified. 533 * 534 * @return This builder. 535 */ 536 public Builder x509CertSHA256Thumbprint(final Base64URL x5t256) { 537 538 this.x5t256 = x5t256; 539 return this; 540 } 541 542 543 /** 544 * Sets the X.509 certificate chain ({@code x5c}) of the JWK. 545 * 546 * @param x5c The X.509 certificate chain as a unmodifiable 547 * list, {@code null} if not specified. 548 * 549 * @return This builder. 550 */ 551 public Builder x509CertChain(final List<Base64> x5c) { 552 553 this.x5c = x5c; 554 return this; 555 } 556 557 558 /** 559 * Sets the expiration time ({@code exp}) of the JWK. 560 * 561 * @param exp The expiration time, {@code null} if not 562 * specified. 563 * 564 * @return This builder. 565 */ 566 public Builder expirationTime(final Date exp) { 567 568 this.exp = exp; 569 return this; 570 } 571 572 573 /** 574 * Sets the not-before time ({@code nbf}) of the JWK. 575 * 576 * @param nbf The not-before time, {@code null} if not 577 * specified. 578 * 579 * @return This builder. 580 */ 581 public Builder notBeforeTime(final Date nbf) { 582 583 this.nbf = nbf; 584 return this; 585 } 586 587 588 /** 589 * Sets the issued-at time ({@code iat}) of the JWK. 590 * 591 * @param iat The issued-at time, {@code null} if not 592 * specified. 593 * 594 * @return This builder. 595 */ 596 public Builder issueTime(final Date iat) { 597 598 this.iat = iat; 599 return this; 600 } 601 602 603 /** 604 * Sets the revocation ({@code revoked}) of the JWK. 605 * 606 * @param revocation The key revocation, {@code null} if not 607 * specified. 608 * 609 * @return This builder. 610 */ 611 public Builder keyRevocation(final KeyRevocation revocation) { 612 613 this.revocation = revocation; 614 return this; 615 } 616 617 618 /** 619 * Sets the underlying key store. 620 * 621 * @param keyStore Reference to the underlying key store, 622 * {@code null} if none. 623 * 624 * @return This builder. 625 */ 626 public Builder keyStore(final KeyStore keyStore) { 627 628 this.ks = keyStore; 629 return this; 630 } 631 632 633 /** 634 * Builds a new Elliptic Curve JWK. 635 * 636 * @return The Elliptic Curve JWK. 637 * 638 * @throws IllegalStateException If the JWK parameters were 639 * inconsistently specified. 640 */ 641 public ECKey build() { 642 643 try { 644 if (d == null && priv == null) { 645 // Public key 646 return new ECKey(crv, x, y, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, revocation, ks); 647 } 648 649 if (priv != null) { 650 // PKCS#11 reference to private key 651 return new ECKey(crv, x, y, priv, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, revocation, ks); 652 } 653 654 // Public / private key pair with 'd' 655 return new ECKey(crv, x, y, d, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, revocation, ks); 656 657 } catch (IllegalArgumentException e) { 658 throw new IllegalStateException(e.getMessage(), e); 659 } 660 } 661 } 662 663 664 /** 665 * Returns the Base64URL encoding of the specified elliptic curve 'x', 666 * 'y' or 'd' coordinate, with leading zero padding up to the specified 667 * field size in bits. 668 * 669 * @param fieldSize The field size in bits. 670 * @param coordinate The elliptic curve coordinate. Must not be 671 * {@code null}. 672 * 673 * @return The Base64URL-encoded coordinate, with leading zero padding 674 * up to the curve's field size. 675 */ 676 public static Base64URL encodeCoordinate(final int fieldSize, final BigInteger coordinate) { 677 678 final byte[] notPadded = BigIntegerUtils.toBytesUnsigned(coordinate); 679 680 int bytesToOutput = (fieldSize + 7)/8; 681 682 if (notPadded.length >= bytesToOutput) { 683 // Greater-than check to prevent exception on malformed 684 // key below 685 return Base64URL.encode(notPadded); 686 } 687 688 final byte[] padded = new byte[bytesToOutput]; 689 690 System.arraycopy(notPadded, 0, padded, bytesToOutput - notPadded.length, notPadded.length); 691 692 return Base64URL.encode(padded); 693 } 694 695 696 /** 697 * The curve name. 698 */ 699 private final Curve crv; 700 701 702 /** 703 * The public 'x' EC coordinate. 704 */ 705 private final Base64URL x; 706 707 708 /** 709 * The public 'y' EC coordinate. 710 */ 711 private final Base64URL y; 712 713 714 /** 715 * The private 'd' EC coordinate. 716 */ 717 private final Base64URL d; 718 719 720 /** 721 * Private PKCS#11 key handle. 722 */ 723 private final PrivateKey privateKey; 724 725 726 /** 727 * Ensures the specified 'x' and 'y' public coordinates are on the 728 * given curve. 729 * 730 * @param crv The curve. Must not be {@code null}. 731 * @param x The public 'x' coordinate. Must not be {@code null}. 732 * @param y The public 'y' coordinate. Must not be {@code null}. 733 */ 734 private static void ensurePublicCoordinatesOnCurve(final Curve crv, final Base64URL x, final Base64URL y) { 735 736 if (! SUPPORTED_CURVES.contains(crv)) { 737 throw new IllegalArgumentException("Unknown / unsupported curve: " + crv); 738 } 739 740 if (! ECChecks.isPointOnCurve(x.decodeToBigInteger(), y.decodeToBigInteger(), crv.toECParameterSpec())) { 741 throw new IllegalArgumentException("Invalid EC JWK: The 'x' and 'y' public coordinates are not on the " + crv + " curve"); 742 } 743 } 744 745 746 /** 747 * Creates a new public Elliptic Curve JSON Web Key (JWK) with the 748 * specified parameters. 749 * 750 * @param crv The cryptographic curve. Must not be {@code null}. 751 * @param x The public 'x' coordinate for the elliptic curve 752 * point. It is represented as the Base64URL encoding of 753 * the coordinate's big endian representation. Must not 754 * be {@code null}. 755 * @param y The public 'y' coordinate for the elliptic curve 756 * point. It is represented as the Base64URL encoding of 757 * the coordinate's big endian representation. Must not 758 * be {@code null}. 759 * @param use The key use, {@code null} if not specified or if the 760 * key is intended for signing as well as encryption. 761 * @param ops The key operations, {@code null} if not specified. 762 * @param alg The intended JOSE algorithm for the key, {@code null} 763 * if not specified. 764 * @param kid The key ID, {@code null} if not specified. 765 * @param x5u The X.509 certificate URL, {@code null} if not 766 * specified. 767 * @param x5t The X.509 certificate SHA-1 thumbprint, {@code null} 768 * if not specified. 769 * @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null} 770 * if not specified. 771 * @param x5c The X.509 certificate chain, {@code null} if not 772 * specified. 773 * @param ks Reference to the underlying key store, {@code null} if 774 * not specified. 775 */ 776 @Deprecated 777 public ECKey(final Curve crv, final Base64URL x, final Base64URL y, 778 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 779 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 780 final KeyStore ks) { 781 782 this(crv, x, y, use, ops, alg, kid, x5u, x5t, x5t256, x5c, null, null, null, ks); 783 } 784 785 786 /** 787 * Creates a new public / private Elliptic Curve JSON Web Key (JWK) 788 * with the specified parameters. 789 * 790 * @param crv The cryptographic curve. Must not be {@code null}. 791 * @param x The public 'x' coordinate for the elliptic curve 792 * point. It is represented as the Base64URL encoding of 793 * the coordinate's big endian representation. Must not 794 * be {@code null}. 795 * @param y The public 'y' coordinate for the elliptic curve 796 * point. It is represented as the Base64URL encoding of 797 * the coordinate's big endian representation. Must not 798 * be {@code null}. 799 * @param d The private 'd' coordinate for the elliptic curve 800 * point. It is represented as the Base64URL encoding of 801 * the coordinate's big endian representation. Must not 802 * be {@code null}. 803 * @param use The key use, {@code null} if not specified or if the 804 * key is intended for signing as well as encryption. 805 * @param ops The key operations, {@code null} if not specified. 806 * @param alg The intended JOSE algorithm for the key, {@code null} 807 * if not specified. 808 * @param kid The key ID, {@code null} if not specified. 809 * @param x5u The X.509 certificate URL, {@code null} if not 810 * specified. 811 * @param x5t The X.509 certificate SHA-1 thumbprint, {@code null} 812 * if not specified. 813 * @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null} 814 * if not specified. 815 * @param x5c The X.509 certificate chain, {@code null} if not 816 * specified. 817 * @param ks Reference to the underlying key store, {@code null} if 818 * not specified. 819 */ 820 @Deprecated 821 public ECKey(final Curve crv, final Base64URL x, final Base64URL y, final Base64URL d, 822 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 823 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 824 final KeyStore ks) { 825 826 this(crv, x, y, d, use, ops, alg, kid, x5u, x5t, x5t256, x5c, null, null, null, ks); 827 } 828 829 830 /** 831 * Creates a new public / private Elliptic Curve JSON Web Key (JWK) 832 * with the specified parameters. The private key is specified by its 833 * PKCS#11 handle. 834 * 835 * @param crv The cryptographic curve. Must not be {@code null}. 836 * @param x The public 'x' coordinate for the elliptic curve 837 * point. It is represented as the Base64URL encoding of 838 * the coordinate's big endian representation. Must not 839 * be {@code null}. 840 * @param y The public 'y' coordinate for the elliptic curve 841 * point. It is represented as the Base64URL encoding of 842 * the coordinate's big endian representation. Must not 843 * be {@code null}. 844 * @param priv The private key as a PKCS#11 handle, {@code null} if 845 * not specified. 846 * @param use The key use, {@code null} if not specified or if the 847 * key is intended for signing as well as encryption. 848 * @param ops The key operations, {@code null} if not specified. 849 * @param alg The intended JOSE algorithm for the key, {@code null} 850 * if not specified. 851 * @param kid The key ID, {@code null} if not specified. 852 * @param x5u The X.509 certificate URL, {@code null} if not 853 * specified. 854 * @param x5t The X.509 certificate SHA-1 thumbprint, {@code null} 855 * if not specified. 856 * @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null} 857 * if not specified. 858 * @param x5c The X.509 certificate chain, {@code null} if not 859 * specified. 860 * @param ks Reference to the underlying key store, {@code null} if 861 * not specified. 862 */ 863 @Deprecated 864 public ECKey(final Curve crv, final Base64URL x, final Base64URL y, final PrivateKey priv, 865 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 866 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 867 final KeyStore ks) { 868 869 this(crv, x, y, priv, use, ops, alg, kid, x5u, x5t, x5t256, x5c, null, null, null, ks); 870 } 871 872 873 /** 874 * Creates a new public Elliptic Curve JSON Web Key (JWK) with the 875 * specified parameters. 876 * 877 * @param crv The cryptographic curve. Must not be {@code null}. 878 * @param pub The public EC key to represent. Must not be 879 * {@code null}. 880 * @param use The key use, {@code null} if not specified or if the 881 * key is intended for signing as well as encryption. 882 * @param ops The key operations, {@code null} if not specified. 883 * @param alg The intended JOSE algorithm for the key, {@code null} 884 * if not specified. 885 * @param kid The key ID, {@code null} if not specified. 886 * @param x5u The X.509 certificate URL, {@code null} if not 887 * specified. 888 * @param x5t The X.509 certificate SHA-1 thumbprint, {@code null} 889 * if not specified. 890 * @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null} 891 * if not specified. 892 * @param x5c The X.509 certificate chain, {@code null} if not 893 * specified. 894 * @param ks Reference to the underlying key store, {@code null} if 895 * not specified. 896 */ 897 @Deprecated 898 public ECKey(final Curve crv, final ECPublicKey pub, 899 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 900 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 901 final KeyStore ks) { 902 903 this(crv, 904 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()), 905 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()), 906 use, ops, alg, kid, 907 x5u, x5t, x5t256, x5c, 908 null, null, null, 909 ks); 910 } 911 912 913 /** 914 * Creates a new public / private Elliptic Curve JSON Web Key (JWK) 915 * with the specified parameters. 916 * 917 * @param crv The cryptographic curve. Must not be {@code null}. 918 * @param pub The public EC key to represent. Must not be 919 * {@code null}. 920 * @param priv The private EC key to represent. Must not be 921 * {@code null}. 922 * @param use The key use, {@code null} if not specified or if the 923 * key is intended for signing as well as encryption. 924 * @param ops The key operations, {@code null} if not specified. 925 * @param alg The intended JOSE algorithm for the key, {@code null} 926 * if not specified. 927 * @param kid The key ID, {@code null} if not specified. 928 * @param x5u The X.509 certificate URL, {@code null} if not 929 * specified. 930 * @param x5t The X.509 certificate SHA-1 thumbprint, {@code null} 931 * if not specified. 932 * @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null} 933 * if not specified. 934 * @param x5c The X.509 certificate chain, {@code null} if not 935 * specified. 936 * @param ks Reference to the underlying key store, {@code null} if 937 * not specified. 938 */ 939 @Deprecated 940 public ECKey(final Curve crv, final ECPublicKey pub, final ECPrivateKey priv, 941 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 942 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 943 final KeyStore ks) { 944 945 this(crv, 946 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()), 947 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()), 948 encodeCoordinate(priv.getParams().getCurve().getField().getFieldSize(), priv.getS()), 949 use, ops, alg, kid, 950 x5u, x5t, x5t256, x5c, 951 null, null, null, 952 ks); 953 } 954 955 956 /** 957 * Creates a new public / private Elliptic Curve JSON Web Key (JWK) 958 * with the specified parameters. The private key is specified by its 959 * PKCS#11 handle. 960 * 961 * @param crv The cryptographic curve. Must not be {@code null}. 962 * @param pub The public EC key to represent. Must not be 963 * {@code null}. 964 * @param priv The private key as a PKCS#11 handle, {@code null} if 965 * not specified. 966 * @param use The key use, {@code null} if not specified or if the 967 * key is intended for signing as well as encryption. 968 * @param ops The key operations, {@code null} if not specified. 969 * @param alg The intended JOSE algorithm for the key, {@code null} 970 * if not specified. 971 * @param kid The key ID, {@code null} if not specified. 972 * @param x5u The X.509 certificate URL, {@code null} if not 973 * specified. 974 * @param x5t The X.509 certificate SHA-1 thumbprint, {@code null} 975 * if not specified. 976 * @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null} 977 * if not specified. 978 * @param x5c The X.509 certificate chain, {@code null} if not 979 * specified. 980 * @param ks Reference to the underlying key store, {@code null} if 981 * not specified. 982 */ 983 @Deprecated 984 public ECKey(final Curve crv, final ECPublicKey pub, final PrivateKey priv, 985 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 986 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 987 final KeyStore ks) { 988 989 this( 990 crv, 991 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()), 992 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()), 993 priv, 994 use, ops, alg, kid, x5u, x5t, x5t256, x5c, 995 null, null, null, 996 ks); 997 } 998 999 1000 /** 1001 * Creates a new public Elliptic Curve JSON Web Key (JWK) with the 1002 * specified parameters. 1003 * 1004 * @param crv The cryptographic curve. Must not be {@code null}. 1005 * @param x The public 'x' coordinate for the elliptic curve 1006 * point. It is represented as the Base64URL encoding of 1007 * the coordinate's big endian representation. Must not 1008 * be {@code null}. 1009 * @param y The public 'y' coordinate for the elliptic curve 1010 * point. It is represented as the Base64URL encoding of 1011 * the coordinate's big endian representation. Must not 1012 * be {@code null}. 1013 * @param use The key use, {@code null} if not specified or if the 1014 * key is intended for signing as well as encryption. 1015 * @param ops The key operations, {@code null} if not specified. 1016 * @param alg The intended JOSE algorithm for the key, {@code null} 1017 * if not specified. 1018 * @param kid The key ID, {@code null} if not specified. 1019 * @param x5u The X.509 certificate URL, {@code null} if not 1020 * specified. 1021 * @param x5t The X.509 certificate SHA-1 thumbprint, {@code null} 1022 * if not specified. 1023 * @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null} 1024 * if not specified. 1025 * @param x5c The X.509 certificate chain, {@code null} if not 1026 * specified. 1027 * @param exp The key expiration time, {@code null} if not 1028 * specified. 1029 * @param nbf The key not-before time, {@code null} if not 1030 * specified. 1031 * @param iat The key issued-at time, {@code null} if not specified. 1032 * @param ks Reference to the underlying key store, {@code null} if 1033 * not specified. 1034 */ 1035 @Deprecated 1036 public ECKey(final Curve crv, final Base64URL x, final Base64URL y, 1037 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1038 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 1039 final Date exp, final Date nbf, final Date iat, 1040 final KeyStore ks) { 1041 1042 this(crv, x, y, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, null, ks); 1043 } 1044 1045 1046 // JWK public 1047 /** 1048 * Creates a new public Elliptic Curve JSON Web Key (JWK) with the 1049 * specified parameters. 1050 * 1051 * @param crv The cryptographic curve. Must not be {@code null}. 1052 * @param x The public 'x' coordinate for the elliptic curve 1053 * point. It is represented as the Base64URL encoding 1054 * of the coordinate's big endian representation. 1055 * Must not be {@code null}. 1056 * @param y The public 'y' coordinate for the elliptic curve 1057 * point. It is represented as the Base64URL encoding 1058 * of the coordinate's big endian representation. 1059 * Must not be {@code null}. 1060 * @param use The key use, {@code null} if not specified or if 1061 * the key is intended for signing as well as 1062 * encryption. 1063 * @param ops The key operations, {@code null} if not specified. 1064 * @param alg The intended JOSE algorithm for the key, 1065 * {@code null} if not specified. 1066 * @param kid The key ID, {@code null} if not specified. 1067 * @param x5u The X.509 certificate URL, {@code null} if not 1068 * specified. 1069 * @param x5t The X.509 certificate SHA-1 thumbprint, 1070 * {@code null} if not specified. 1071 * @param x5t256 The X.509 certificate SHA-256 thumbprint, 1072 * {@code null} if not specified. 1073 * @param x5c The X.509 certificate chain, {@code null} if not 1074 * specified. 1075 * @param exp The key expiration time, {@code null} if not 1076 * specified. 1077 * @param nbf The key not-before time, {@code null} if not 1078 * specified. 1079 * @param iat The key issued-at time, {@code null} if not 1080 * specified. 1081 * @param revocation The key revocation, {@code null} if not specified. 1082 * @param ks Reference to the underlying key store, 1083 * {@code null} if not specified. 1084 */ 1085 public ECKey(final Curve crv, final Base64URL x, final Base64URL y, 1086 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1087 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 1088 final Date exp, final Date nbf, final Date iat, final KeyRevocation revocation, 1089 final KeyStore ks) { 1090 1091 super(KeyType.EC, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, revocation, ks); 1092 this.crv = Objects.requireNonNull(crv, "The curve must not be null"); 1093 this.x = Objects.requireNonNull(x, "The x coordinate must not be null"); 1094 this.y = Objects.requireNonNull(y, "The y coordinate must not be null"); 1095 ensurePublicCoordinatesOnCurve(crv, x, y); 1096 ensureMatches(getParsedX509CertChain()); 1097 this.d = null; 1098 this.privateKey = null; 1099 } 1100 1101 1102 /** 1103 * Creates a new public / private Elliptic Curve JSON Web Key (JWK) 1104 * with the specified parameters. 1105 * 1106 * @param crv The cryptographic curve. Must not be {@code null}. 1107 * @param x The public 'x' coordinate for the elliptic curve 1108 * point. It is represented as the Base64URL encoding of 1109 * the coordinate's big endian representation. Must not 1110 * be {@code null}. 1111 * @param y The public 'y' coordinate for the elliptic curve 1112 * point. It is represented as the Base64URL encoding of 1113 * the coordinate's big endian representation. Must not 1114 * be {@code null}. 1115 * @param d The private 'd' coordinate for the elliptic curve 1116 * point. It is represented as the Base64URL encoding of 1117 * the coordinate's big endian representation. Must not 1118 * be {@code null}. 1119 * @param use The key use, {@code null} if not specified or if the 1120 * key is intended for signing as well as encryption. 1121 * @param ops The key operations, {@code null} if not specified. 1122 * @param alg The intended JOSE algorithm for the key, {@code null} 1123 * if not specified. 1124 * @param kid The key ID, {@code null} if not specified. 1125 * @param x5u The X.509 certificate URL, {@code null} if not 1126 * specified. 1127 * @param x5t The X.509 certificate SHA-1 thumbprint, {@code null} 1128 * if not specified. 1129 * @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null} 1130 * if not specified. 1131 * @param x5c The X.509 certificate chain, {@code null} if not 1132 * specified. 1133 * @param exp The key expiration time, {@code null} if not 1134 * specified. 1135 * @param nbf The key not-before time, {@code null} if not 1136 * specified. 1137 * @param iat The key issued-at time, {@code null} if not specified. 1138 * @param ks Reference to the underlying key store, {@code null} if 1139 * not specified. 1140 */ 1141 @Deprecated 1142 public ECKey(final Curve crv, final Base64URL x, final Base64URL y, final Base64URL d, 1143 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1144 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 1145 final Date exp, final Date nbf, final Date iat, 1146 final KeyStore ks) { 1147 1148 this(crv, x, y, d, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, null, ks); 1149 } 1150 1151 1152 // JWK public + private 1153 /** 1154 * Creates a new public / private Elliptic Curve JSON Web Key (JWK) 1155 * with the specified parameters. 1156 * 1157 * @param crv The cryptographic curve. Must not be {@code null}. 1158 * @param x The public 'x' coordinate for the elliptic curve 1159 * point. It is represented as the Base64URL encoding 1160 * of the coordinate's big endian representation. 1161 * Must not be {@code null}. 1162 * @param y The public 'y' coordinate for the elliptic curve 1163 * point. It is represented as the Base64URL encoding 1164 * of the coordinate's big endian representation. 1165 * Must not be {@code null}. 1166 * @param d The private 'd' coordinate for the elliptic curve 1167 * point. It is represented as the Base64URL encoding 1168 * of the coordinate's big endian representation. 1169 * Must not be {@code null}. 1170 * @param use The key use, {@code null} if not specified or if 1171 * the key is intended for signing as well as 1172 * encryption. 1173 * @param ops The key operations, {@code null} if not specified. 1174 * @param alg The intended JOSE algorithm for the key, 1175 * {@code null} if not specified. 1176 * @param kid The key ID, {@code null} if not specified. 1177 * @param x5u The X.509 certificate URL, {@code null} if not 1178 * specified. 1179 * @param x5t The X.509 certificate SHA-1 thumbprint, 1180 * {@code null} if not specified. 1181 * @param x5t256 The X.509 certificate SHA-256 thumbprint, 1182 * {@code null} if not specified. 1183 * @param x5c The X.509 certificate chain, {@code null} if not 1184 * specified. 1185 * @param exp The key expiration time, {@code null} if not 1186 * specified. 1187 * @param nbf The key not-before time, {@code null} if not 1188 * specified. 1189 * @param iat The key issued-at time, {@code null} if not 1190 * specified. 1191 * @param revocation The key revocation, {@code null} if not specified. 1192 * @param ks Reference to the underlying key store, 1193 * {@code null} if not specified. 1194 */ 1195 public ECKey(final Curve crv, final Base64URL x, final Base64URL y, final Base64URL d, 1196 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1197 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 1198 final Date exp, final Date nbf, final Date iat, final KeyRevocation revocation, 1199 final KeyStore ks) { 1200 1201 super(KeyType.EC, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, revocation, ks); 1202 this.crv = Objects.requireNonNull(crv, "The curve must not be null"); 1203 this.x = Objects.requireNonNull(x, "The x coordinate must not be null"); 1204 this.y = Objects.requireNonNull(y, "The y coordinate must not be null"); 1205 ensurePublicCoordinatesOnCurve(crv, x, y); 1206 ensureMatches(getParsedX509CertChain()); 1207 this.d = Objects.requireNonNull(d, "The d coordinate must not be null"); 1208 this.privateKey = null; 1209 } 1210 1211 1212 /** 1213 * Creates a new public / private Elliptic Curve JSON Web Key (JWK) 1214 * with the specified parameters. The private key is specified by its 1215 * PKCS#11 handle. 1216 * 1217 * @param crv The cryptographic curve. Must not be {@code null}. 1218 * @param x The public 'x' coordinate for the elliptic curve 1219 * point. It is represented as the Base64URL encoding of 1220 * the coordinate's big endian representation. Must not 1221 * be {@code null}. 1222 * @param y The public 'y' coordinate for the elliptic curve 1223 * point. It is represented as the Base64URL encoding of 1224 * the coordinate's big endian representation. Must not 1225 * be {@code null}. 1226 * @param priv The private key as a PKCS#11 handle, {@code null} if 1227 * not specified. 1228 * @param use The key use, {@code null} if not specified or if the 1229 * key is intended for signing as well as encryption. 1230 * @param ops The key operations, {@code null} if not specified. 1231 * @param alg The intended JOSE algorithm for the key, {@code null} 1232 * if not specified. 1233 * @param kid The key ID, {@code null} if not specified. 1234 * @param x5u The X.509 certificate URL, {@code null} if not 1235 * specified. 1236 * @param x5t The X.509 certificate SHA-1 thumbprint, {@code null} 1237 * if not specified. 1238 * @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null} 1239 * if not specified. 1240 * @param x5c The X.509 certificate chain, {@code null} if not 1241 * specified. 1242 * @param exp The key expiration time, {@code null} if not 1243 * specified. 1244 * @param nbf The key not-before time, {@code null} if not 1245 * specified. 1246 * @param iat The key issued-at time, {@code null} if not specified. 1247 * @param ks Reference to the underlying key store, {@code null} if 1248 * not specified. 1249 */ 1250 @Deprecated 1251 public ECKey(final Curve crv, final Base64URL x, final Base64URL y, final PrivateKey priv, 1252 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1253 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 1254 final Date exp, final Date nbf, final Date iat, 1255 final KeyStore ks) { 1256 1257 this(crv, x, y, priv, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, null, ks); 1258 } 1259 1260 1261 // JWK public + private handle 1262 /** 1263 * Creates a new public / private Elliptic Curve JSON Web Key (JWK) 1264 * with the specified parameters. The private key is specified by its 1265 * PKCS#11 handle. 1266 * 1267 * @param crv The cryptographic curve. Must not be {@code null}. 1268 * @param x The public 'x' coordinate for the elliptic curve 1269 * point. It is represented as the Base64URL encoding 1270 * of the coordinate's big endian representation. 1271 * Must not be {@code null}. 1272 * @param y The public 'y' coordinate for the elliptic curve 1273 * point. It is represented as the Base64URL encoding 1274 * of the coordinate's big endian representation. 1275 * Must not be {@code null}. 1276 * @param priv The private key as a PKCS#11 handle, {@code null} 1277 * if not specified. 1278 * @param use The key use, {@code null} if not specified or if 1279 * the key is intended for signing as well as 1280 * encryption. 1281 * @param ops The key operations, {@code null} if not specified. 1282 * @param alg The intended JOSE algorithm for the key, 1283 * {@code null} if not specified. 1284 * @param kid The key ID, {@code null} if not specified. 1285 * @param x5u The X.509 certificate URL, {@code null} if not 1286 * specified. 1287 * @param x5t The X.509 certificate SHA-1 thumbprint, 1288 * {@code null} if not specified. 1289 * @param x5t256 The X.509 certificate SHA-256 thumbprint, 1290 * {@code null} if not specified. 1291 * @param x5c The X.509 certificate chain, {@code null} if not 1292 * specified. 1293 * @param exp The key expiration time, {@code null} if not 1294 * specified. 1295 * @param nbf The key not-before time, {@code null} if not 1296 * specified. 1297 * @param iat The key issued-at time, {@code null} if not 1298 * specified. 1299 * @param revocation The key revocation, {@code null} if not specified. 1300 * @param ks Reference to the underlying key store, 1301 * {@code null} if not specified. 1302 */ 1303 public ECKey(final Curve crv, final Base64URL x, final Base64URL y, final PrivateKey priv, 1304 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1305 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 1306 final Date exp, final Date nbf, final Date iat, final KeyRevocation revocation, 1307 final KeyStore ks) { 1308 1309 super(KeyType.EC, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, revocation, ks); 1310 this.crv = Objects.requireNonNull(crv, "The curve must not be null"); 1311 this.x = Objects.requireNonNull(x, "The x coordinate must not be null"); 1312 this.y = Objects.requireNonNull(y, "The y coordinate must not be null"); 1313 ensurePublicCoordinatesOnCurve(crv, x, y); 1314 ensureMatches(getParsedX509CertChain()); 1315 d = null; 1316 this.privateKey = priv; 1317 } 1318 1319 1320 /** 1321 * Creates a new public Elliptic Curve JSON Web Key (JWK) with the 1322 * specified parameters. 1323 * 1324 * @param crv The cryptographic curve. Must not be {@code null}. 1325 * @param pub The public EC key to represent. Must not be 1326 * {@code null}. 1327 * @param use The key use, {@code null} if not specified or if the 1328 * key is intended for signing as well as encryption. 1329 * @param ops The key operations, {@code null} if not specified. 1330 * @param alg The intended JOSE algorithm for the key, {@code null} 1331 * if not specified. 1332 * @param kid The key ID, {@code null} if not specified. 1333 * @param x5u The X.509 certificate URL, {@code null} if not 1334 * specified. 1335 * @param x5t The X.509 certificate SHA-1 thumbprint, {@code null} 1336 * if not specified. 1337 * @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null} 1338 * if not specified. 1339 * @param x5c The X.509 certificate chain, {@code null} if not 1340 * specified. 1341 * @param exp The key expiration time, {@code null} if not 1342 * specified. 1343 * @param nbf The key not-before time, {@code null} if not 1344 * specified. 1345 * @param iat The key issued-at time, {@code null} if not specified. 1346 * @param ks Reference to the underlying key store, {@code null} if 1347 * not specified. 1348 */ 1349 @Deprecated 1350 public ECKey(final Curve crv, final ECPublicKey pub, 1351 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1352 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 1353 final Date exp, final Date nbf, final Date iat, 1354 final KeyStore ks) { 1355 1356 this(crv, pub, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, null, ks); 1357 } 1358 1359 1360 // Java public 1361 /** 1362 * Creates a new public Elliptic Curve JSON Web Key (JWK) with the 1363 * specified parameters. 1364 * 1365 * @param crv The cryptographic curve. Must not be {@code null}. 1366 * @param pub The public EC key to represent. Must not be 1367 * {@code null}. 1368 * @param use The key use, {@code null} if not specified or if 1369 * the key is intended for signing as well as 1370 * encryption. 1371 * @param ops The key operations, {@code null} if not specified. 1372 * @param alg The intended JOSE algorithm for the key, 1373 * {@code null} if not specified. 1374 * @param kid The key ID, {@code null} if not specified. 1375 * @param x5u The X.509 certificate URL, {@code null} if not 1376 * specified. 1377 * @param x5t The X.509 certificate SHA-1 thumbprint, 1378 * {@code null} if not specified. 1379 * @param x5t256 The X.509 certificate SHA-256 thumbprint, 1380 * {@code null} if not specified. 1381 * @param x5c The X.509 certificate chain, {@code null} if not 1382 * specified. 1383 * @param exp The key expiration time, {@code null} if not 1384 * specified. 1385 * @param nbf The key not-before time, {@code null} if not 1386 * specified. 1387 * @param iat The key issued-at time, {@code null} if not 1388 * specified. 1389 * @param revocation The key revocation, {@code null} if not specified. 1390 * @param ks Reference to the underlying key store, 1391 * {@code null} if not specified. 1392 */ 1393 public ECKey(final Curve crv, final ECPublicKey pub, 1394 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1395 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 1396 final Date exp, final Date nbf, final Date iat, final KeyRevocation revocation, 1397 final KeyStore ks) { 1398 1399 this(crv, 1400 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()), 1401 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()), 1402 use, ops, alg, kid, 1403 x5u, x5t, x5t256, x5c, 1404 exp, nbf, iat, revocation, 1405 ks); 1406 } 1407 1408 1409 /** 1410 * Creates a new public / private Elliptic Curve JSON Web Key (JWK) 1411 * with the specified parameters. 1412 * 1413 * @param crv The cryptographic curve. Must not be {@code null}. 1414 * @param pub The public EC key to represent. Must not be 1415 * {@code null}. 1416 * @param priv The private EC key to represent. Must not be 1417 * {@code null}. 1418 * @param use The key use, {@code null} if not specified or if the 1419 * key is intended for signing as well as encryption. 1420 * @param ops The key operations, {@code null} if not specified. 1421 * @param alg The intended JOSE algorithm for the key, {@code null} 1422 * if not specified. 1423 * @param kid The key ID, {@code null} if not specified. 1424 * @param x5u The X.509 certificate URL, {@code null} if not 1425 * specified. 1426 * @param x5t The X.509 certificate SHA-1 thumbprint, {@code null} 1427 * if not specified. 1428 * @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null} 1429 * if not specified. 1430 * @param x5c The X.509 certificate chain, {@code null} if not 1431 * specified. 1432 * @param exp The key expiration time, {@code null} if not 1433 * specified. 1434 * @param nbf The key not-before time, {@code null} if not 1435 * specified. 1436 * @param iat The key issued-at time, {@code null} if not specified. 1437 * @param ks Reference to the underlying key store, {@code null} if 1438 * not specified. 1439 */ 1440 @Deprecated 1441 public ECKey(final Curve crv, final ECPublicKey pub, final ECPrivateKey priv, 1442 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1443 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 1444 final Date exp, final Date nbf, final Date iat, 1445 final KeyStore ks) { 1446 1447 this(crv, pub, priv, use, ops, alg, kid, x5u, x5t, x5t256, x5c, exp, nbf, iat, null, ks); 1448 } 1449 1450 1451 // Java public + private 1452 /** 1453 * Creates a new public / private Elliptic Curve JSON Web Key (JWK) 1454 * with the specified parameters. 1455 * 1456 * @param crv The cryptographic curve. Must not be {@code null}. 1457 * @param pub The public EC key to represent. Must not be 1458 * {@code null}. 1459 * @param priv The private EC key to represent. Must not be 1460 * {@code null}. 1461 * @param use The key use, {@code null} if not specified or if 1462 * the key is intended for signing as well as 1463 * encryption. 1464 * @param ops The key operations, {@code null} if not specified. 1465 * @param alg The intended JOSE algorithm for the key, 1466 * {@code null} if not specified. 1467 * @param kid The key ID, {@code null} if not specified. 1468 * @param x5u The X.509 certificate URL, {@code null} if not 1469 * specified. 1470 * @param x5t The X.509 certificate SHA-1 thumbprint, 1471 * {@code null} if not specified. 1472 * @param x5t256 The X.509 certificate SHA-256 thumbprint, 1473 * {@code null} if not specified. 1474 * @param x5c The X.509 certificate chain, {@code null} if not 1475 * specified. 1476 * @param exp The key expiration time, {@code null} if not 1477 * specified. 1478 * @param nbf The key not-before time, {@code null} if not 1479 * specified. 1480 * @param iat The key issued-at time, {@code null} if not 1481 * specified. 1482 * @param revocation The key revocation, {@code null} if not specified. 1483 * @param ks Reference to the underlying key store, 1484 * {@code null} if not specified. 1485 */ 1486 public ECKey(final Curve crv, final ECPublicKey pub, final ECPrivateKey priv, 1487 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1488 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 1489 final Date exp, final Date nbf, final Date iat, final KeyRevocation revocation, 1490 final KeyStore ks) { 1491 1492 this(crv, 1493 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()), 1494 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()), 1495 encodeCoordinate(priv.getParams().getCurve().getField().getFieldSize(), priv.getS()), 1496 use, ops, alg, kid, 1497 x5u, x5t, x5t256, x5c, 1498 exp, nbf, iat, revocation, 1499 ks); 1500 } 1501 1502 1503 /** 1504 * Creates a new public / private Elliptic Curve JSON Web Key (JWK) 1505 * with the specified parameters. The private key is specified by its 1506 * PKCS#11 handle. 1507 * 1508 * @param crv The cryptographic curve. Must not be {@code null}. 1509 * @param pub The public EC key to represent. Must not be 1510 * {@code null}. 1511 * @param priv The private key as a PKCS#11 handle, {@code null} if 1512 * not specified. 1513 * @param use The key use, {@code null} if not specified or if the 1514 * key is intended for signing as well as encryption. 1515 * @param ops The key operations, {@code null} if not specified. 1516 * @param alg The intended JOSE algorithm for the key, {@code null} 1517 * if not specified. 1518 * @param kid The key ID, {@code null} if not specified. 1519 * @param x5u The X.509 certificate URL, {@code null} if not 1520 * specified. 1521 * @param x5t The X.509 certificate SHA-1 thumbprint, {@code null} 1522 * if not specified. 1523 * @param x5t256 The X.509 certificate SHA-256 thumbprint, {@code null} 1524 * if not specified. 1525 * @param x5c The X.509 certificate chain, {@code null} if not 1526 * specified. 1527 * @param exp The key expiration time, {@code null} if not 1528 * specified. 1529 * @param nbf The key not-before time, {@code null} if not 1530 * specified. 1531 * @param iat The key issued-at time, {@code null} if not specified. 1532 * @param ks Reference to the underlying key store, {@code null} if 1533 * not specified. 1534 */ 1535 @Deprecated 1536 public ECKey(final Curve crv, final ECPublicKey pub, final PrivateKey priv, 1537 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1538 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 1539 final Date exp, final Date nbf, final Date iat, 1540 final KeyStore ks) { 1541 1542 this( 1543 crv, 1544 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()), 1545 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()), 1546 priv, 1547 use, ops, alg, kid, x5u, x5t, x5t256, x5c, 1548 exp, nbf, iat, 1549 ks); 1550 } 1551 1552 1553 // Java public + private handle 1554 /** 1555 * Creates a new public / private Elliptic Curve JSON Web Key (JWK) 1556 * with the specified parameters. The private key is specified by its 1557 * PKCS#11 handle. 1558 * 1559 * @param crv The cryptographic curve. Must not be {@code null}. 1560 * @param pub The public EC key to represent. Must not be 1561 * {@code null}. 1562 * @param priv The private key as a PKCS#11 handle, {@code null} 1563 * if not specified. 1564 * @param use The key use, {@code null} if not specified or if 1565 * the key is intended for signing as well as 1566 * encryption. 1567 * @param ops The key operations, {@code null} if not specified. 1568 * @param alg The intended JOSE algorithm for the key, 1569 * {@code null} if not specified. 1570 * @param kid The key ID, {@code null} if not specified. 1571 * @param x5u The X.509 certificate URL, {@code null} if not 1572 * specified. 1573 * @param x5t The X.509 certificate SHA-1 thumbprint, 1574 * {@code null} if not specified. 1575 * @param x5t256 The X.509 certificate SHA-256 thumbprint, 1576 * {@code null} if not specified. 1577 * @param x5c The X.509 certificate chain, {@code null} if not 1578 * specified. 1579 * @param exp The key expiration time, {@code null} if not 1580 * specified. 1581 * @param nbf The key not-before time, {@code null} if not 1582 * specified. 1583 * @param iat The key issued-at time, {@code null} if not 1584 * specified. 1585 * @param revocation The key revocation, {@code null} if not specified. 1586 * @param ks Reference to the underlying key store, 1587 * {@code null} if not specified. 1588 */ 1589 public ECKey(final Curve crv, final ECPublicKey pub, final PrivateKey priv, 1590 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1591 final URI x5u, final Base64URL x5t, final Base64URL x5t256, final List<Base64> x5c, 1592 final Date exp, final Date nbf, final Date iat, final KeyRevocation revocation, 1593 final KeyStore ks) { 1594 1595 this( 1596 crv, 1597 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineX()), 1598 encodeCoordinate(pub.getParams().getCurve().getField().getFieldSize(), pub.getW().getAffineY()), 1599 priv, 1600 use, ops, alg, kid, x5u, x5t, x5t256, x5c, 1601 exp, nbf, iat, revocation, 1602 ks); 1603 } 1604 1605 1606 @Override 1607 public Curve getCurve() { 1608 1609 return crv; 1610 } 1611 1612 1613 /** 1614 * Gets the public 'x' coordinate for the elliptic curve point. 1615 * 1616 * @return The 'x' coordinate. It is represented as the Base64URL 1617 * encoding of the coordinate's big endian representation. 1618 */ 1619 public Base64URL getX() { 1620 1621 return x; 1622 } 1623 1624 1625 /** 1626 * Gets the public 'y' coordinate for the elliptic curve point. 1627 * 1628 * @return The 'y' coordinate. It is represented as the Base64URL 1629 * encoding of the coordinate's big endian representation. 1630 */ 1631 public Base64URL getY() { 1632 1633 return y; 1634 } 1635 1636 1637 /** 1638 * Gets the private 'd' coordinate for the elliptic curve point. It is 1639 * represented as the Base64URL encoding of the coordinate's big endian 1640 * representation. 1641 * 1642 * @return The 'd' coordinate. It is represented as the Base64URL 1643 * encoding of the coordinate's big endian representation. 1644 * {@code null} if not specified (for a public key). 1645 */ 1646 public Base64URL getD() { 1647 1648 return d; 1649 } 1650 1651 1652 /** 1653 * Returns a standard {@code java.security.interfaces.ECPublicKey} 1654 * representation of this Elliptic Curve JWK. Uses the default JCA 1655 * provider. 1656 * 1657 * @return The public Elliptic Curve key. 1658 * 1659 * @throws JOSEException If EC is not supported by the underlying Java 1660 * Cryptography (JCA) provider or if the JWK 1661 * parameters are invalid for a public EC key. 1662 */ 1663 public ECPublicKey toECPublicKey() 1664 throws JOSEException { 1665 1666 return toECPublicKey(null); 1667 } 1668 1669 1670 /** 1671 * Returns a standard {@code java.security.interfaces.ECPublicKey} 1672 * representation of this Elliptic Curve JWK. 1673 * 1674 * @param provider The JCA provider to use, {@code null} implies the 1675 * default. 1676 * 1677 * @return The public Elliptic Curve key. 1678 * 1679 * @throws JOSEException If EC is not supported by the underlying Java 1680 * Cryptography (JCA) provider or if the JWK 1681 * parameters are invalid for a public EC key. 1682 */ 1683 public ECPublicKey toECPublicKey(final Provider provider) 1684 throws JOSEException { 1685 1686 ECParameterSpec spec = crv.toECParameterSpec(); 1687 1688 if (spec == null) { 1689 throw new JOSEException("Couldn't get EC parameter spec for curve " + crv); 1690 } 1691 1692 ECPoint w = new ECPoint(x.decodeToBigInteger(), y.decodeToBigInteger()); 1693 1694 ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(w, spec); 1695 1696 try { 1697 KeyFactory keyFactory; 1698 1699 if (provider == null) { 1700 keyFactory = KeyFactory.getInstance("EC"); 1701 } else { 1702 keyFactory = KeyFactory.getInstance("EC", provider); 1703 } 1704 1705 return (ECPublicKey) keyFactory.generatePublic(publicKeySpec); 1706 1707 } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { 1708 1709 throw new JOSEException(e.getMessage(), e); 1710 } 1711 } 1712 1713 1714 /** 1715 * Returns a standard {@code java.security.interfaces.ECPrivateKey} 1716 * representation of this Elliptic Curve JWK. Uses the default JCA 1717 * provider. 1718 * 1719 * @return The private Elliptic Curve key, {@code null} if not 1720 * specified by this JWK. 1721 * 1722 * @throws JOSEException If EC is not supported by the underlying Java 1723 * Cryptography (JCA) provider or if the JWK 1724 * parameters are invalid for a private EC key. 1725 */ 1726 public ECPrivateKey toECPrivateKey() 1727 throws JOSEException { 1728 1729 return toECPrivateKey(null); 1730 } 1731 1732 1733 /** 1734 * Returns a standard {@code java.security.interfaces.ECPrivateKey} 1735 * representation of this Elliptic Curve JWK. 1736 * 1737 * @param provider The JCA provider to use, {@code null} implies the 1738 * default. 1739 * 1740 * @return The private Elliptic Curve key, {@code null} if not 1741 * specified by this JWK. 1742 * 1743 * @throws JOSEException If EC is not supported by the underlying Java 1744 * Cryptography (JCA) provider or if the JWK 1745 * parameters are invalid for a private EC key. 1746 */ 1747 public ECPrivateKey toECPrivateKey(final Provider provider) 1748 throws JOSEException { 1749 1750 if (d == null) { 1751 // No private 'd' param 1752 return null; 1753 } 1754 1755 ECParameterSpec spec = crv.toECParameterSpec(); 1756 1757 if (spec == null) { 1758 throw new JOSEException("Couldn't get EC parameter spec for curve " + crv); 1759 } 1760 1761 ECPrivateKeySpec privateKeySpec = new ECPrivateKeySpec(d.decodeToBigInteger(), spec); 1762 1763 try { 1764 KeyFactory keyFactory; 1765 1766 if (provider == null) { 1767 keyFactory = KeyFactory.getInstance("EC"); 1768 } else { 1769 keyFactory = KeyFactory.getInstance("EC", provider); 1770 } 1771 1772 return (ECPrivateKey) keyFactory.generatePrivate(privateKeySpec); 1773 1774 } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { 1775 1776 throw new JOSEException(e.getMessage(), e); 1777 } 1778 } 1779 1780 1781 @Override 1782 public PublicKey toPublicKey() 1783 throws JOSEException { 1784 1785 return toECPublicKey(); 1786 } 1787 1788 1789 @Override 1790 public PrivateKey toPrivateKey() 1791 throws JOSEException { 1792 1793 PrivateKey prv = toECPrivateKey(); 1794 1795 if (prv != null) { 1796 // Return private EC key with key material 1797 return prv; 1798 } 1799 1800 // Return private EC key as PKCS#11 handle, or null 1801 return privateKey; 1802 } 1803 1804 1805 /** 1806 * Returns a standard {@code java.security.KeyPair} representation of 1807 * this Elliptic Curve JWK. Uses the default JCA provider. 1808 * 1809 * @return The Elliptic Curve key pair. The private Elliptic Curve key 1810 * will be {@code null} if not specified. 1811 * 1812 * @throws JOSEException If EC is not supported by the underlying Java 1813 * Cryptography (JCA) provider or if the JWK 1814 * parameters are invalid for a public and / or 1815 * private EC key. 1816 */ 1817 @Override 1818 public KeyPair toKeyPair() 1819 throws JOSEException { 1820 1821 return toKeyPair(null); 1822 } 1823 1824 1825 /** 1826 * Returns a standard {@code java.security.KeyPair} representation of 1827 * this Elliptic Curve JWK. 1828 * 1829 * @param provider The JCA provider to use, {@code null} implies the 1830 * default. 1831 * 1832 * @return The Elliptic Curve key pair. The private Elliptic Curve key 1833 * will be {@code null} if not specified. 1834 * 1835 * @throws JOSEException If EC is not supported by the underlying Java 1836 * Cryptography (JCA) provider or if the JWK 1837 * parameters are invalid for a public and / or 1838 * private EC key. 1839 */ 1840 public KeyPair toKeyPair(final Provider provider) 1841 throws JOSEException { 1842 1843 if (privateKey != null) { 1844 // Private key as PKCS#11 handle 1845 return new KeyPair(toECPublicKey(provider), privateKey); 1846 } else { 1847 return new KeyPair(toECPublicKey(provider), toECPrivateKey(provider)); 1848 } 1849 } 1850 1851 1852 @Override 1853 public ECKey toRevokedJWK(final KeyRevocation keyRevocation) { 1854 1855 if (getKeyRevocation() != null) { 1856 throw new IllegalStateException("Already revoked"); 1857 } 1858 1859 return new ECKey.Builder(this) 1860 .keyRevocation(Objects.requireNonNull(keyRevocation)) 1861 .build(); 1862 } 1863 1864 1865 @Override 1866 public boolean matches(final X509Certificate cert) { 1867 1868 ECPublicKey certECKey; 1869 try { 1870 certECKey = (ECPublicKey) getParsedX509CertChain().get(0).getPublicKey(); 1871 } catch (ClassCastException ex) { 1872 return false; 1873 } 1874 // Compare Big Ints, base64url encoding may have padding! 1875 // https://tools.ietf.org/html/rfc7518#section-6.2.1.2 1876 if (! getX().decodeToBigInteger().equals(certECKey.getW().getAffineX())) { 1877 return false; 1878 } 1879 return getY().decodeToBigInteger().equals(certECKey.getW().getAffineY()); 1880 } 1881 1882 1883 /** 1884 * Calls {@link #matches(X509Certificate)} for the first X.509 1885 * certificate in the specified chain. 1886 * 1887 * @param chain The X.509 certificate chain, {@code null} if not 1888 * specified. 1889 * 1890 * @throws IllegalArgumentException If a certificate chain is specified 1891 * and the first certificate in it 1892 * doesn't match. 1893 */ 1894 private void ensureMatches(final List<X509Certificate> chain) { 1895 1896 if (chain == null) 1897 return; 1898 1899 if (! matches(chain.get(0))) 1900 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"); 1901 } 1902 1903 1904 @Override 1905 public LinkedHashMap<String,?> getRequiredParams() { 1906 1907 // Put mandatory params in sorted order 1908 LinkedHashMap<String,String> requiredParams = new LinkedHashMap<>(); 1909 requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE, crv.toString()); 1910 requiredParams.put(JWKParameterNames.KEY_TYPE, getKeyType().getValue()); 1911 requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE_X_COORDINATE, x.toString()); 1912 requiredParams.put(JWKParameterNames.ELLIPTIC_CURVE_Y_COORDINATE, y.toString()); 1913 return requiredParams; 1914 } 1915 1916 1917 @Override 1918 public boolean isPrivate() { 1919 1920 return d != null || privateKey != null; 1921 } 1922 1923 1924 @Override 1925 public int size() { 1926 1927 ECParameterSpec ecParameterSpec = crv.toECParameterSpec(); 1928 1929 if (ecParameterSpec == null) { 1930 throw new UnsupportedOperationException("Couldn't determine field size for curve " + crv.getName()); 1931 } 1932 1933 return ecParameterSpec.getCurve().getField().getFieldSize(); 1934 } 1935 1936 1937 /** 1938 * Returns a copy of this Elliptic Curve JWK with any private values 1939 * removed. 1940 * 1941 * @return The copied public Elliptic Curve JWK. 1942 */ 1943 @Override 1944 public ECKey toPublicJWK() { 1945 1946 return new ECKey( 1947 getCurve(), getX(), getY(), 1948 getKeyUse(), getKeyOperations(), getAlgorithm(), getKeyID(), 1949 getX509CertURL(), getX509CertThumbprint(), getX509CertSHA256Thumbprint(), getX509CertChain(), 1950 getExpirationTime(), getNotBeforeTime(), getIssueTime(), getKeyRevocation(), 1951 getKeyStore()); 1952 } 1953 1954 1955 @Override 1956 public Map<String, Object> toJSONObject() { 1957 1958 Map<String, Object> o = super.toJSONObject(); 1959 1960 // Append EC specific attributes 1961 o.put(JWKParameterNames.ELLIPTIC_CURVE, crv.toString()); 1962 o.put(JWKParameterNames.ELLIPTIC_CURVE_X_COORDINATE, x.toString()); 1963 o.put(JWKParameterNames.ELLIPTIC_CURVE_Y_COORDINATE, y.toString()); 1964 1965 if (d != null) { 1966 o.put(JWKParameterNames.ELLIPTIC_CURVE_PRIVATE_KEY, d.toString()); 1967 } 1968 1969 return o; 1970 } 1971 1972 1973 /** 1974 * Parses a public / private Elliptic Curve JWK from the specified JSON 1975 * object string representation. 1976 * 1977 * @param s The JSON object string to parse. Must not be {@code null}. 1978 * 1979 * @return The public / private Elliptic Curve JWK. 1980 * 1981 * @throws ParseException If the string couldn't be parsed to an 1982 * Elliptic Curve JWK. 1983 */ 1984 public static ECKey parse(final String s) 1985 throws ParseException { 1986 1987 return parse(JSONObjectUtils.parse(s)); 1988 } 1989 1990 1991 /** 1992 * Parses a public / private Elliptic Curve JWK from the specified JSON 1993 * object representation. 1994 * 1995 * @param jsonObject The JSON object to parse. Must not be 1996 * {@code null}. 1997 * 1998 * @return The public / private Elliptic Curve JWK. 1999 * 2000 * @throws ParseException If the JSON object couldn't be parsed to an 2001 * Elliptic Curve JWK. 2002 */ 2003 public static ECKey parse(final Map<String, Object> jsonObject) 2004 throws ParseException { 2005 2006 // Check key type 2007 if (! KeyType.EC.equals(JWKMetadata.parseKeyType(jsonObject))) { 2008 throw new ParseException("The key type \"kty\" must be EC", 0); 2009 } 2010 2011 // Parse the mandatory public key parameters 2012 Curve crv; 2013 try { 2014 crv = Curve.parse(JSONObjectUtils.getString(jsonObject, JWKParameterNames.ELLIPTIC_CURVE)); 2015 } catch (IllegalArgumentException e) { 2016 throw new ParseException(e.getMessage(), 0); 2017 } 2018 2019 Base64URL x = JSONObjectUtils.getBase64URL(jsonObject, JWKParameterNames.ELLIPTIC_CURVE_X_COORDINATE); 2020 Base64URL y = JSONObjectUtils.getBase64URL(jsonObject, JWKParameterNames.ELLIPTIC_CURVE_Y_COORDINATE); 2021 2022 // Get optional private key 2023 Base64URL d = JSONObjectUtils.getBase64URL(jsonObject, JWKParameterNames.ELLIPTIC_CURVE_PRIVATE_KEY); 2024 2025 try { 2026 if (d == null) { 2027 // Public key 2028 return new ECKey(crv, x, y, 2029 JWKMetadata.parseKeyUse(jsonObject), 2030 JWKMetadata.parseKeyOperations(jsonObject), 2031 JWKMetadata.parseAlgorithm(jsonObject), 2032 JWKMetadata.parseKeyID(jsonObject), 2033 JWKMetadata.parseX509CertURL(jsonObject), 2034 JWKMetadata.parseX509CertThumbprint(jsonObject), 2035 JWKMetadata.parseX509CertSHA256Thumbprint(jsonObject), 2036 JWKMetadata.parseX509CertChain(jsonObject), 2037 JWKMetadata.parseExpirationTime(jsonObject), 2038 JWKMetadata.parseNotBeforeTime(jsonObject), 2039 JWKMetadata.parseIssueTime(jsonObject), 2040 JWKMetadata.parseKeyRevocation(jsonObject), 2041 null); 2042 2043 } else { 2044 // Key pair 2045 return new ECKey(crv, x, y, d, 2046 JWKMetadata.parseKeyUse(jsonObject), 2047 JWKMetadata.parseKeyOperations(jsonObject), 2048 JWKMetadata.parseAlgorithm(jsonObject), 2049 JWKMetadata.parseKeyID(jsonObject), 2050 JWKMetadata.parseX509CertURL(jsonObject), 2051 JWKMetadata.parseX509CertThumbprint(jsonObject), 2052 JWKMetadata.parseX509CertSHA256Thumbprint(jsonObject), 2053 JWKMetadata.parseX509CertChain(jsonObject), 2054 JWKMetadata.parseExpirationTime(jsonObject), 2055 JWKMetadata.parseNotBeforeTime(jsonObject), 2056 JWKMetadata.parseIssueTime(jsonObject), 2057 JWKMetadata.parseKeyRevocation(jsonObject), 2058 null); 2059 } 2060 2061 } catch (Exception ex) { 2062 2063 // Missing x or y, conflicting 'use' and 'key_ops' 2064 throw new ParseException(ex.getMessage(), 0); 2065 } 2066 } 2067 2068 2069 /** 2070 * Parses a public Elliptic Curve JWK from the specified X.509 2071 * certificate. Requires BouncyCastle. 2072 * 2073 * <p><strong>Important:</strong> The X.509 certificate is not 2074 * validated! 2075 * 2076 * <p>Sets the following JWK parameters: 2077 * 2078 * <ul> 2079 * <li>The curve is obtained from the subject public key info 2080 * algorithm parameters. 2081 * <li>The JWK use inferred by {@link KeyUse#from}. 2082 * <li>The JWK ID from the X.509 serial number (in base 10). 2083 * <li>The JWK X.509 certificate chain (this certificate only). 2084 * <li>The JWK X.509 certificate SHA-256 thumbprint. 2085 * </ul> 2086 * 2087 * @param cert The X.509 certificate. Must not be {@code null}. 2088 * 2089 * @return The public Elliptic Curve JWK. 2090 * 2091 * @throws JOSEException If parsing failed. 2092 */ 2093 public static ECKey parse(final X509Certificate cert) 2094 throws JOSEException { 2095 2096 if (! (cert.getPublicKey() instanceof ECPublicKey)) { 2097 throw new JOSEException("The public key of the X.509 certificate is not EC"); 2098 } 2099 2100 ECPublicKey publicKey = (ECPublicKey) cert.getPublicKey(); 2101 2102 try { 2103 JcaX509CertificateHolder certHolder = new JcaX509CertificateHolder(cert); 2104 2105 String oid = certHolder.getSubjectPublicKeyInfo().getAlgorithm().getParameters().toString(); 2106 2107 Curve crv = Curve.forOID(oid); 2108 2109 if (crv == null) { 2110 throw new JOSEException("Couldn't determine EC JWK curve for OID " + oid); 2111 } 2112 2113 MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); 2114 2115 return new ECKey.Builder(crv, publicKey) 2116 .keyUse(KeyUse.from(cert)) 2117 .keyID(cert.getSerialNumber().toString(10)) 2118 .x509CertChain(Collections.singletonList(Base64.encode(cert.getEncoded()))) 2119 .x509CertSHA256Thumbprint(Base64URL.encode(sha256.digest(cert.getEncoded()))) 2120 .expirationTime(cert.getNotAfter()) 2121 .notBeforeTime(cert.getNotBefore()) 2122 .build(); 2123 } catch (NoSuchAlgorithmException e) { 2124 throw new JOSEException("Couldn't encode x5t parameter: " + e.getMessage(), e); 2125 } catch (CertificateEncodingException e) { 2126 throw new JOSEException("Couldn't encode x5c parameter: " + e.getMessage(), e); 2127 } 2128 } 2129 2130 2131 /** 2132 * Loads a public / private Elliptic Curve JWK from the specified JCA 2133 * key store. Requires BouncyCastle. 2134 * 2135 * <p><strong>Important:</strong> The X.509 certificate is not 2136 * validated! 2137 * 2138 * @param keyStore The key store. Must not be {@code null}. 2139 * @param alias The alias. Must not be {@code null}. 2140 * @param pin The pin to unlock the private key if any, empty or 2141 * {@code null} if not required. 2142 * 2143 * @return The public / private Elliptic Curve JWK., {@code null} if no 2144 * key with the specified alias was found. 2145 * 2146 * @throws KeyStoreException On a key store exception. 2147 * @throws JOSEException If EC key loading failed. 2148 */ 2149 public static ECKey load(final KeyStore keyStore, 2150 final String alias, 2151 final char[] pin) 2152 throws KeyStoreException, JOSEException { 2153 2154 Certificate cert = keyStore.getCertificate(alias); 2155 2156 if (!(cert instanceof X509Certificate)) { 2157 return null; 2158 } 2159 2160 X509Certificate x509Cert = (X509Certificate)cert; 2161 2162 if (! (x509Cert.getPublicKey() instanceof ECPublicKey)) { 2163 throw new JOSEException("Couldn't load EC JWK: The key algorithm is not EC"); 2164 } 2165 2166 ECKey ecJWK = ECKey.parse(x509Cert); 2167 2168 // Let kid=alias 2169 ecJWK = new ECKey.Builder(ecJWK).keyID(alias).keyStore(keyStore).build(); 2170 2171 // Check for private counterpart 2172 Key key; 2173 try { 2174 key = keyStore.getKey(alias, pin); 2175 } catch (UnrecoverableKeyException | NoSuchAlgorithmException e) { 2176 throw new JOSEException("Couldn't retrieve private EC key (bad pin?): " + e.getMessage(), e); 2177 } 2178 2179 if (key instanceof ECPrivateKey) { 2180 // Simple file based key store 2181 return new ECKey.Builder(ecJWK) 2182 .privateKey((ECPrivateKey)key) 2183 .build(); 2184 } else if (key instanceof PrivateKey && "EC".equalsIgnoreCase(key.getAlgorithm())) { 2185 // PKCS#11 store 2186 return new ECKey.Builder(ecJWK) 2187 .privateKey((PrivateKey)key) 2188 .build(); 2189 } else { 2190 return ecJWK; 2191 } 2192 } 2193 2194 2195 @Override 2196 public boolean equals(Object o) { 2197 if (this == o) return true; 2198 if (!(o instanceof ECKey)) return false; 2199 if (!super.equals(o)) return false; 2200 ECKey ecKey = (ECKey) o; 2201 return Objects.equals(crv, ecKey.crv) && 2202 Objects.equals(x, ecKey.x) && 2203 Objects.equals(y, ecKey.y) && 2204 Objects.equals(d, ecKey.d) && 2205 Objects.equals(privateKey, ecKey.privateKey); 2206 } 2207 2208 2209 @Override 2210 public int hashCode() { 2211 return Objects.hash(super.hashCode(), crv, x, y, d, privateKey); 2212 } 2213}