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