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