001    package com.nimbusds.jose;
002    
003    
004    import java.text.ParseException;
005    
006    import net.jcip.annotations.Immutable;
007    import net.minidev.json.JSONObject;
008    
009    import com.nimbusds.jose.util.Base64URL;
010    import com.nimbusds.jose.util.JSONObjectUtils;
011    
012    
013    /**
014     * Public {@link KeyType#RSA RSA} JSON Web Key (JWK). This class is immutable.
015     *
016     * <p>Example JSON:
017     *
018     * <pre>
019     * { 
020     *   "kty" : "RSA",
021     *   "n"   : "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx
022     *            4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs
023     *            tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2
024     *            QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI
025     *            SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb
026     *            w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
027     *   "e"   : "AQAB",
028     *   "alg" : "RS256"
029     *   "kid" : "2011-04-29"}
030     * }
031     * </pre>
032     *
033     * <p>See http://en.wikipedia.org/wiki/RSA_%28algorithm%29
034     *
035     * @author Vladimir Dzhuvinov
036     * @version $version$ (2013-01-08)
037     */
038    @Immutable
039    public final class RSAKey extends JWK {
040    
041    
042            /**
043             * The modulus value for the RSA public key.
044             */
045            private final Base64URL n;
046    
047    
048            /**
049             * The exponent value for the RSA public key.
050             */
051            private final Base64URL e;
052    
053    
054            /**
055             * Creates a new public RSA JSON Web Key (JWK) with the specified 
056             * parameters.
057             *
058             * @param n   The the modulus value for the RSA public key. It is 
059             *            represented as the Base64URL encoding of value's big 
060             *            endian representation. Must not be {@code null}.
061             * @param e   The exponent value for the RSA public key. It is 
062             *            represented as the Base64URL encoding of value's big 
063             *            endian representation. Must not be {@code null}.
064             * @param use The key use. {@code null} if not specified.
065             * @param alg The intended JOSE algorithm for the key, {@code null} if
066             *            not specified.
067             * @param kid The key ID. {@code null} if not specified.
068             */
069            public RSAKey(final Base64URL n, final Base64URL e, 
070                            final Use use, final Algorithm alg, final String kid) {
071    
072                    super(KeyType.RSA, use, alg, kid);
073    
074                    if (n == null) {
075                            throw new IllegalArgumentException("The modulus value must not be null");
076                    }
077    
078                    this.n = n;
079    
080                    if (e == null) {
081                            throw new IllegalArgumentException("The exponent value must not be null");
082                    }
083    
084                    this.e = e;
085            }
086    
087    
088            /**
089             * Returns the modulus value for this RSA public key. It is represented
090             * as the Base64URL encoding of the value's big ending representation.
091             *
092             * @return The RSA public key modulus.
093             */
094            public Base64URL getModulus() {
095    
096                    return n;
097            }
098    
099    
100            /**
101             * Returns the exponent value for this RSA public key. It is represented
102             * as the Base64URL encoding of the value's big ending representation.
103             *
104             * @return The RSA public key exponent.
105             */
106            public Base64URL getExponent() {
107    
108                    return e;
109            }
110    
111    
112            @Override
113            public JSONObject toJSONObject() {
114    
115                    JSONObject o = super.toJSONObject();
116    
117                    // Append RSA public key specific attributes
118                    o.put("n", n.toString());
119                    o.put("e", e.toString());
120    
121                    return o;
122            }
123    
124    
125            /**
126             * Parses a public RSA JWK from the specified JSON object 
127             * representation.
128             *
129             * @param jsonObject The JSON object to parse. Must not be 
130             *                   @code null}.
131             *
132             * @return The RSA Key.
133             *
134             * @throws ParseException If the JSON object couldn't be parsed to valid
135             *                        RSA JWK.
136             */
137            public static RSAKey parse(final JSONObject jsonObject)
138                            throws ParseException {
139    
140                    // Parse the mandatory parameters first
141                    KeyType kty = KeyType.parse(JSONObjectUtils.getString(jsonObject, "kty"));
142                    Base64URL mod = new Base64URL(JSONObjectUtils.getString(jsonObject, "n"));
143                    Base64URL exp = new Base64URL(JSONObjectUtils.getString(jsonObject, "e"));
144    
145                    // Get optional key use
146                    Use use = JWK.parseKeyUse(jsonObject);
147    
148                    // Get optional intended algorithm
149                    Algorithm alg = JWK.parseAlgorithm(jsonObject);
150    
151                    // Get optional key ID
152                    String id = JWK.parseKeyID(jsonObject);
153    
154                    // Check key type
155                    if (kty != KeyType.RSA) {
156                            throw new ParseException("The key type \"kty\" must be RSA", 0);
157                    }
158    
159                    return new RSAKey(mod, exp, use, alg, id);
160            }
161    }