001package com.nimbusds.jose.jwk; 002 003 004import java.net.URI; 005import java.math.BigInteger; 006import java.nio.charset.Charset; 007import java.security.KeyFactory; 008import java.security.KeyPair; 009import java.security.MessageDigest; 010import java.security.NoSuchAlgorithmException; 011import java.security.interfaces.RSAMultiPrimePrivateCrtKey; 012import java.security.interfaces.RSAPrivateCrtKey; 013import java.security.interfaces.RSAPrivateKey; 014import java.security.interfaces.RSAPublicKey; 015import java.security.spec.InvalidKeySpecException; 016import java.security.spec.RSAMultiPrimePrivateCrtKeySpec; 017import java.security.spec.RSAOtherPrimeInfo; 018import java.security.spec.RSAPrivateCrtKeySpec; 019import java.security.spec.RSAPrivateKeySpec; 020import java.security.spec.RSAPublicKeySpec; 021import java.text.ParseException; 022import java.util.*; 023 024import net.jcip.annotations.Immutable; 025 026import net.minidev.json.JSONArray; 027import net.minidev.json.JSONObject; 028 029import com.nimbusds.jose.Algorithm; 030import com.nimbusds.jose.JOSEException; 031import com.nimbusds.jose.util.Base64; 032import com.nimbusds.jose.util.Base64URL; 033import com.nimbusds.jose.util.JSONObjectUtils; 034 035 036/** 037 * Public and private {@link KeyType#RSA RSA} JSON Web Key (JWK). This class is 038 * immutable. 039 * 040 * <p>Provides RSA JWK import from / export to the following standard Java 041 * interfaces and classes: 042 * 043 * <ul> 044 * <li>{@code java.security.interfaces.RSAPublicKey} 045 * <li>{@code java.security.interfaces.RSAPrivateKey} 046 * <ul> 047 * <li>{@code java.security.interfaces.RSAPrivateCrtKey} 048 * <li>{@code java.security.interfaces.RSAMultiPrimePrivateCrtKey} 049 * </ul> 050 * <li>{@code java.security.KeyPair} 051 * </ul> 052 * 053 * <p>Example JSON object representation of a public RSA JWK: 054 * 055 * <pre> 056 * { 057 * "kty" : "RSA", 058 * "n" : "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx 059 * 4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs 060 * tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2 061 * QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI 062 * SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb 063 * w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", 064 * "e" : "AQAB", 065 * "alg" : "RS256", 066 * "kid" : "2011-04-29" 067 * } 068 * </pre> 069 * 070 * <p>Example JSON object representation of a public and private RSA JWK (with 071 * both the first and the second private key representations): 072 * 073 * <pre> 074 * { 075 * "kty" : "RSA", 076 * "n" : "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx 077 * 4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs 078 * tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2 079 * QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI 080 * SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb 081 * w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", 082 * "e" : "AQAB", 083 * "d" : "X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9 084 * M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqij 085 * wp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d 086 * _cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBz 087 * nbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFz 088 * me1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q", 089 * "p" : "83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPV 090 * nwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqV 091 * WlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs", 092 * "q" : "3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyum 093 * qjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgx 094 * kIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk", 095 * "dp" : "G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oim 096 * YwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_Nmtu 097 * YZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0", 098 * "dq" : "s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUU 099 * vMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9 100 * GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk", 101 * "qi" : "GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzg 102 * UIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rx 103 * yR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU", 104 * "alg" : "RS256", 105 * "kid" : "2011-04-29" 106 * } 107 * </pre> 108 * 109 * <p>See RFC 3447. 110 * 111 * <p>See http://en.wikipedia.org/wiki/RSA_%28algorithm%29 112 * 113 * @author Vladimir Dzhuvinov 114 * @author Justin Richer 115 * @author Cedric Staub 116 * @version 2015-09-21 117 */ 118@Immutable 119public final class RSAKey extends JWK { 120 121 122 /** 123 * Other Primes Info, represents the private {@code oth} parameter of a 124 * RSA JWK. This class is immutable. 125 */ 126 @Immutable 127 public static class OtherPrimesInfo { 128 129 130 /** 131 * The prime factor. 132 */ 133 private final Base64URL r; 134 135 136 /** 137 * The factor Chinese Remainder Theorem (CRT) exponent. 138 */ 139 private final Base64URL d; 140 141 142 /** 143 * The factor Chinese Remainder Theorem (CRT) coefficient. 144 */ 145 private final Base64URL t; 146 147 148 /** 149 * Creates a new JWK Other Primes Info with the specified 150 * parameters. 151 * 152 * @param r The prime factor. Must not be {@code null}. 153 * @param d The factor Chinese Remainder Theorem (CRT) 154 * exponent. Must not be {@code null}. 155 * @param t The factor Chinese Remainder Theorem (CRT) 156 * coefficient. Must not be {@code null}. 157 */ 158 public OtherPrimesInfo(final Base64URL r, final Base64URL d, final Base64URL t) { 159 160 if (r == null) { 161 162 throw new IllegalArgumentException("The prime factor must not be null"); 163 } 164 165 this.r = r; 166 167 if (d == null) { 168 169 throw new IllegalArgumentException("The factor CRT exponent must not be null"); 170 } 171 172 this.d = d; 173 174 if (t == null) { 175 176 throw new IllegalArgumentException("The factor CRT coefficient must not be null"); 177 } 178 179 this.t = t; 180 } 181 182 183 /** 184 * Creates a new JWK Other Primes Info from the specified 185 * {@code java.security.spec.RSAOtherPrimeInfo} instance. 186 * 187 * @param oth The RSA Other Primes Info instance. Must not be 188 * {@code null}. 189 */ 190 public OtherPrimesInfo(final RSAOtherPrimeInfo oth) { 191 192 r = Base64URL.encode(oth.getPrime()); 193 d = Base64URL.encode(oth.getExponent()); 194 t = Base64URL.encode(oth.getCrtCoefficient()); 195 } 196 197 198 /** 199 * Gets the prime factor ({@code r}). 200 * 201 * @return The prime factor. 202 */ 203 public Base64URL getPrimeFactor() { 204 205 return r; 206 } 207 208 209 /** 210 * Gets factor Chinese Remainder Theorem (CRT) exponent 211 * ({@code d}). 212 * 213 * @return The factor Chinese Remainder Theorem (CRT) exponent. 214 */ 215 public Base64URL getFactorCRTExponent() { 216 217 return d; 218 } 219 220 221 /** 222 * The factor Chinese Remainder Theorem (CRT) coefficient 223 * ({@code t}). 224 * 225 * @return The factor Chinese Remainder Theorem (CRT) 226 * coefficient. 227 */ 228 public Base64URL getFactorCRTCoefficient() { 229 230 return t; 231 } 232 233 234 /** 235 * Converts the specified array of 236 * {@code java.security.spec.RSAOtherPrimeInfo} instances to a 237 * list of JWK Other Prime Infos. 238 * 239 * @param othArray Array of RSA Other Primes Info instances. 240 * May be be {@code null}. 241 * 242 * @return The corresponding list of JWK Other Prime Infos, or 243 * empty list of the array was {@code null}. 244 */ 245 public static List<OtherPrimesInfo> toList(final RSAOtherPrimeInfo[] othArray) { 246 247 List<OtherPrimesInfo> list = new ArrayList<>(); 248 249 if (othArray == null) { 250 251 // Return empty list 252 return list; 253 } 254 255 for (RSAOtherPrimeInfo oth: othArray) { 256 257 list.add(new OtherPrimesInfo(oth)); 258 } 259 260 return list; 261 } 262 } 263 264 265 /** 266 * Builder for constructing RSA JWKs. 267 * 268 * <p>Example usage: 269 * 270 * <pre> 271 * RSAKey key = new RSAKey.Builder(n, e). 272 * privateExponent(d). 273 * algorithm(JWSAlgorithm.RS512). 274 * keyID("456"). 275 * build(); 276 * </pre> 277 */ 278 public static class Builder { 279 280 281 // Public RSA params 282 283 /** 284 * The modulus value for the RSA key. 285 */ 286 private final Base64URL n; 287 288 289 /** 290 * The public exponent of the RSA key. 291 */ 292 private final Base64URL e; 293 294 295 // Private RSA params, 1st representation 296 297 /** 298 * The private exponent of the RSA key. 299 */ 300 private Base64URL d; 301 302 303 // Private RSA params, 2nd representation 304 305 /** 306 * The first prime factor of the private RSA key. 307 */ 308 private Base64URL p; 309 310 311 /** 312 * The second prime factor of the private RSA key. 313 */ 314 private Base64URL q; 315 316 317 /** 318 * The first factor Chinese Remainder Theorem exponent of the 319 * private RSA key. 320 */ 321 private Base64URL dp; 322 323 324 /** 325 * The second factor Chinese Remainder Theorem exponent of the 326 * private RSA key. 327 */ 328 private Base64URL dq; 329 330 331 /** 332 * The first Chinese Remainder Theorem coefficient of the private RSA 333 * key. 334 */ 335 private Base64URL qi; 336 337 338 /** 339 * The other primes information of the private RSA key, should 340 * they exist. When only two primes have been used (the normal 341 * case), this parameter MUST be omitted. When three or more 342 * primes have been used, the number of array elements MUST be 343 * the number of primes used minus two. 344 */ 345 private List<OtherPrimesInfo> oth; 346 347 348 /** 349 * The key use, optional. 350 */ 351 private KeyUse use; 352 353 354 /** 355 * The key operations, optional. 356 */ 357 private Set<KeyOperation> ops; 358 359 360 /** 361 * The intended JOSE algorithm for the key, optional. 362 */ 363 private Algorithm alg; 364 365 366 /** 367 * The key ID, optional. 368 */ 369 private String kid; 370 371 372 /** 373 * X.509 certificate URL, optional. 374 */ 375 private URI x5u; 376 377 378 /** 379 * X.509 certificate thumbprint, optional. 380 */ 381 private Base64URL x5t; 382 383 384 /** 385 * The X.509 certificate chain, optional. 386 */ 387 private List<Base64> x5c; 388 389 390 /** 391 * Creates a new RSA JWK builder. 392 * 393 * @param n The the modulus value for the public RSA key. It is 394 * represented as the Base64URL encoding of value's 395 * big endian representation. Must not be 396 * {@code null}. 397 * @param e The exponent value for the public RSA key. It is 398 * represented as the Base64URL encoding of value's 399 * big endian representation. Must not be 400 * {@code null}. 401 */ 402 public Builder(final Base64URL n, final Base64URL e) { 403 404 // Ensure the public params are defined 405 406 if (n == null) { 407 throw new IllegalArgumentException("The modulus value must not be null"); 408 } 409 410 this.n = n; 411 412 413 if (e == null) { 414 throw new IllegalArgumentException("The public exponent value must not be null"); 415 } 416 417 this.e = e; 418 } 419 420 421 /** 422 * Creates a new RSA JWK builder. 423 * 424 * @param pub The public RSA key to represent. Must not be 425 * {@code null}. 426 */ 427 public Builder(final RSAPublicKey pub) { 428 429 n = Base64URL.encode(pub.getModulus()); 430 e = Base64URL.encode(pub.getPublicExponent()); 431 } 432 433 434 /** 435 * Sets the private exponent ({@code d}) of the RSA key. 436 * 437 * @param d The private RSA key exponent. It is represented as 438 * the Base64URL encoding of the value's big endian 439 * representation. {@code null} if not specified (for 440 * a public key or a private key using the second 441 * representation only). 442 * 443 * @return This builder. 444 */ 445 public Builder privateExponent(final Base64URL d) { 446 447 this.d = d; 448 return this; 449 } 450 451 452 /** 453 * Sets the private RSA key, using the first representation. 454 * 455 * @param priv The private RSA key, used to obtain the private 456 * exponent ({@code d}). Must not be {@code null}. 457 * 458 * @return This builder. 459 */ 460 public Builder privateKey(final RSAPrivateKey priv) { 461 462 if (priv instanceof RSAPrivateCrtKey) { 463 return this.privateKey((RSAPrivateCrtKey) priv); 464 } else if (priv instanceof RSAMultiPrimePrivateCrtKey) { 465 return this.privateKey((RSAMultiPrimePrivateCrtKey) priv); 466 } else { 467 this.d = Base64URL.encode(priv.getPrivateExponent()); 468 return this; 469 } 470 } 471 472 473 /** 474 * Sets the first prime factor ({@code p}) of the private RSA 475 * key. 476 * 477 * @param p The RSA first prime factor. It is represented as 478 * the Base64URL encoding of the value's big endian 479 * representation. {@code null} if not specified (for 480 * a public key or a private key using the first 481 * representation only). 482 * 483 * @return This builder. 484 */ 485 public Builder firstPrimeFactor(final Base64URL p) { 486 487 this.p = p; 488 return this; 489 } 490 491 492 /** 493 * Sets the second prime factor ({@code q}) of the private RSA 494 * key. 495 * 496 * @param q The RSA second prime factor. It is represented as 497 * the Base64URL encoding of the value's big endian 498 * representation. {@code null} if not specified (for 499 * a public key or a private key using the first 500 * representation only). 501 * 502 * @return This builder. 503 */ 504 public Builder secondPrimeFactor(final Base64URL q) { 505 506 this.q = q; 507 return this; 508 } 509 510 511 /** 512 * Sets the first factor Chinese Remainder Theorem (CRT) 513 * exponent ({@code dp}) of the private RSA key. 514 * 515 * @param dp The RSA first factor CRT exponent. It is 516 * represented as the Base64URL encoding of the 517 * value's big endian representation. {@code null} 518 * if not specified (for a public key or a private 519 * key using the first representation only). 520 * 521 * @return This builder. 522 */ 523 public Builder firstFactorCRTExponent(final Base64URL dp) { 524 525 this.dp = dp; 526 return this; 527 } 528 529 530 /** 531 * Sets the second factor Chinese Remainder Theorem (CRT) 532 * exponent ({@code dq}) of the private RSA key. 533 * 534 * @param dq The RSA second factor CRT exponent. It is 535 * represented as the Base64URL encoding of the 536 * value's big endian representation. {@code null} if 537 * not specified (for a public key or a private key 538 * using the first representation only). 539 * 540 * @return This builder. 541 */ 542 public Builder secondFactorCRTExponent(final Base64URL dq) { 543 544 this.dq = dq; 545 return this; 546 } 547 548 549 /** 550 * Sets the first Chinese Remainder Theorem (CRT) coefficient 551 * ({@code qi})} of the private RSA key. 552 * 553 * @param qi The RSA first CRT coefficient. It is represented 554 * as the Base64URL encoding of the value's big 555 * endian representation. {@code null} if not 556 * specified (for a public key or a private key using 557 * the first representation only). 558 * 559 * @return This builder. 560 */ 561 public Builder firstCRTCoefficient(final Base64URL qi) { 562 563 this.qi = qi; 564 return this; 565 } 566 567 568 /** 569 * Sets the other primes information ({@code oth}) for the 570 * private RSA key, should they exist. 571 * 572 * @param oth The RSA other primes information, {@code null} or 573 * empty list if not specified. 574 * 575 * @return This builder. 576 */ 577 public Builder otherPrimes(final List<OtherPrimesInfo> oth) { 578 579 this.oth = oth; 580 return this; 581 } 582 583 584 /** 585 * Sets the private RSA key, using the second representation 586 * (see RFC 3447, section 3.2). 587 * 588 * @param priv The private RSA key, used to obtain the private 589 * exponent ({@code d}), the first prime factor 590 * ({@code p}), the second prime factor 591 * ({@code q}), the first factor CRT exponent 592 * ({@code dp}), the second factor CRT exponent 593 * ({@code dq}) and the first CRT coefficient 594 * ({@code qi}). Must not be {@code null}. 595 * 596 * @return This builder. 597 */ 598 public Builder privateKey(final RSAPrivateCrtKey priv) { 599 600 d = Base64URL.encode(priv.getPrivateExponent()); 601 p = Base64URL.encode(priv.getPrimeP()); 602 q = Base64URL.encode(priv.getPrimeQ()); 603 dp = Base64URL.encode(priv.getPrimeExponentP()); 604 dq = Base64URL.encode(priv.getPrimeExponentQ()); 605 qi = Base64URL.encode(priv.getCrtCoefficient()); 606 607 return this; 608 } 609 610 611 /** 612 * Sets the private RSA key, using the second representation, 613 * with optional other primes info (see RFC 3447, section 3.2). 614 * 615 * @param priv The private RSA key, used to obtain the private 616 * exponent ({@code d}), the first prime factor 617 * ({@code p}), the second prime factor 618 * ({@code q}), the first factor CRT exponent 619 * ({@code dp}), the second factor CRT exponent 620 * ({@code dq}), the first CRT coefficient 621 * ({@code qi}) and the other primes info 622 * ({@code oth}). Must not be {@code null}. 623 * 624 * @return This builder. 625 */ 626 public Builder privateKey(final RSAMultiPrimePrivateCrtKey priv) { 627 628 d = Base64URL.encode(priv.getPrivateExponent()); 629 p = Base64URL.encode(priv.getPrimeP()); 630 q = Base64URL.encode(priv.getPrimeQ()); 631 dp = Base64URL.encode(priv.getPrimeExponentP()); 632 dq = Base64URL.encode(priv.getPrimeExponentQ()); 633 qi = Base64URL.encode(priv.getCrtCoefficient()); 634 oth = OtherPrimesInfo.toList(priv.getOtherPrimeInfo()); 635 636 return this; 637 } 638 639 640 /** 641 * Sets the use ({@code use}) of the JWK. 642 * 643 * @param use The key use, {@code null} if not specified or if 644 * the key is intended for signing as well as 645 * encryption. 646 * 647 * @return This builder. 648 */ 649 public Builder keyUse(final KeyUse use) { 650 651 this.use = use; 652 return this; 653 } 654 655 656 /** 657 * Sets the operations ({@code key_ops}) of the JWK (for a 658 * non-public key). 659 * 660 * @param ops The key operations, {@code null} if not 661 * specified. 662 * 663 * @return This builder. 664 */ 665 public Builder keyOperations(final Set<KeyOperation> ops) { 666 667 this.ops = ops; 668 return this; 669 } 670 671 672 /** 673 * Sets the intended JOSE algorithm ({@code alg}) for the JWK. 674 * 675 * @param alg The intended JOSE algorithm, {@code null} if not 676 * specified. 677 * 678 * @return This builder. 679 */ 680 public Builder algorithm(final Algorithm alg) { 681 682 this.alg = alg; 683 return this; 684 } 685 686 /** 687 * Sets the ID ({@code kid}) of the JWK. The key ID can be used 688 * to match a specific key. This can be used, for instance, to 689 * choose a key within a {@link JWKSet} during key rollover. 690 * The key ID may also correspond to a JWS/JWE {@code kid} 691 * header parameter value. 692 * 693 * @param kid The key ID, {@code null} if not specified. 694 * 695 * @return This builder. 696 */ 697 public Builder keyID(final String kid) { 698 699 this.kid = kid; 700 return this; 701 } 702 703 704 /** 705 * Sets the X.509 certificate URL ({@code x5u}) of the JWK. 706 * 707 * @param x5u The X.509 certificate URL, {@code null} if not 708 * specified. 709 * 710 * @return This builder. 711 */ 712 public Builder x509CertURL(final URI x5u) { 713 714 this.x5u = x5u; 715 return this; 716 } 717 718 719 /** 720 * Sets the X.509 certificate thumbprint ({@code x5t}) of the 721 * JWK. 722 * 723 * @param x5t The X.509 certificate thumbprint, {@code null} if 724 * not specified. 725 * 726 * @return This builder. 727 */ 728 public Builder x509CertThumbprint(final Base64URL x5t) { 729 730 this.x5t = x5t; 731 return this; 732 } 733 734 /** 735 * Sets the X.509 certificate chain ({@code x5c}) of the JWK. 736 * 737 * @param x5c The X.509 certificate chain as a unmodifiable 738 * list, {@code null} if not specified. 739 * 740 * @return This builder. 741 */ 742 public Builder x509CertChain(final List<Base64> x5c) { 743 744 this.x5c = x5c; 745 return this; 746 } 747 748 /** 749 * Builds a new RSA JWK. 750 * 751 * @return The RSA JWK. 752 * 753 * @throws IllegalStateException If the JWK parameters were 754 * inconsistently specified. 755 */ 756 public RSAKey build() { 757 758 try { 759 // The full constructor 760 return new RSAKey(n, e, d, p, q, dp, dq, qi, oth, 761 use, ops, alg, kid, x5u, x5t, x5c); 762 763 } catch (IllegalArgumentException e) { 764 765 throw new IllegalStateException(e.getMessage(), e); 766 } 767 } 768 } 769 770 771 // Public RSA params 772 773 /** 774 * The modulus value of the RSA key. 775 */ 776 private final Base64URL n; 777 778 779 /** 780 * The public exponent of the RSA key. 781 */ 782 private final Base64URL e; 783 784 785 // Private RSA params, 1st representation 786 787 /** 788 * The private exponent of the RSA key. 789 */ 790 private final Base64URL d; 791 792 793 // Private RSA params, 2nd representation 794 795 /** 796 * The first prime factor of the private RSA key. 797 */ 798 private final Base64URL p; 799 800 801 /** 802 * The second prime factor of the private RSA key. 803 */ 804 private final Base64URL q; 805 806 807 /** 808 * The first factor Chinese Remainder Theorem exponent of the private 809 * RSA key. 810 */ 811 private final Base64URL dp; 812 813 814 /** 815 * The second factor Chinese Remainder Theorem exponent of the private 816 * RSA key. 817 */ 818 private final Base64URL dq; 819 820 821 /** 822 * The first Chinese Remainder Theorem coefficient of the private RSA 823 * key. 824 */ 825 private final Base64URL qi; 826 827 828 /** 829 * The other primes information of the private RSA key, should they 830 * exist. When only two primes have been used (the normal case), this 831 * parameter MUST be omitted. When three or more primes have been used, 832 * the number of array elements MUST be the number of primes used minus 833 * two. 834 */ 835 private final List<OtherPrimesInfo> oth; 836 837 838 /** 839 * Creates a new public RSA JSON Web Key (JWK) with the specified 840 * parameters. 841 * 842 * @param n The the modulus value for the public RSA key. It is 843 * represented as the Base64URL encoding of value's big 844 * endian representation. Must not be {@code null}. 845 * @param e The exponent value for the public RSA key. It is 846 * represented as the Base64URL encoding of value's big 847 * endian representation. Must not be {@code null}. 848 * @param use The key use, {@code null} if not specified or if the key 849 * is intended for signing as well as encryption. 850 * @param ops The key operations, {@code null} if not specified. 851 * @param alg The intended JOSE algorithm for the key, {@code null} if 852 * not specified. 853 * @param kid The key ID. {@code null} if not specified. 854 * @param x5u The X.509 certificate URL, {@code null} if not specified. 855 * @param x5t The X.509 certificate thumbprint, {@code null} if not 856 * specified. 857 * @param x5c The X.509 certificate chain, {@code null} if not 858 * specified. 859 */ 860 public RSAKey(final Base64URL n, final Base64URL e, 861 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 862 final URI x5u, final Base64URL x5t, final List<Base64> x5c) { 863 864 // Call the full constructor, all private key parameters are null 865 this(n, e, null, null, null, null, null, null, null, use, ops, alg, kid, 866 x5u, x5t, x5c); 867 } 868 869 870 /** 871 * Creates a new public / private RSA JSON Web Key (JWK) with the 872 * specified parameters. The private RSA key is specified by its first 873 * representation (see RFC 3447, section 3.2). 874 * 875 * @param n The the modulus value for the public RSA key. It is 876 * represented as the Base64URL encoding of value's big 877 * endian representation. Must not be {@code null}. 878 * @param e The exponent value for the public RSA key. It is 879 * represented as the Base64URL encoding of value's big 880 * endian representation. Must not be {@code null}. 881 * @param d The private exponent. It is represented as the Base64URL 882 * encoding of the value's big endian representation. Must 883 * not be {@code null}. 884 * @param use The key use, {@code null} if not specified or if the key 885 * is intended for signing as well as encryption. 886 * @param ops The key operations, {@code null} if not specified. 887 * @param alg The intended JOSE algorithm for the key, {@code null} if 888 * not specified. 889 * @param kid The key ID. {@code null} if not specified. 890 * @param x5u The X.509 certificate URL, {@code null} if not specified. 891 * @param x5t The X.509 certificate thumbprint, {@code null} if not 892 * specified. 893 * @param x5c The X.509 certificate chain, {@code null} if not 894 * specified. 895 */ 896 public RSAKey(final Base64URL n, final Base64URL e, final Base64URL d, 897 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 898 final URI x5u, final Base64URL x5t, final List<Base64> x5c) { 899 900 // Call the full constructor, the second private representation 901 // parameters are all null 902 this(n, e, d, null, null, null, null, null, null, use, ops, alg, kid, 903 x5u, x5t, x5c); 904 905 if (d == null) { 906 throw new IllegalArgumentException("The private exponent must not be null"); 907 } 908 } 909 910 911 /** 912 * Creates a new public / private RSA JSON Web Key (JWK) with the 913 * specified parameters. The private RSA key is specified by its 914 * second representation (see RFC 3447, section 3.2). 915 * 916 * @param n The the modulus value for the public RSA key. It is 917 * represented as the Base64URL encoding of value's big 918 * endian representation. Must not be {@code null}. 919 * @param e The exponent value for the public RSA key. It is 920 * represented as the Base64URL encoding of value's big 921 * endian representation. Must not be {@code null}. 922 * @param p The first prime factor. It is represented as the 923 * Base64URL encoding of the value's big endian 924 * representation. Must not be {@code null}. 925 * @param q The second prime factor. It is represented as the 926 * Base64URL encoding of the value's big endian 927 * representation. Must not be {@code null}. 928 * @param dp The first factor Chinese Remainder Theorem exponent. It 929 * is represented as the Base64URL encoding of the value's 930 * big endian representation. Must not be {@code null}. 931 * @param dq The second factor Chinese Remainder Theorem exponent. It 932 * is represented as the Base64URL encoding of the value's 933 * big endian representation. Must not be {@code null}. 934 * @param qi The first Chinese Remainder Theorem coefficient. It is 935 * represented as the Base64URL encoding of the value's big 936 * endian representation. Must not be {@code null}. 937 * @param oth The other primes information, should they exist, 938 * {@code null} or an empty list if not specified. 939 * @param use The key use, {@code null} if not specified or if the key 940 * is intended for signing as well as encryption. 941 * @param ops The key operations, {@code null} if not specified. 942 * @param alg The intended JOSE algorithm for the key, {@code null} if 943 * not specified. 944 * @param kid The key ID. {@code null} if not specified. 945 * @param x5u The X.509 certificate URL, {@code null} if not specified. 946 * @param x5t The X.509 certificate thumbprint, {@code null} if not 947 * specified. 948 * @param x5c The X.509 certificate chain, {@code null} if not 949 * specified. 950 */ 951 public RSAKey(final Base64URL n, final Base64URL e, 952 final Base64URL p, final Base64URL q, 953 final Base64URL dp, final Base64URL dq, final Base64URL qi, 954 final List<OtherPrimesInfo> oth, 955 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 956 final URI x5u, final Base64URL x5t, final List<Base64> x5c) { 957 958 // Call the full constructor, the first private representation 959 // d param is null 960 this(n, e, null, p, q, dp, dq, qi, oth, use, ops, alg, kid, 961 x5u, x5t, x5c); 962 963 if (p == null) { 964 throw new IllegalArgumentException("The first prime factor must not be null"); 965 } 966 967 if (q == null) { 968 throw new IllegalArgumentException("The second prime factor must not be null"); 969 } 970 971 if (dp == null) { 972 throw new IllegalArgumentException("The first factor CRT exponent must not be null"); 973 } 974 975 if (dq == null) { 976 throw new IllegalArgumentException("The second factor CRT exponent must not be null"); 977 } 978 979 if (qi == null) { 980 throw new IllegalArgumentException("The first CRT coefficient must not be null"); 981 } 982 } 983 984 985 /** 986 * Creates a new public / private RSA JSON Web Key (JWK) with the 987 * specified parameters. The private RSA key is specified by both its 988 * first and second representations (see RFC 3447, section 3.2). 989 * 990 * <p>A valid first private RSA key representation must specify the 991 * {@code d} parameter. 992 * 993 * <p>A valid second private RSA key representation must specify all 994 * required Chinese Remained Theorem (CRT) parameters - {@code p}, 995 * {@code q}, {@code dp}, {@code dq} and {@code qi}, else an 996 * {@link java.lang.IllegalArgumentException} will be thrown. 997 * 998 * @param n The the modulus value for the public RSA key. It is 999 * represented as the Base64URL encoding of value's big 1000 * endian representation. Must not be {@code null}. 1001 * @param e The exponent value for the public RSA key. It is 1002 * represented as the Base64URL encoding of value's big 1003 * endian representation. Must not be {@code null}. 1004 * @param d The private exponent. It is represented as the Base64URL 1005 * encoding of the value's big endian representation. May 1006 * be {@code null}. 1007 * @param p The first prime factor. It is represented as the 1008 * Base64URL encoding of the value's big endian 1009 * representation. May be {@code null}. 1010 * @param q The second prime factor. It is represented as the 1011 * Base64URL encoding of the value's big endian 1012 * representation. May be {@code null}. 1013 * @param dp The first factor Chinese Remainder Theorem exponent. It 1014 * is represented as the Base64URL encoding of the value's 1015 * big endian representation. May be {@code null}. 1016 * @param dq The second factor Chinese Remainder Theorem exponent. It 1017 * is represented as the Base64URL encoding of the value's 1018 * big endian representation. May be {@code null}. 1019 * @param qi The first Chinese Remainder Theorem coefficient. It is 1020 * represented as the Base64URL encoding of the value's big 1021 * endian representation. May be {@code null}. 1022 * @param oth The other primes information, should they exist, 1023 * {@code null} or an empty list if not specified. 1024 * @param use The key use, {@code null} if not specified or if the key 1025 * is intended for signing as well as encryption. 1026 * @param ops The key operations, {@code null} if not specified. 1027 * @param alg The intended JOSE algorithm for the key, {@code null} if 1028 * not specified. 1029 * @param kid The key ID. {@code null} if not specified. 1030 * @param x5u The X.509 certificate URL, {@code null} if not specified. 1031 * @param x5t The X.509 certificate thumbprint, {@code null} if not 1032 * specified. 1033 * @param x5c The X.509 certificate chain, {@code null} if not 1034 * specified. 1035 */ 1036 public RSAKey(final Base64URL n, final Base64URL e, 1037 final Base64URL d, 1038 final Base64URL p, final Base64URL q, 1039 final Base64URL dp, final Base64URL dq, final Base64URL qi, 1040 final List<OtherPrimesInfo> oth, 1041 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1042 final URI x5u, final Base64URL x5t, final List<Base64> x5c) { 1043 1044 super(KeyType.RSA, use, ops, alg, kid, x5u, x5t, x5c); 1045 1046 1047 // Ensure the public params are defined 1048 1049 if (n == null) { 1050 throw new IllegalArgumentException("The modulus value must not be null"); 1051 } 1052 1053 this.n = n; 1054 1055 1056 if (e == null) { 1057 throw new IllegalArgumentException("The public exponent value must not be null"); 1058 } 1059 1060 this.e = e; 1061 1062 1063 // Private params, 1st representation 1064 1065 this.d = d; 1066 1067 1068 // Private params, 2nd representation, check for consistency 1069 1070 if (p != null && q != null && dp != null && dq != null && qi != null) { 1071 1072 // CRT params fully specified 1073 this.p = p; 1074 this.q = q; 1075 this.dp = dp; 1076 this.dq = dq; 1077 this.qi = qi; 1078 1079 // Other RSA primes info optional, default to empty list 1080 if (oth != null) { 1081 this.oth = Collections.unmodifiableList(oth); 1082 } else { 1083 this.oth = Collections.emptyList(); 1084 } 1085 1086 } else if (p == null && q == null && dp == null && dq == null && qi == null && oth == null) { 1087 1088 // No CRT params 1089 this.p = null; 1090 this.q = null; 1091 this.dp = null; 1092 this.dq = null; 1093 this.qi = null; 1094 1095 this.oth = Collections.emptyList(); 1096 1097 } else { 1098 1099 if (p == null) { 1100 throw new IllegalArgumentException("Incomplete second private (CRT) representation: The first prime factor must not be null"); 1101 } else if (q == null) { 1102 throw new IllegalArgumentException("Incomplete second private (CRT) representation: The second prime factor must not be null"); 1103 } else if (dp == null) { 1104 throw new IllegalArgumentException("Incomplete second private (CRT) representation: The first factor CRT exponent must not be null"); 1105 } else if (dq == null) { 1106 throw new IllegalArgumentException("Incomplete second private (CRT) representation: The second factor CRT exponent must not be null"); 1107 } else { // qi == null 1108 throw new IllegalArgumentException("Incomplete second private (CRT) representation: The first CRT coefficient must not be null"); 1109 } 1110 } 1111 } 1112 1113 1114 /** 1115 * Creates a new public RSA JSON Web Key (JWK) with the specified 1116 * parameters. 1117 * 1118 * @param pub The public RSA key to represent. Must not be 1119 * {@code null}. 1120 * @param use The key use, {@code null} if not specified or if the key 1121 * is intended for signing as well as encryption. 1122 * @param ops The key operations, {@code null} if not specified. 1123 * @param alg The intended JOSE algorithm for the key, {@code null} if 1124 * not specified. 1125 * @param kid The key ID. {@code null} if not specified. 1126 * @param x5u The X.509 certificate URL, {@code null} if not specified. 1127 * @param x5t The X.509 certificate thumbprint, {@code null} if not 1128 * specified. 1129 * @param x5c The X.509 certificate chain, {@code null} if not 1130 * specified. 1131 */ 1132 public RSAKey(final RSAPublicKey pub, 1133 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1134 final URI x5u, final Base64URL x5t, final List<Base64> x5c) { 1135 1136 this(Base64URL.encode(pub.getModulus()), 1137 Base64URL.encode(pub.getPublicExponent()), 1138 use, ops, alg, kid, 1139 x5u, x5t, x5c); 1140 } 1141 1142 1143 /** 1144 * Creates a new public / private RSA JSON Web Key (JWK) with the 1145 * specified parameters. The private RSA key is specified by its first 1146 * representation (see RFC 3447, section 3.2). 1147 * 1148 * @param pub The public RSA key to represent. Must not be 1149 * {@code null}. 1150 * @param priv The private RSA key to represent. Must not be 1151 * {@code null}. 1152 * @param use The key use, {@code null} if not specified or if the key 1153 * is intended for signing as well as encryption. 1154 * @param ops The key operations, {@code null} if not specified. 1155 * @param alg The intended JOSE algorithm for the key, {@code null} if 1156 * not specified. 1157 * @param kid The key ID. {@code null} if not specified. 1158 * @param x5u The X.509 certificate URL, {@code null} if not 1159 * specified. 1160 * @param x5t The X.509 certificate thumbprint, {@code null} if not 1161 * specified. 1162 * @param x5c The X.509 certificate chain, {@code null} if not 1163 * specified. 1164 */ 1165 public RSAKey(final RSAPublicKey pub, final RSAPrivateKey priv, 1166 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1167 final URI x5u, final Base64URL x5t, final List<Base64> x5c) { 1168 1169 this(Base64URL.encode(pub.getModulus()), 1170 Base64URL.encode(pub.getPublicExponent()), 1171 Base64URL.encode(priv.getPrivateExponent()), 1172 use, ops, alg, kid, 1173 x5u, x5t, x5c); 1174 } 1175 1176 1177 /** 1178 * Creates a new public / private RSA JSON Web Key (JWK) with the 1179 * specified parameters. The private RSA key is specified by its second 1180 * representation (see RFC 3447, section 3.2). 1181 * 1182 * @param pub The public RSA key to represent. Must not be 1183 * {@code null}. 1184 * @param priv The private RSA key to represent. Must not be 1185 * {@code null}. 1186 * @param use The key use, {@code null} if not specified or if the key 1187 * is intended for signing as well as encryption. 1188 * @param ops The key operations, {@code null} if not specified. 1189 * @param alg The intended JOSE algorithm for the key, {@code null} if 1190 * not specified. 1191 * @param kid The key ID. {@code null} if not specified. 1192 * @param x5u The X.509 certificate URL, {@code null} if not 1193 * specified. 1194 * @param x5t The X.509 certificate thumbprint, {@code null} if not 1195 * specified. 1196 * @param x5c The X.509 certificate chain, {@code null} if not 1197 * specified. 1198 */ 1199 public RSAKey(final RSAPublicKey pub, final RSAPrivateCrtKey priv, 1200 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1201 final URI x5u, final Base64URL x5t, final List<Base64> x5c) { 1202 1203 this(Base64URL.encode(pub.getModulus()), 1204 Base64URL.encode(pub.getPublicExponent()), 1205 Base64URL.encode(priv.getPrivateExponent()), 1206 Base64URL.encode(priv.getPrimeP()), 1207 Base64URL.encode(priv.getPrimeQ()), 1208 Base64URL.encode(priv.getPrimeExponentP()), 1209 Base64URL.encode(priv.getPrimeExponentQ()), 1210 Base64URL.encode(priv.getCrtCoefficient()), 1211 null, 1212 use, ops, alg, kid, 1213 x5u, x5t, x5c); 1214 } 1215 1216 1217 /** 1218 * Creates a new public / private RSA JSON Web Key (JWK) with the 1219 * specified parameters. The private RSA key is specified by its second 1220 * representation, with optional other primes info (see RFC 3447, 1221 * section 3.2). 1222 * 1223 * @param pub The public RSA key to represent. Must not be 1224 * {@code null}. 1225 * @param priv The private RSA key to represent. Must not be 1226 * {@code null}. 1227 * @param use The key use, {@code null} if not specified or if the key 1228 * is intended for signing as well as encryption. 1229 * @param ops The key operations, {@code null} if not specified. 1230 * @param alg The intended JOSE algorithm for the key, {@code null} if 1231 * not specified. 1232 * @param kid The key ID. {@code null} if not specified. 1233 * @param x5u The X.509 certificate URL, {@code null} if not 1234 * specified. 1235 * @param x5t The X.509 certificate thumbprint, {@code null} if not 1236 * specified. 1237 * @param x5c The X.509 certificate chain, {@code null} if not 1238 * specified. 1239 */ 1240 public RSAKey(final RSAPublicKey pub, final RSAMultiPrimePrivateCrtKey priv, 1241 final KeyUse use, final Set<KeyOperation> ops, final Algorithm alg, final String kid, 1242 final URI x5u, final Base64URL x5t, final List<Base64> x5c) { 1243 1244 this(Base64URL.encode(pub.getModulus()), 1245 Base64URL.encode(pub.getPublicExponent()), 1246 Base64URL.encode(priv.getPrivateExponent()), 1247 Base64URL.encode(priv.getPrimeP()), 1248 Base64URL.encode(priv.getPrimeQ()), 1249 Base64URL.encode(priv.getPrimeExponentP()), 1250 Base64URL.encode(priv.getPrimeExponentQ()), 1251 Base64URL.encode(priv.getCrtCoefficient()), 1252 OtherPrimesInfo.toList(priv.getOtherPrimeInfo()), 1253 use, ops, alg, kid, 1254 x5u, x5t, x5c); 1255 } 1256 1257 1258 /** 1259 * Gets the modulus value ({@code n}) of the RSA key. 1260 * 1261 * @return The RSA key modulus. It is represented as the Base64URL 1262 * encoding of the value's big endian representation. 1263 */ 1264 public Base64URL getModulus() { 1265 1266 return n; 1267 } 1268 1269 1270 /** 1271 * Gets the public exponent ({@code e}) of the RSA key. 1272 * 1273 * @return The public RSA key exponent. It is represented as the 1274 * Base64URL encoding of the value's big endian representation. 1275 */ 1276 public Base64URL getPublicExponent() { 1277 1278 return e; 1279 } 1280 1281 1282 /** 1283 * Gets the private exponent ({@code d}) of the RSA key. 1284 * 1285 * @return The private RSA key exponent. It is represented as the 1286 * Base64URL encoding of the value's big endian representation. 1287 * {@code null} if not specified (for a public key or a private 1288 * key using the second representation only). 1289 */ 1290 public Base64URL getPrivateExponent() { 1291 1292 return d; 1293 } 1294 1295 1296 /** 1297 * Gets the first prime factor ({@code p}) of the private RSA key. 1298 * 1299 * @return The RSA first prime factor. It is represented as the 1300 * Base64URL encoding of the value's big endian representation. 1301 * {@code null} if not specified (for a public key or a private 1302 * key using the first representation only). 1303 */ 1304 public Base64URL getFirstPrimeFactor() { 1305 1306 return p; 1307 } 1308 1309 1310 /** 1311 * Gets the second prime factor ({@code q}) of the private RSA key. 1312 * 1313 * @return The RSA second prime factor. It is represented as the 1314 * Base64URL encoding of the value's big endian representation. 1315 * {@code null} if not specified (for a public key or a private 1316 * key using the first representation only). 1317 */ 1318 public Base64URL getSecondPrimeFactor() { 1319 1320 return q; 1321 } 1322 1323 1324 /** 1325 * Gets the first factor Chinese Remainder Theorem (CRT) exponent 1326 * ({@code dp}) of the private RSA key. 1327 * 1328 * @return The RSA first factor CRT exponent. It is represented as the 1329 * Base64URL encoding of the value's big endian representation. 1330 * {@code null} if not specified (for a public key or a private 1331 * key using the first representation only). 1332 */ 1333 public Base64URL getFirstFactorCRTExponent() { 1334 1335 return dp; 1336 } 1337 1338 1339 /** 1340 * Gets the second factor Chinese Remainder Theorem (CRT) exponent 1341 * ({@code dq}) of the private RSA key. 1342 * 1343 * @return The RSA second factor CRT exponent. It is represented as the 1344 * Base64URL encoding of the value's big endian representation. 1345 * {@code null} if not specified (for a public key or a private 1346 * key using the first representation only). 1347 */ 1348 public Base64URL getSecondFactorCRTExponent() { 1349 1350 return dq; 1351 } 1352 1353 1354 /** 1355 * Gets the first Chinese Remainder Theorem (CRT) coefficient 1356 * ({@code qi})} of the private RSA key. 1357 * 1358 * @return The RSA first CRT coefficient. It is represented as the 1359 * Base64URL encoding of the value's big endian representation. 1360 * {@code null} if not specified (for a public key or a private 1361 * key using the first representation only). 1362 */ 1363 public Base64URL getFirstCRTCoefficient() { 1364 1365 return qi; 1366 } 1367 1368 1369 /** 1370 * Gets the other primes information ({@code oth}) for the private RSA 1371 * key, should they exist. 1372 * 1373 * @return The RSA other primes information, {@code null} or empty list 1374 * if not specified. 1375 */ 1376 public List<OtherPrimesInfo> getOtherPrimes() { 1377 1378 return oth; 1379 } 1380 1381 1382 /** 1383 * Returns a standard {@code java.security.interfaces.RSAPublicKey} 1384 * representation of this RSA JWK. 1385 * 1386 * @return The public RSA key. 1387 * 1388 * @throws JOSEException If RSA is not supported by the underlying Java 1389 * Cryptography (JCA) provider or if the JWK 1390 * parameters are invalid for a public RSA key. 1391 */ 1392 public RSAPublicKey toRSAPublicKey() 1393 throws JOSEException { 1394 1395 BigInteger modulus = n.decodeToBigInteger(); 1396 BigInteger exponent = e.decodeToBigInteger(); 1397 1398 RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent); 1399 1400 try { 1401 KeyFactory factory = KeyFactory.getInstance("RSA"); 1402 1403 return (RSAPublicKey) factory.generatePublic(spec); 1404 1405 } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { 1406 1407 throw new JOSEException(e.getMessage(), e); 1408 } 1409 } 1410 1411 1412 /** 1413 * Returns a standard {@code java.security.interfaces.RSAPrivateKey} 1414 * representation of this RSA JWK. 1415 * 1416 * @return The private RSA key, {@code null} if not specified by this 1417 * JWK. 1418 * 1419 * @throws JOSEException If RSA is not supported by the underlying Java 1420 * Cryptography (JCA) provider or if the JWK 1421 * parameters are invalid for a private RSA key. 1422 */ 1423 public RSAPrivateKey toRSAPrivateKey() 1424 throws JOSEException { 1425 1426 if (d == null) { 1427 // no private key 1428 return null; 1429 } 1430 1431 BigInteger modulus = n.decodeToBigInteger(); 1432 BigInteger privateExponent = d.decodeToBigInteger(); 1433 1434 RSAPrivateKeySpec spec; 1435 1436 if (p == null) { 1437 // Use 1st representation 1438 spec = new RSAPrivateKeySpec(modulus, privateExponent); 1439 1440 } else { 1441 // Use 2nd (CRT) representation 1442 BigInteger publicExponent = e.decodeToBigInteger(); 1443 BigInteger primeP = p.decodeToBigInteger(); 1444 BigInteger primeQ = q.decodeToBigInteger(); 1445 BigInteger primeExponentP = dp.decodeToBigInteger(); 1446 BigInteger primeExponentQ = dq.decodeToBigInteger(); 1447 BigInteger crtCoefficient = qi.decodeToBigInteger(); 1448 1449 if (oth != null && ! oth.isEmpty()) { 1450 // Construct other info spec 1451 RSAOtherPrimeInfo[] otherInfo = new RSAOtherPrimeInfo[oth.size()]; 1452 1453 for (int i=0; i < oth.size(); i++) { 1454 1455 OtherPrimesInfo opi = oth.get(i); 1456 1457 BigInteger otherPrime = opi.getPrimeFactor().decodeToBigInteger(); 1458 BigInteger otherPrimeExponent = opi.getFactorCRTExponent().decodeToBigInteger(); 1459 BigInteger otherCrtCoefficient = opi.getFactorCRTCoefficient().decodeToBigInteger(); 1460 1461 otherInfo[i] = new RSAOtherPrimeInfo(otherPrime, 1462 otherPrimeExponent, 1463 otherCrtCoefficient); 1464 } 1465 1466 spec = new RSAMultiPrimePrivateCrtKeySpec(modulus, 1467 publicExponent, 1468 privateExponent, 1469 primeP, 1470 primeQ, 1471 primeExponentP, 1472 primeExponentQ, 1473 crtCoefficient, 1474 otherInfo); 1475 } else { 1476 // Construct spec with no other info 1477 spec = new RSAPrivateCrtKeySpec(modulus, 1478 publicExponent, 1479 privateExponent, 1480 primeP, 1481 primeQ, 1482 primeExponentP, 1483 primeExponentQ, 1484 crtCoefficient); 1485 } 1486 } 1487 1488 try { 1489 KeyFactory factory = KeyFactory.getInstance("RSA"); 1490 1491 return (RSAPrivateKey) factory.generatePrivate(spec); 1492 1493 } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { 1494 1495 throw new JOSEException(e.getMessage(), e); 1496 } 1497 } 1498 1499 1500 /** 1501 * Returns a standard {@code java.security.KeyPair} representation of 1502 * this RSA JWK. 1503 * 1504 * @return The RSA key pair. The private RSA key will be {@code null} 1505 * if not specified. 1506 * 1507 * @throws JOSEException If RSA is not supported by the underlying Java 1508 * Cryptography (JCA) provider or if the JWK 1509 * parameters are invalid for a public and / or 1510 * private RSA key. 1511 */ 1512 public KeyPair toKeyPair() 1513 throws JOSEException { 1514 1515 return new KeyPair(toRSAPublicKey(), toRSAPrivateKey()); 1516 } 1517 1518 1519 @Override 1520 public Base64URL computeThumbprint(final String hashAlg) 1521 throws JOSEException { 1522 1523 Map<String,String> o = new LinkedHashMap<>(); 1524 o.put("e", e.toString()); 1525 o.put("kty", getKeyType().getValue()); 1526 o.put("n", n.toString()); 1527 1528 MessageDigest md; 1529 1530 try { 1531 md = MessageDigest.getInstance(hashAlg); 1532 } catch (NoSuchAlgorithmException e) { 1533 throw new JOSEException("Unsupported hash algorithm: " + e.getMessage(), e); 1534 } 1535 1536 md.update(JSONObject.toJSONString(o).getBytes(Charset.forName("UTF-8"))); 1537 1538 return Base64URL.encode(md.digest()); 1539 } 1540 1541 1542 @Override 1543 public boolean isPrivate() { 1544 1545 // Check if 1st or 2nd form params are specified 1546 return d != null || p != null; 1547 } 1548 1549 1550 /** 1551 * Returns a copy of this RSA JWK with any private values removed. 1552 * 1553 * @return The copied public RSA JWK. 1554 */ 1555 @Override 1556 public RSAKey toPublicJWK() { 1557 1558 return new RSAKey(getModulus(), getPublicExponent(), 1559 getKeyUse(), getKeyOperations(), getAlgorithm(), getKeyID(), 1560 getX509CertURL(), getX509CertThumbprint(), getX509CertChain()); 1561 } 1562 1563 1564 @Override 1565 public JSONObject toJSONObject() { 1566 1567 JSONObject o = super.toJSONObject(); 1568 1569 // Append public RSA key specific attributes 1570 o.put("n", n.toString()); 1571 o.put("e", e.toString()); 1572 if (d != null) { 1573 o.put("d", d.toString()); 1574 } 1575 if (p != null) { 1576 o.put("p", p.toString()); 1577 } 1578 if (q != null) { 1579 o.put("q", q.toString()); 1580 } 1581 if (dp != null) { 1582 o.put("dp", dp.toString()); 1583 } 1584 if (dq != null) { 1585 o.put("dq", dq.toString()); 1586 } 1587 if (qi != null) { 1588 o.put("qi", qi.toString()); 1589 } 1590 if (oth != null && !oth.isEmpty()) { 1591 1592 JSONArray a = new JSONArray(); 1593 1594 for (OtherPrimesInfo other : oth) { 1595 1596 JSONObject oo = new JSONObject(); 1597 oo.put("r", other.r.toString()); 1598 oo.put("d", other.d.toString()); 1599 oo.put("t", other.t.toString()); 1600 1601 a.add(oo); 1602 } 1603 1604 o.put("oth", a); 1605 } 1606 1607 return o; 1608 } 1609 1610 1611 /** 1612 * Parses a public / private RSA Curve JWK from the specified JSON 1613 * object string representation. 1614 * 1615 * @param s The JSON object string to parse. Must not be {@code null}. 1616 * 1617 * @return The public / private RSA JWK. 1618 * 1619 * @throws ParseException If the string couldn't be parsed to an RSA 1620 * JWK. 1621 */ 1622 public static RSAKey parse(final String s) 1623 throws ParseException { 1624 1625 return parse(JSONObjectUtils.parseJSONObject(s)); 1626 } 1627 1628 1629 /** 1630 * Parses a public / private RSA JWK from the specified JSON object 1631 * representation. 1632 * 1633 * @param jsonObject The JSON object to parse. Must not be 1634 * @code null}. 1635 * 1636 * @return The public / private RSA Key. 1637 * 1638 * @throws ParseException If the JSON object couldn't be parsed to an 1639 * RSA JWK. 1640 */ 1641 public static RSAKey parse(final JSONObject jsonObject) 1642 throws ParseException { 1643 1644 // Parse the mandatory public key parameters first 1645 Base64URL n = new Base64URL(JSONObjectUtils.getString(jsonObject, "n")); 1646 Base64URL e = new Base64URL(JSONObjectUtils.getString(jsonObject, "e")); 1647 1648 // Check key type 1649 KeyType kty = KeyType.parse(JSONObjectUtils.getString(jsonObject, "kty")); 1650 if (kty != KeyType.RSA) { 1651 throw new ParseException("The key type \"kty\" must be RSA", 0); 1652 } 1653 1654 // Parse the optional private key parameters 1655 1656 // 1st private representation 1657 Base64URL d = null; 1658 if (jsonObject.containsKey("d")) { 1659 d = new Base64URL(JSONObjectUtils.getString(jsonObject, "d")); 1660 } 1661 1662 // 2nd private (CRT) representation 1663 Base64URL p = null; 1664 if (jsonObject.containsKey("p")) { 1665 p = new Base64URL(JSONObjectUtils.getString(jsonObject, "p")); 1666 } 1667 Base64URL q = null; 1668 if (jsonObject.containsKey("q")) { 1669 q = new Base64URL(JSONObjectUtils.getString(jsonObject, "q")); 1670 } 1671 Base64URL dp = null; 1672 if (jsonObject.containsKey("dp")) { 1673 dp = new Base64URL(JSONObjectUtils.getString(jsonObject, "dp")); 1674 } 1675 Base64URL dq= null; 1676 if (jsonObject.containsKey("dq")) { 1677 dq = new Base64URL(JSONObjectUtils.getString(jsonObject, "dq")); 1678 } 1679 Base64URL qi = null; 1680 if (jsonObject.containsKey("qi")) { 1681 qi = new Base64URL(JSONObjectUtils.getString(jsonObject, "qi")); 1682 } 1683 1684 List<OtherPrimesInfo> oth = null; 1685 if (jsonObject.containsKey("oth")) { 1686 1687 JSONArray arr = JSONObjectUtils.getJSONArray(jsonObject, "oth"); 1688 oth = new ArrayList<>(arr.size()); 1689 1690 for (Object o : arr) { 1691 1692 if (o instanceof JSONObject) { 1693 JSONObject otherJson = (JSONObject)o; 1694 1695 Base64URL r = new Base64URL(JSONObjectUtils.getString(otherJson, "r")); 1696 Base64URL odq = new Base64URL(JSONObjectUtils.getString(otherJson, "dq")); 1697 Base64URL t = new Base64URL(JSONObjectUtils.getString(otherJson, "t")); 1698 1699 OtherPrimesInfo prime = new OtherPrimesInfo(r, odq, t); 1700 oth.add(prime); 1701 } 1702 } 1703 } 1704 1705 try { 1706 return new RSAKey(n, e, d, p, q, dp, dq, qi, oth, 1707 JWKMetadata.parseKeyUse(jsonObject), 1708 JWKMetadata.parseKeyOperations(jsonObject), 1709 JWKMetadata.parseAlgorithm(jsonObject), 1710 JWKMetadata.parseKeyID(jsonObject), 1711 JWKMetadata.parseX509CertURL(jsonObject), 1712 JWKMetadata.parseX509CertThumbprint(jsonObject), 1713 JWKMetadata.parseX509CertChain(jsonObject)); 1714 1715 } catch (IllegalArgumentException ex) { 1716 1717 // Inconsistent 2nd spec, conflicting 'use' and 'key_ops' 1718 throw new ParseException(ex.getMessage(), 0); 1719 } 1720 } 1721}