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