001    package com.nimbusds.jose.jwk;
002    
003    
004    import net.jcip.annotations.Immutable;
005    
006    import net.minidev.json.JSONAware;
007    import net.minidev.json.JSONObject;
008    
009    import com.nimbusds.jose.Requirement;
010    
011    
012    /**
013     * Key type. Used to represent the {@code kty} parameter in a JSON Web Key
014     * (JWK). This class is immutable.
015     *
016     * <p>Includes constants for the following standard key types:
017     *
018     * <ul>
019     *     <li>{@link #EC}
020     *     <li>{@link #RSA}
021     *     <li>{@link #OCT}
022     * </ul>
023     *
024     * <p>Additional key types can be defined using the constructor.
025     *
026     * @author Vladimir Dzhuvinov
027     * @author Justin Richer
028     * @version $version$ (2013-03-27)
029     */
030    @Immutable
031    public final class KeyType implements JSONAware {
032    
033    
034            /**
035             * The key type value.
036             */
037            private final String value;
038    
039    
040            /**
041             * The implementation requirement, {@code null} if not known.
042             */
043            private final Requirement requirement;
044    
045    
046            /**
047             * Elliptic Curve (DSS) key type (recommended).
048             */
049            public static final KeyType EC = new KeyType("EC", Requirement.RECOMMENDED);
050    
051    
052            /**
053             * RSA (RFC 3447) key type (required).
054             */
055            public static final KeyType RSA = new KeyType("RSA", Requirement.REQUIRED);
056    
057    
058            /**
059             * Octet sequence key type (optional)
060             */
061            public static final KeyType OCT = new KeyType("oct", Requirement.OPTIONAL);
062            
063    
064            /**
065             * Creates a new key type with the specified value and implementation 
066             * requirement.
067             *
068             * @param value The key type value. Values are case sensitive. Must not
069             *              be {@code null}.
070             * @param req   The implementation requirement, {@code null} if not 
071             *              known.
072             */
073            public KeyType(final String value, final Requirement req) {
074    
075                    if (value == null) {
076    
077                            throw new IllegalArgumentException("The key type value must not be null");
078                    }
079    
080                    this.value = value;
081    
082                    requirement = req;
083            }
084    
085    
086            /**
087             * Gets the value of this key type. Values are case sensitive.
088             *
089             * @return The key type.
090             */
091            public String getValue() {
092    
093                    return value;
094            }
095    
096    
097            /**
098             * Gets the implementation requirement of this key type.
099             *
100             * @return The implementation requirement, {@code null} if not known.
101             */
102            public Requirement getRequirement() {
103    
104                    return requirement;
105            }
106    
107    
108            /**
109             * Overrides {@code Object.hashCode()}.
110             *
111             * @return The object hash code.
112             */
113            @Override
114            public int hashCode() {
115    
116                    return value.hashCode();
117            }
118    
119    
120            /**
121             * Overrides {@code Object.equals()}.
122             *
123             * @param object The object to compare to.
124             *
125             * @return {@code true} if the objects have the same value, otherwise
126             *         {@code false}.
127             */
128            @Override
129            public boolean equals(final Object object) {
130    
131                    return object != null && 
132                           object instanceof KeyType && 
133                           this.toString().equals(object.toString());
134            }
135    
136    
137            /**
138             * Returns the string representation of this key type.
139             *
140             * @see #getValue
141             *
142             * @return The string representation.
143             */
144            @Override
145            public String toString() {
146    
147                    return value;
148            }
149    
150    
151            /**
152             * Returns the JSON string representation of this key type.
153             * 
154             * @return The JSON string representation.
155             */
156            @Override
157            public String toJSONString() {
158    
159                    StringBuilder sb = new StringBuilder();
160                    sb.append('"');
161                    sb.append(JSONObject.escape(value));
162                    sb.append('"');
163                    return sb.toString();
164            }
165    
166    
167            /**
168             * Parses a key type from the specified string.
169             *
170             * @param s The string to parse. Must not be {@code null}.
171             *
172             * @return The key type (matching standard key type constant, else a 
173             *         newly created one).
174             *
175             * @throws ParseException If the string couldn't be parsed.
176             */
177            public static KeyType parse(final String s) {
178    
179                    if (s == null) {
180    
181                            throw new IllegalArgumentException("The ket type string must not be null");
182                    }
183    
184                    if (s.equals(EC.getValue())) {
185    
186                            return EC;
187    
188                    } else if (s.equals(RSA.getValue())) {
189    
190                            return RSA;
191    
192                    } else if (s.equals(OCT.getValue())) {
193    
194                            return OCT;
195    
196                    } else {
197                            
198                            return new KeyType(s, null);
199                    }
200            }
201    }