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