001    package com.nimbusds.jose.jwk;
002    
003    
004    import java.math.BigInteger;
005    import java.security.KeyFactory;
006    import java.security.KeyPair;
007    import java.security.NoSuchAlgorithmException;
008    import java.security.interfaces.RSAMultiPrimePrivateCrtKey;
009    import java.security.interfaces.RSAPrivateCrtKey;
010    import java.security.interfaces.RSAPrivateKey;
011    import java.security.interfaces.RSAPublicKey;
012    import java.security.spec.InvalidKeySpecException;
013    import java.security.spec.RSAMultiPrimePrivateCrtKeySpec;
014    import java.security.spec.RSAOtherPrimeInfo;
015    import java.security.spec.RSAPrivateCrtKeySpec;
016    import java.security.spec.RSAPrivateKeySpec;
017    import java.security.spec.RSAPublicKeySpec;
018    import java.text.ParseException;
019    import java.util.ArrayList;
020    import java.util.Collections;
021    import java.util.List;
022    
023    import net.jcip.annotations.Immutable;
024    
025    import net.minidev.json.JSONArray;
026    import net.minidev.json.JSONObject;
027    
028    import com.nimbusds.jose.Algorithm;
029    import com.nimbusds.jose.util.Base64URL;
030    import 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
115    public 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    }