001package com.nimbusds.jose.jwk;
002
003
004import java.math.BigInteger;
005import java.security.KeyFactory;
006import java.security.KeyPair;
007import java.security.NoSuchAlgorithmException;
008import java.security.interfaces.RSAMultiPrimePrivateCrtKey;
009import java.security.interfaces.RSAPrivateCrtKey;
010import java.security.interfaces.RSAPrivateKey;
011import java.security.interfaces.RSAPublicKey;
012import java.security.spec.InvalidKeySpecException;
013import java.security.spec.RSAMultiPrimePrivateCrtKeySpec;
014import java.security.spec.RSAOtherPrimeInfo;
015import java.security.spec.RSAPrivateCrtKeySpec;
016import java.security.spec.RSAPrivateKeySpec;
017import java.security.spec.RSAPublicKeySpec;
018import java.text.ParseException;
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.List;
022
023import net.jcip.annotations.Immutable;
024
025import net.minidev.json.JSONArray;
026import net.minidev.json.JSONObject;
027
028import com.nimbusds.jose.Algorithm;
029import com.nimbusds.jose.util.Base64URL;
030import com.nimbusds.jose.util.JSONObjectUtils;
031
032
033/**
034 * Public and private {@link KeyType#RSA RSA} JSON Web Key (JWK). This class is
035 * immutable.
036 *
037 * <p>Provides RSA JWK import from / export to the following standard Java 
038 * interfaces and classes:
039 *
040 * <ul>
041 *     <li>{@code java.security.interfaces.RSAPublicKey}
042 *     <li>{@code java.security.interfaces.RSAPrivateKey}
043 *         <ul>
044 *             <li>{@code java.security.interfaces.RSAPrivateCrtKey}
045 *             <li>{@code java.security.interfaces.RSAMultiPrimePrivateCrtKey}
046 *         </ul>
047 *     <li>{@code java.security.KeyPair}
048 * </ul>
049 *
050 * <p>Example JSON object representation of a public RSA JWK:
051 *
052 * <pre>
053 * { 
054 *   "kty" : "RSA",
055 *   "n"   : "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx
056 *            4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs
057 *            tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2
058 *            QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI
059 *            SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb
060 *            w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
061 *   "e"   : "AQAB",
062 *   "alg" : "RS256",
063 *   "kid" : "2011-04-29"
064 * }
065 * </pre>
066 *
067 * <p>Example JSON object representation of a public and private RSA JWK (with 
068 * both the first and the second private key representations):
069 *
070 * <pre>
071 * { 
072 *   "kty" : "RSA",
073 *   "n"   : "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx
074 *            4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs
075 *            tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2
076 *            QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI
077 *            SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb
078 *            w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
079 *   "e"   : "AQAB",
080 *   "d"   : "X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9
081 *            M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqij
082 *            wp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d
083 *            _cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBz
084 *            nbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFz
085 *            me1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q",
086 *   "p"   : "83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPV
087 *            nwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqV
088 *            WlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs",
089 *   "q"   : "3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyum
090 *            qjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgx
091 *            kIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk",
092 *   "dp"  : "G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oim
093 *            YwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_Nmtu
094 *            YZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0",
095 *   "dq"  : "s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUU
096 *            vMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9
097 *            GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk",
098 *   "qi"  : "GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzg
099 *            UIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rx
100 *            yR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU",
101 *   "alg" : "RS256",
102 *   "kid" : "2011-04-29"
103 * }
104 * </pre>
105 *
106 * <p>See RFC 3447.
107 *
108 * <p>See http://en.wikipedia.org/wiki/RSA_%28algorithm%29
109 *
110 * @author Vladimir Dzhuvinov
111 * @author Justin Richer
112 * @version $version$ (2013-03-27)
113 */
114@Immutable
115public final class RSAKey extends JWK {
116
117
118        /**
119         * Other Primes Info, represents the private {@code oth} parameter of a
120         * RSA JWK. This class is immutable.
121         *
122         * @author Justin Richer
123         */
124        @Immutable
125        public static class OtherPrimesInfo {
126
127
128                 /**
129                  * The prime factor.
130                  */
131                private final Base64URL r;
132
133                
134                /**
135                 * The factor Chinese Remainder Theorem (CRT) exponent.
136                 */
137                private final Base64URL d;
138        
139
140                /**
141                 * The factor Chinese Remainder Theorem (CRT) coefficient.
142                 */
143                private final Base64URL t;
144
145
146                /**
147                 * Creates a new JWK Other Primes Info with the specified 
148                 * parameters.
149                 *
150                 * @param r The prime factor. Must not be {@code null}.
151                 * @param d The factor Chinese Remainder Theorem (CRT) 
152                 *          exponent. Must not be {@code null}.
153                 * @param t The factor Chinese Remainder Theorem (CRT) 
154                 *          coefficient. Must not be {@code null}.
155                 */
156                public OtherPrimesInfo(final Base64URL r, final Base64URL d, final Base64URL t) {
157
158                        if (r == null) {
159
160                                throw new IllegalArgumentException("The prime factor must not be null");
161                        }
162
163                        this.r = r;
164
165                        if (d == null) {
166
167                                throw new IllegalArgumentException("The factor CRT exponent must not be null");
168                        }
169
170                        this.d = d;
171
172                        if (t == null) {
173
174                                throw new IllegalArgumentException("The factor CRT coefficient must not be null");
175                        }
176                        
177                        this.t = t;
178                }
179
180
181                /**
182                 * Creates a new JWK Other Primes Info from the specified
183                 * {@code java.security.spec.RSAOtherPrimeInfo} instance.
184                 *
185                 * @param oth The RSA Other Primes Info instance. Must not be 
186                 *            {@code null}.
187                 */
188                public OtherPrimesInfo(final RSAOtherPrimeInfo oth) {
189
190                        r = Base64URL.encode(oth.getPrime());
191                        d = Base64URL.encode(oth.getExponent());
192                        t = Base64URL.encode(oth.getCrtCoefficient());
193                }
194       
195        
196                /**
197                 * Gets the prime factor ({@code r}).
198                 *
199                 * @return The prime factor.
200                 */
201                public Base64URL getPrimeFactor() {
202
203                        return r;
204                }
205
206
207                /**
208                 * Gets factor Chinese Remainder Theorem (CRT) exponent
209                 * ({@code d}).
210                 *
211                 * @return The factor Chinese Remainder Theorem (CRT) exponent.
212                 */
213                public Base64URL getFactorCRTExponent() {
214
215                        return d;
216                }
217
218
219                /**
220                 * The factor Chinese Remainder Theorem (CRT) coefficient
221                 * ({@code t}).
222                 *
223                 * @return The factor Chinese Remainder Theorem (CRT) 
224                 *         coefficient.
225                 */
226                public Base64URL getFactorCRTCoefficient() {
227
228                        return t;
229                }
230
231
232                /**
233                 * Converts the specified array of 
234                 * {@code java.security.spec.RSAOtherPrimeInfo} instances to a
235                 * list of JWK Other Prime Infos.
236                 *
237                 * @param othArray Array of RSA Other Primes Info instances. 
238                 *                 May be be {@code null}.
239                 *
240                 * @return The corresponding list of JWK Other Prime Infos, or
241                 *         empty list of the array was {@code null}.
242                 */
243                public static List<OtherPrimesInfo> toList(final RSAOtherPrimeInfo[] othArray) {
244
245                        List<OtherPrimesInfo> list = new ArrayList<OtherPrimesInfo>();
246
247                        if (othArray == null) {
248
249                                // Return empty list
250                                return list;
251                        }
252
253                        for (RSAOtherPrimeInfo oth: othArray) {
254
255                                list.add(new OtherPrimesInfo(oth));
256                        }
257
258                        return list;
259                }
260        }
261
262
263        // Public RSA params
264
265        /**
266         * The modulus value for the RSA key.
267         */
268        private final Base64URL n;
269
270
271        /**
272         * The public exponent of the RSA key.
273         */
274        private final Base64URL e;
275
276
277        // Private RSA params, 1st representation       
278
279        /**
280         * The private exponent of the RSA key.
281         */
282        private final Base64URL d;
283
284        
285        // Private RSA params, 2nd representation
286
287        /**
288         * The first prime factor of the private RSA key.
289         */
290        private final Base64URL p;
291
292        
293        /**
294         * The second prime factor of the private RSA key.
295         */
296        private final Base64URL q;
297
298        
299        /**
300         * The first factor Chinese Remainder Theorem exponent of the private 
301         * RSA key.
302         */
303        private final Base64URL dp;
304
305        
306        /**
307         * The second factor Chinese Remainder Theorem exponent of the private
308         * RSA key.
309         */
310        private final Base64URL dq;
311
312        
313        /**
314         * The first Chinese Remainder Theorem coefficient of the private RSA
315         * key.
316         */
317        private final Base64URL qi;
318
319        
320        /**
321         * The other primes information of the private RSA key, should the
322         * exist. When only two primes have been used (the normal case), this 
323         * parameter MUST be omitted. When three or more primes have been used,
324         * the number of array elements MUST be the number of primes used minus
325         * two. Each array element MUST be an object with the following 
326         * members:
327         */
328        private final List<OtherPrimesInfo> oth;
329
330
331        /**
332         * Creates a new public RSA JSON Web Key (JWK) with the specified 
333         * parameters.
334         *
335         * @param n   The the modulus value for the public RSA key. It is 
336         *            represented as the Base64URL encoding of value's big 
337         *            endian representation. Must not be {@code null}.
338         * @param e   The exponent value for the public RSA key. It is 
339         *            represented as the Base64URL encoding of value's big 
340         *            endian representation. Must not be {@code null}.
341         * @param use The key use, {@code null} if not specified.
342         * @param alg The intended JOSE algorithm for the key, {@code null} if
343         *            not specified.
344         * @param kid The key ID. {@code null} if not specified.
345         */
346        public RSAKey(final Base64URL n, final Base64URL e, final Use use, 
347                      final Algorithm alg, final String kid) {
348
349                // Call the full constructor, all private key parameters are null
350                this(n, e, null, null, null, null, null, null, null, use, alg, kid);
351        }
352
353
354        /**
355         * Creates a new public / private RSA JSON Web Key (JWK) with the 
356         * specified parameters. The private RSA key is specified by its first
357         * representation (see RFC 3447, section 3.2).
358         * 
359         * @param n   The the modulus value for the public RSA key. It is
360         *            represented as the Base64URL encoding of value's big 
361         *            endian representation. Must not be {@code null}.
362         * @param e   The exponent value for the public RSA key. It is 
363         *            represented as the Base64URL encoding of value's big 
364         *            endian representation. Must not be {@code null}.
365         * @param d   The private exponent. It is represented as the Base64URL 
366         *            encoding of the value's big endian representation. Must 
367         *            not be {@code null}.
368         * @param use The key use, {@code null} if not specified.
369         * @param alg The intended JOSE algorithm for the key, {@code null} if
370         *            not specified.
371         * @param kid The key ID. {@code null} if not specified.
372         */
373        public RSAKey(final Base64URL n, final Base64URL e, final Base64URL d,
374                      final Use use, final Algorithm alg, final String kid) {
375            
376                // Call the full constructor, the second private representation 
377                // parameters are all null
378                this(n, e, d, null, null, null, null, null, null, use, alg, kid);
379
380                if (d == null) {
381                        throw new IllegalArgumentException("The private exponent must not be null");
382                }
383        }
384
385
386        /**
387         * Creates a new public / private RSA JSON Web Key (JWK) with the 
388         * specified parameters. The private RSA key is specified by its
389         * second representation (see RFC 3447, section 3.2).
390         * 
391         * @param n   The the modulus value for the public RSA key. It is
392         *            represented as the Base64URL encoding of value's big 
393         *            endian representation. Must not be {@code null}.
394         * @param e   The exponent value for the public RSA key. It is 
395         *            represented as the Base64URL encoding of value's big 
396         *            endian representation. Must not be {@code null}.
397         * @param p   The first prime factor. It is represented as the 
398         *            Base64URL encoding of the value's big endian 
399         *            representation. Must not be {@code null}.
400         * @param q   The second prime factor. It is represented as the 
401         *            Base64URL encoding of the value's big endian 
402         *            representation. Must not be {@code null}.
403         * @param dp  The first factor Chinese Remainder Theorem exponent. It 
404         *            is represented as the Base64URL encoding of the value's 
405         *            big endian representation. Must not be {@code null}.
406         * @param dq  The second factor Chinese Remainder Theorem exponent. It 
407         *            is represented as the Base64URL encoding of the value's 
408         *            big endian representation. Must not be {@code null}.
409         * @param qi  The first Chinese Remainder Theorem coefficient. It is 
410         *            represented as the Base64URL encoding of the value's big 
411         *            endian representation. Must not be {@code null}.
412         * @param oth The other primes information, should they exist,
413         *            {@code null} or an empty list if not specified.
414         * @param use The key use, {@code null} if not specified.
415         * @param alg The intended JOSE algorithm for the key, {@code null} if
416         *            not specified.
417         * @param kid The key ID. {@code null} if not specified.
418         */
419        public RSAKey(final Base64URL n, final Base64URL e, 
420                      final Base64URL p, final Base64URL q, 
421                      final Base64URL dp, final Base64URL dq, final Base64URL qi, 
422                      final List<OtherPrimesInfo> oth,
423                      final Use use, final Algorithm alg, final String kid) {
424            
425                // Call the full constructor, the first private representation 
426                // d param is null
427                this(n, e, null, p, q, dp, dq, qi, oth, use, alg, kid);
428
429                if (p == null) {
430                        throw new IllegalArgumentException("The first prime factor must not be null");
431                }
432
433                if (q == null) {
434                        throw new IllegalArgumentException("The second prime factor must not be null");
435                }
436
437                if (dp == null) {
438                        throw new IllegalArgumentException("The first factor CRT exponent must not be null");
439                }
440
441                if (dq == null) {
442                        throw new IllegalArgumentException("The second factor CRT exponent must not be null");
443                }
444
445                if (qi == null) {
446                        throw new IllegalArgumentException("The first CRT coefficient must not be null");
447                }
448        }
449
450
451        /**
452         * Creates a new public / private RSA JSON Web Key (JWK) with the 
453         * specified parameters. The private RSA key is specified by both its
454         * first and second representations (see RFC 3447, section 3.2).
455         *
456         * <p>A valid first private RSA key representation must specify the
457         * {@code d}.
458         *
459         * <p>A valid second private RSA key representation must specify all 
460         * required Chinese Remained Theorem (CRT) parameters - {@code p}, 
461         * {@code q}, {@code dp}, {@code dq} and {@code qi}, else an
462         * {@link java.lang.IllegalArgumentException} will be thrown.
463         * 
464         * @param n   The the modulus value for the public RSA key. It is
465         *            represented as the Base64URL encoding of value's big 
466         *            endian representation. Must not be {@code null}.
467         * @param e   The exponent value for the public RSA key. It is 
468         *            represented as the Base64URL encoding of value's big 
469         *            endian representation. Must not be {@code null}.
470         * @param d   The private exponent. It is represented as the Base64URL 
471         *            encoding of the value's big endian representation. May 
472         *            be {@code null}.
473         * @param p   The first prime factor. It is represented as the 
474         *            Base64URL encoding of the value's big endian 
475         *            representation. May be {@code null}.
476         * @param q   The second prime factor. It is represented as the 
477         *            Base64URL encoding of the value's big endian 
478         *            representation. May be {@code null}.
479         * @param dp  The first factor Chinese Remainder Theorem exponent. It 
480         *            is represented as the Base64URL encoding of the value's 
481         *            big endian representation. May be {@code null}.
482         * @param dq  The second factor Chinese Remainder Theorem exponent. It 
483         *            is represented as the Base64URL encoding of the value's 
484         *            big endian representation. May be {@code null}.
485         * @param qi  The first Chinese Remainder Theorem coefficient. It is 
486         *            represented as the Base64URL encoding of the value's big 
487         *            endian representation. May be {@code null}.
488         * @param oth The other primes information, should they exist,
489         *            {@code null} or an empty list if not specified.
490         * @param use The key use, {@code null} if not specified.
491         * @param alg The intended JOSE algorithm for the key, {@code null} if
492         *            not specified.
493         * @param kid The key ID. {@code null} if not specified.
494         */
495        public RSAKey(final Base64URL n, final Base64URL e,
496                      final Base64URL d, 
497                      final Base64URL p, final Base64URL q, 
498                      final Base64URL dp, final Base64URL dq, final Base64URL qi, 
499                      final List<OtherPrimesInfo> oth,
500                      final Use use, final Algorithm alg, final String kid) {
501            
502                super(KeyType.RSA, use, alg, kid);
503
504
505                // Ensure the public params are defined
506
507                if (n == null) {
508                        throw new IllegalArgumentException("The modulus value must not be null");
509                }
510
511                this.n = n;
512
513
514                if (e == null) {
515                        throw new IllegalArgumentException("The public exponent value must not be null");
516                }
517
518                this.e = e;
519
520
521                // Private params, 1st representation
522
523                this.d = d;
524
525
526                // Private params, 2nd representation, check for consistency
527
528                if (p != null && q != null && dp != null && dq != null && qi != null) {
529
530                        // CRT params fully specified
531
532                        this.p = p;
533                        this.q = q;
534                        this.dp = dp;
535                        this.dq = dq;
536                        this.qi = qi;
537
538                        // Other RSA primes info optional, default to empty list
539                        if (oth != null) {
540
541                                this.oth = Collections.unmodifiableList(oth);
542
543                        } else {
544
545                                this.oth = Collections.emptyList();
546                        }
547
548                } else if (p == null && q == null && dp == null && dq == null && qi == null && oth == null) {
549
550                        // No CRT params
551                        this.p = null;
552                        this.q = null;
553                        this.dp = null;
554                        this.dq = null;
555                        this.qi = null;
556
557                        this.oth = Collections.emptyList();
558
559                } else {
560
561                        if (p == null) {
562                                throw new IllegalArgumentException("Incomplete second private (CRT) representation: The first prime factor must not be null");
563                        }
564
565                        if (q == null) {
566                                throw new IllegalArgumentException("Incomplete second private (CRT) representation: The second prime factor must not be null");
567                        }
568
569                        if (dp == null) {
570                                throw new IllegalArgumentException("Incomplete second private (CRT) representation: The first factor CRT exponent must not be null");
571                        }
572
573                        if (dq == null) {
574                                throw new IllegalArgumentException("Incomplete second private (CRT) representation: The second factor CRT exponent must not be null");
575                        }
576
577                        if (qi == null) {
578                                throw new IllegalArgumentException("Incomplete second private (CRT) representation: The first CRT coefficient must not be null");
579                        }
580
581                        // We shouldn't really fall through
582                        throw new IllegalArgumentException("Incomplete second private (CRT) representation");
583                }
584        }
585
586
587        /**
588         * Creates a new public RSA JSON Web Key (JWK) with the specified
589         * parameters.
590         * 
591         * @param pub The public RSA key to represent. Must not be 
592         *            {@code null}.
593         * @param use The key use, {@code null} if not specified.
594         * @param alg The intended JOSE algorithm for the key, {@code null} if
595         *            not specified.
596         * @param kid The key ID. {@code null} if not specified.
597         */
598        public RSAKey(final RSAPublicKey pub, final Use use, final Algorithm alg, final String kid) {
599
600                this(Base64URL.encode(pub.getModulus()), 
601                     Base64URL.encode(pub.getPublicExponent()), 
602                     use, alg, kid);
603        }
604
605
606        /**
607         * Creates a new public / private RSA JSON Web Key (JWK) with the 
608         * specified parameters. The private RSA key is specified by its first
609         * representation (see RFC 3447, section 3.2).
610         * 
611         * @param pub  The public RSA key to represent. Must not be 
612         *             {@code null}.
613         * @param priv The private RSA key to represent. Must not be
614         *             {@code null}.
615         * @param use  The key use, {@code null} if not specified.
616         * @param alg  The intended JOSE algorithm for the key, {@code null} if
617         *             not specified.
618         * @param kid  The key ID. {@code null} if not specified.
619         */
620        public RSAKey(final RSAPublicKey pub, final RSAPrivateKey priv,
621                      final Use use, final Algorithm alg, final String kid) {
622                
623                this(Base64URL.encode(pub.getModulus()), 
624                     Base64URL.encode(pub.getPublicExponent()), 
625                     Base64URL.encode(priv.getPrivateExponent()),
626                     use, alg, kid);
627        }
628
629
630        /**
631         * Creates a new public / private RSA JSON Web Key (JWK) with the 
632         * specified parameters. The private RSA key is specified by its second
633         * representation (see RFC 3447, section 3.2).
634         * 
635         * @param pub  The public RSA key to represent. Must not be 
636         *             {@code null}.
637         * @param priv The private RSA key to represent. Must not be
638         *             {@code null}.
639         * @param use  The key use, {@code null} if not specified.
640         * @param alg  The intended JOSE algorithm for the key, {@code null} if
641         *             not specified.
642         * @param kid  The key ID. {@code null} if not specified.
643         */
644        public RSAKey(final RSAPublicKey pub, final RSAPrivateCrtKey priv,
645                      final Use use, final Algorithm alg, final String kid) {
646                
647                this(Base64URL.encode(pub.getModulus()), 
648                     Base64URL.encode(pub.getPublicExponent()), 
649                     Base64URL.encode(priv.getPrivateExponent()),
650                     Base64URL.encode(priv.getPrimeP()),
651                     Base64URL.encode(priv.getPrimeQ()),
652                     Base64URL.encode(priv.getPrimeExponentP()),
653                     Base64URL.encode(priv.getPrimeExponentQ()),
654                     Base64URL.encode(priv.getCrtCoefficient()),
655                     null,
656                     use, alg, kid);
657        }
658
659
660        /**
661         * Creates a new public / private RSA JSON Web Key (JWK) with the 
662         * specified parameters. The private RSA key is specified by its second
663         * representation, with optional other primes info (see RFC 3447, 
664         * section 3.2).
665         * 
666         * @param pub  The public RSA key to represent. Must not be 
667         *             {@code null}.
668         * @param priv The private RSA key to represent. Must not be
669         *             {@code null}.
670         * @param use  The key use, {@code null} if not specified.
671         * @param alg  The intended JOSE algorithm for the key, {@code null} if
672         *             not specified.
673         * @param kid  The key ID. {@code null} if not specified.
674         */
675        public RSAKey(final RSAPublicKey pub, final RSAMultiPrimePrivateCrtKey priv,
676                      final Use use, final Algorithm alg, final String kid) {
677                
678                this(Base64URL.encode(pub.getModulus()), 
679                     Base64URL.encode(pub.getPublicExponent()), 
680                     Base64URL.encode(priv.getPrivateExponent()),
681                     Base64URL.encode(priv.getPrimeP()),
682                     Base64URL.encode(priv.getPrimeQ()),
683                     Base64URL.encode(priv.getPrimeExponentP()),
684                     Base64URL.encode(priv.getPrimeExponentQ()),
685                     Base64URL.encode(priv.getCrtCoefficient()),
686                     OtherPrimesInfo.toList(priv.getOtherPrimeInfo()),
687                     use, alg, kid);
688        }
689
690
691        /**
692         * Returns the modulus value ({@code n}) of the RSA key. It is 
693         * represented as the Base64URL encoding of the value's big endian 
694         * representation.
695         *
696         * @return The RSA key modulus.
697         */
698        public Base64URL getModulus() {
699
700                return n;
701        }
702
703
704        /**
705         * Returns the public exponent ({@code e}) of the RSA key. It is
706         * represented as the Base64URL encoding of the value's big endian 
707         * representation.
708         *
709         * @return The public RSA key exponent.
710         */
711        public Base64URL getPublicExponent() {
712
713                return e;
714        }
715
716
717        /**
718         * Returns the private exponent ({@code d}) of the RSA key. It is
719         * represented as the Base64URL encoding of the value's big endian 
720         * representation.
721         *
722         * @return The private RSA key exponent, {@code null} if not specified.
723         */
724        public Base64URL getPrivateExponent() {
725
726                return d;
727        }
728
729
730        /**
731         * Returns the first prime factor ({@code p}) of the private RSA key. 
732         * It is represented as the Base64URL encoding of the value's big 
733         * endian representation.
734         *
735         * @return The RSA first prime factor, {@code null} if not specified.
736         */
737        public Base64URL getFirstPrimeFactor() {
738
739                return p;
740        }
741
742
743        /**
744         * Returns the second prime factor ({@code q}) of the private RSA key. 
745         * It is represented as the Base64URL encoding of the value's big 
746         * endian representation.
747         *
748         * @return The RSA second prime factor, {@code null} if not specified.
749         */
750        public Base64URL getSecondPrimeFactor() {
751
752                return q;
753        }
754
755
756        /**
757         * Returns the first factor Chinese Remainder Theorem (CRT) exponent
758         * ({@code dp}) of the private RSA key. It is represented as the 
759         * Base64URL encoding of the value's big endian representation.
760         *
761         * @return The RSA first factor CRT exponent, {@code null} if not 
762         *         specified.
763         */
764        public Base64URL getFirstFactorCRTExponent() {
765
766                return dp;
767        }
768
769
770        /**
771         * Returns the second factor Chinese Remainder Theorem (CRT) exponent 
772         * ({@code dq}) of the private RSA key. It is represented as the 
773         * Base64URL encoding of the value's big endian representation.
774         *
775         * @return The RSA second factor CRT exponent, {@code null} if not
776         *         specified.
777         */
778        public Base64URL getSecondFactorCRTExponent() {
779
780                return dq;
781        }
782
783
784        /**
785         * Returns the first Chinese Remainder Theorem (CRT) coefficient
786         * ({@code qi})} of the private RSA key. It is represented as the 
787         * Base64URL encoding of the value's big endian representation.
788         *
789         * @return The RSA first CRT coefficient, {@code null} if not 
790         *         specified.
791         */
792        public Base64URL getFirstCRTCoefficient() {
793
794                return qi;
795        }
796
797
798        /**
799         * Returns the other primes information ({@code oth}) for the private 
800         * RSA key, should they exist.
801         *
802         * @return The RSA other primes information, {@code null} or empty list
803         *         if not specified.
804         */
805        public List<OtherPrimesInfo> getOtherPrimes() {
806
807                return oth;
808        }
809
810        
811        /**
812         * Returns a standard {@code java.security.interfaces.RSAPublicKey} 
813         * representation of this RSA JWK.
814         * 
815         * @return The public RSA key.
816         * 
817         * @throws NoSuchAlgorithmException If RSA is not supported by the
818         *                                  underlying Java Cryptography (JCA)
819         *                                  provider.
820         * @throws InvalidKeySpecException  If the JWK key parameters are 
821         *                                  invalid for a public RSA key.
822         */
823        public RSAPublicKey toRSAPublicKey() 
824                throws NoSuchAlgorithmException, InvalidKeySpecException {
825
826                BigInteger modulus = n.decodeToBigInteger();
827                BigInteger exponent = e.decodeToBigInteger();
828                                
829                RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
830                KeyFactory factory = KeyFactory.getInstance("RSA");
831                
832                RSAPublicKey pub = (RSAPublicKey) factory.generatePublic(spec);
833                
834                return pub;
835        }
836        
837
838        /**
839         * Returns a standard {@code java.security.interfaces.RSAPrivateKey} 
840         * representation of this RSA JWK.
841         * 
842         * @return The private RSA key, {@code null} if not specified by this
843         *         JWK.
844         * 
845         * @throws NoSuchAlgorithmException If RSA is not supported by the
846         *                                  underlying Java Cryptography (JCA)
847         *                                  provider.
848         * @throws InvalidKeySpecException  If the JWK key parameters are 
849         *                                  invalid for a private RSA key.
850         */
851        public RSAPrivateKey toRSAPrivateKey() 
852                throws NoSuchAlgorithmException, InvalidKeySpecException {
853                
854                if (d == null) {
855                        // no private key
856                        return null;
857                }
858                
859                BigInteger modulus = n.decodeToBigInteger();
860                BigInteger privateExponent = d.decodeToBigInteger();
861                
862                RSAPrivateKeySpec spec;
863
864                if (p == null) {
865                        // Use 1st representation
866                        spec = new RSAPrivateKeySpec(modulus, privateExponent);
867
868                } else {
869                        // Use 2nd (CRT) representation
870                        BigInteger publicExponent = e.decodeToBigInteger();
871                        BigInteger primeP = p.decodeToBigInteger();
872                        BigInteger primeQ = q.decodeToBigInteger();
873                        BigInteger primeExponentP = dp.decodeToBigInteger();
874                        BigInteger primeExponentQ = dq.decodeToBigInteger();
875                        BigInteger crtCoefficient = qi.decodeToBigInteger();
876
877                        if (oth != null && ! oth.isEmpty()) {
878                                // Construct other info spec
879                                RSAOtherPrimeInfo[] otherInfo = new RSAOtherPrimeInfo[oth.size()];
880
881                                for (int i=0; i < oth.size(); i++) {
882
883                                        OtherPrimesInfo opi = oth.get(i);
884
885                                        BigInteger otherPrime = opi.getPrimeFactor().decodeToBigInteger();
886                                        BigInteger otherPrimeExponent = opi.getFactorCRTExponent().decodeToBigInteger();
887                                        BigInteger otherCrtCoefficient = opi.getFactorCRTCoefficient().decodeToBigInteger();
888
889                                        otherInfo[i] = new RSAOtherPrimeInfo(otherPrime,
890                                                                             otherPrimeExponent,
891                                                                             otherCrtCoefficient);
892                                }
893
894                                spec = new RSAMultiPrimePrivateCrtKeySpec(modulus,
895                                                                          publicExponent,
896                                                                          privateExponent,
897                                                                          primeP,
898                                                                          primeQ,
899                                                                          primeExponentP,
900                                                                          primeExponentQ,
901                                                                          crtCoefficient,
902                                                                          otherInfo);
903                        } else {
904                                // Construct spec with no other info
905                                spec = new RSAPrivateCrtKeySpec(modulus,
906                                                                publicExponent,
907                                                                privateExponent,
908                                                                primeP,
909                                                                primeQ,
910                                                                primeExponentP,
911                                                                primeExponentQ,
912                                                                crtCoefficient);        
913                        } 
914                }
915                
916                KeyFactory factory = KeyFactory.getInstance("RSA");
917                
918                RSAPrivateKey priv = (RSAPrivateKey) factory.generatePrivate(spec);
919                
920                return priv;
921        }
922
923
924        /**
925         * Returns a standard {@code java.security.KeyPair} representation of 
926         * this RSA JWK.
927         * 
928         * @return The RSA key pair. The private RSA key will be {@code null} 
929         *         if not specified.
930         * 
931         * @throws NoSuchAlgorithmException If RSA is not supported by the
932         *                                  underlying Java Cryptography (JCA)
933         *                                  provider.
934         * @throws InvalidKeySpecException  If the JWK key parameters are 
935         *                                  invalid for a public and / or 
936         *                                  private RSA key.
937         */
938        public KeyPair toKeyPair() 
939                throws NoSuchAlgorithmException, InvalidKeySpecException {
940                
941                return new KeyPair(toRSAPublicKey(), toRSAPrivateKey());
942        }
943
944
945        @Override
946        public boolean isPrivate() {
947
948                // Check if 1st or 2nd form params are specified
949                if (d != null || p != null) {
950
951                        return true;
952
953                } else {
954
955                        return false;
956                }
957        }
958
959
960        /**
961         * Returns a copy of this RSA JWK with any private values removed.
962         *
963         * @return The copied public RSA JWK.
964         */
965        @Override
966        public RSAKey toPublicJWK() {
967
968                return new RSAKey(getModulus(), getPublicExponent(), getKeyUse(), getAlgorithm(), getKeyID());
969        }
970        
971        
972        @Override
973        public JSONObject toJSONObject() {
974
975                JSONObject o = super.toJSONObject();
976
977                // Append public RSA key specific attributes
978                o.put("n", n.toString());
979                o.put("e", e.toString());
980                if (d != null) {
981                        o.put("d", d.toString());
982                }
983                if (p != null) {
984                        o.put("p", p.toString());
985                }
986                if (q != null) {
987                        o.put("q", q.toString());
988                }
989                if (dp != null) {
990                        o.put("dp", dp.toString());
991                }
992                if (dq != null) {
993                        o.put("dq", dq.toString());
994                }
995                if (qi != null) {
996                        o.put("qi", qi.toString());
997                }
998                if (oth != null && !oth.isEmpty()) {
999
1000                        JSONArray a = new JSONArray();
1001
1002                        for (OtherPrimesInfo other : oth) {
1003
1004                                JSONObject oo = new JSONObject();
1005                                oo.put("r", other.r.toString());
1006                                oo.put("d", other.d.toString());
1007                                oo.put("t", other.t.toString());
1008
1009                                a.add(oo);
1010                        }
1011
1012                        o.put("oth", a);
1013                }
1014
1015                return o;
1016        }
1017
1018
1019        /**
1020         * Parses a public / private RSA Curve JWK from the specified JSON
1021         * object string representation.
1022         *
1023         * @param s The JSON object string to parse. Must not be {@code null}.
1024         *
1025         * @return The public / private RSA JWK.
1026         *
1027         * @throws ParseException If the string couldn't be parsed to an RSA
1028         *                        JWK.
1029         */
1030        public static RSAKey parse(final String s)
1031                throws ParseException {
1032
1033                return parse(JSONObjectUtils.parseJSONObject(s));
1034        }
1035
1036
1037        /**
1038         * Parses a public / private RSA JWK from the specified JSON object 
1039         * representation.
1040         *
1041         * @param jsonObject The JSON object to parse. Must not be 
1042         *                   @code null}.
1043         *
1044         * @return The public / private RSA Key.
1045         *
1046         * @throws ParseException If the JSON object couldn't be parsed to an
1047         *                        RSA JWK.
1048         */
1049        public static RSAKey parse(final JSONObject jsonObject)
1050                        throws ParseException {
1051
1052                // Parse the mandatory public key parameters first
1053                Base64URL n = new Base64URL(JSONObjectUtils.getString(jsonObject, "n"));
1054                Base64URL e = new Base64URL(JSONObjectUtils.getString(jsonObject, "e"));
1055
1056                // Check key type
1057                KeyType kty = KeyType.parse(JSONObjectUtils.getString(jsonObject, "kty"));
1058                if (kty != KeyType.RSA) {
1059                        throw new ParseException("The key type \"kty\" must be RSA", 0);
1060                }
1061                
1062                // Parse the optional private key parameters
1063
1064                // 1st private representation
1065                Base64URL d = null;
1066                if (jsonObject.get("d") != null) {
1067                        d = new Base64URL(JSONObjectUtils.getString(jsonObject, "d"));
1068                }
1069
1070                // 2nd private (CRT) representation
1071                Base64URL p = null;
1072                if (jsonObject.get("p") != null) {
1073                        p = new Base64URL(JSONObjectUtils.getString(jsonObject, "p"));
1074                }
1075                Base64URL q = null;
1076                if (jsonObject.get("q") != null) {
1077                        q = new Base64URL(JSONObjectUtils.getString(jsonObject, "q"));
1078                }
1079                Base64URL dp = null;
1080                if (jsonObject.get("dp") != null) {
1081                        dp = new Base64URL(JSONObjectUtils.getString(jsonObject, "dp"));
1082                }
1083                Base64URL dq= null;
1084                if (jsonObject.get("dq") != null) {
1085                        dq = new Base64URL(JSONObjectUtils.getString(jsonObject, "dq"));
1086                }
1087                Base64URL qi = null;
1088                if (jsonObject.get("qi") != null) {
1089                        qi = new Base64URL(JSONObjectUtils.getString(jsonObject, "qi"));
1090                }
1091                
1092                List<OtherPrimesInfo> oth = null;
1093                if (jsonObject.get("oth") != null) {
1094
1095                        JSONArray arr = JSONObjectUtils.getJSONArray(jsonObject, "oth");
1096                        oth = new ArrayList<RSAKey.OtherPrimesInfo>(arr.size());
1097                        
1098                        for (Object o : arr) {
1099
1100                                if (o instanceof JSONObject) {
1101                                        JSONObject otherJson = (JSONObject)o;
1102
1103                                        Base64URL r = new Base64URL(JSONObjectUtils.getString(otherJson, "r"));
1104                                        Base64URL odq = new Base64URL(JSONObjectUtils.getString(otherJson, "dq"));
1105                                        Base64URL t = new Base64URL(JSONObjectUtils.getString(otherJson, "t"));
1106
1107                                        OtherPrimesInfo prime = new OtherPrimesInfo(r, odq, t);
1108                                        oth.add(prime);
1109                                }
1110                        }
1111                }
1112                
1113                // Get optional key use
1114                Use use = JWK.parseKeyUse(jsonObject);
1115
1116                // Get optional intended algorithm
1117                Algorithm alg = JWK.parseAlgorithm(jsonObject);
1118
1119                // Get optional key ID
1120                String kid = JWK.parseKeyID(jsonObject);
1121
1122                try {
1123                        return new RSAKey(n, e, d, p, q, dp, dq, qi, oth, use, alg, kid);       
1124                
1125                } catch (IllegalArgumentException ex) {
1126
1127                        // Inconsistent 2nd spec
1128                        throw new ParseException(ex.getMessage(), 0);
1129                }
1130        }
1131}