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