1 /*
2 * Copyright (C) 2014 jsonwebtoken.io
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package io.jsonwebtoken;
17
18 import io.jsonwebtoken.lang.RuntimeEnvironment;
19
20 /**
21 * Type-safe representation of standard JWT signature algorithm names as defined in the
22 * <a href="https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-31">JSON Web Algorithms</a> specification.
23 *
24 * @since 0.1
25 */
26 public enum SignatureAlgorithm {
27
28 /** JWA name for {@code No digital signature or MAC performed} */
29 NONE("none", "No digital signature or MAC performed", "None", null, false),
30
31 /** JWA algorithm name for {@code HMAC using SHA-256} */
32 HS256("HS256", "HMAC using SHA-256", "HMAC", "HmacSHA256", true),
33
34 /** JWA algorithm name for {@code HMAC using SHA-384} */
35 HS384("HS384", "HMAC using SHA-384", "HMAC", "HmacSHA384", true),
36
37 /** JWA algorithm name for {@code HMAC using SHA-512} */
38 HS512("HS512", "HMAC using SHA-512", "HMAC", "HmacSHA512", true),
39
40 /** JWA algorithm name for {@code RSASSA-PKCS-v1_5 using SHA-256} */
41 RS256("RS256", "RSASSA-PKCS-v1_5 using SHA-256", "RSA", "SHA256withRSA", true),
42
43 /** JWA algorithm name for {@code RSASSA-PKCS-v1_5 using SHA-384} */
44 RS384("RS384", "RSASSA-PKCS-v1_5 using SHA-384", "RSA", "SHA384withRSA", true),
45
46 /** JWA algorithm name for {@code RSASSA-PKCS-v1_5 using SHA-512} */
47 RS512("RS512", "RSASSA-PKCS-v1_5 using SHA-512", "RSA", "SHA512withRSA", true),
48
49 /**
50 * JWA algorithm name for {@code ECDSA using P-256 and SHA-256}. <b>This is not a JDK standard algorithm and
51 * requires that a JCA provider like BouncyCastle be in the runtime classpath.</b> BouncyCastle will be used
52 * automatically if found in the runtime classpath.
53 */
54 ES256("ES256", "ECDSA using P-256 and SHA-256", "Elliptic Curve", "SHA256withECDSA", false),
55
56 /**
57 * JWA algorithm name for {@code ECDSA using P-384 and SHA-384}. <b>This is not a JDK standard algorithm and
58 * requires that a JCA provider like BouncyCastle be in the runtime classpath.</b> BouncyCastle will be used
59 * automatically if found in the runtime classpath.
60 */
61 ES384("ES384", "ECDSA using P-384 and SHA-384", "Elliptic Curve", "SHA384withECDSA", false),
62
63 /**
64 * JWA algorithm name for {@code ECDSA using P-512 and SHA-512}. <b>This is not a JDK standard algorithm and
65 * requires that a JCA provider like BouncyCastle be in the runtime classpath.</b> BouncyCastle will be used
66 * automatically if found in the runtime classpath.
67 */
68 ES512("ES512", "ECDSA using P-512 and SHA-512", "Elliptic Curve", "SHA512withECDSA", false),
69
70 /**
71 * JWA algorithm name for {@code RSASSA-PSS using SHA-256 and MGF1 with SHA-256}. <b>This is not a JDK standard
72 * algorithm and requires that a JCA provider like BouncyCastle be in the runtime classpath.</b> BouncyCastle
73 * will be used automatically if found in the runtime classpath.
74 */
75 PS256("PS256", "RSASSA-PSS using SHA-256 and MGF1 with SHA-256", "RSA", "SHA256withRSAandMGF1", false),
76
77 /**
78 * JWA algorithm name for {@code RSASSA-PSS using SHA-384 and MGF1 with SHA-384}. <b>This is not a JDK standard
79 * algorithm and requires that a JCA provider like BouncyCastle be in the runtime classpath.</b> BouncyCastle
80 * will be used automatically if found in the runtime classpath.
81 */
82 PS384("PS384", "RSASSA-PSS using SHA-384 and MGF1 with SHA-384", "RSA", "SHA384withRSAandMGF1", false),
83
84 /**
85 * JWA algorithm name for {@code RSASSA-PSS using SHA-512 and MGF1 with SHA-512}. <b>This is not a JDK standard
86 * algorithm and requires that a JCA provider like BouncyCastle be in the classpath.</b> BouncyCastle will be used
87 * automatically if found in the runtime classpath.
88 */
89 PS512("PS512", "RSASSA-PSS using SHA-512 and MGF1 with SHA-512", "RSA", "SHA512withRSAandMGF1", false);
90
91 static {
92 RuntimeEnvironment.enableBouncyCastleIfPossible();
93 }
94
95 private final String value;
96 private final String description;
97 private final String familyName;
98 private final String jcaName;
99 private final boolean jdkStandard;
100
101 SignatureAlgorithm(String value, String description, String familyName, String jcaName, boolean jdkStandard) {
102 this.value = value;
103 this.description = description;
104 this.familyName = familyName;
105 this.jcaName = jcaName;
106 this.jdkStandard = jdkStandard;
107 }
108
109 /**
110 * Returns the JWA algorithm name constant.
111 *
112 * @return the JWA algorithm name constant.
113 */
114 public String getValue() {
115 return value;
116 }
117
118 /**
119 * Returns the JWA algorithm description.
120 *
121 * @return the JWA algorithm description.
122 */
123 public String getDescription() {
124 return description;
125 }
126
127
128 /**
129 * Returns the cryptographic family name of the signature algorithm. The value returned is according to the
130 * following table:
131 *
132 * <table>
133 * <caption>Crypto Family</caption>
134 * <thead>
135 * <tr>
136 * <th>SignatureAlgorithm</th>
137 * <th>Family Name</th>
138 * </tr>
139 * </thead>
140 * <tbody>
141 * <tr>
142 * <td>HS256</td>
143 * <td>HMAC</td>
144 * </tr>
145 * <tr>
146 * <td>HS384</td>
147 * <td>HMAC</td>
148 * </tr>
149 * <tr>
150 * <td>HS512</td>
151 * <td>HMAC</td>
152 * </tr>
153 * <tr>
154 * <td>RS256</td>
155 * <td>RSA</td>
156 * </tr>
157 * <tr>
158 * <td>RS384</td>
159 * <td>RSA</td>
160 * </tr>
161 * <tr>
162 * <td>RS512</td>
163 * <td>RSA</td>
164 * </tr>
165 * <tr>
166 * <td>PS256</td>
167 * <td>RSA</td>
168 * </tr>
169 * <tr>
170 * <td>PS384</td>
171 * <td>RSA</td>
172 * </tr>
173 * <tr>
174 * <td>PS512</td>
175 * <td>RSA</td>
176 * </tr>
177 * <tr>
178 * <td>ES256</td>
179 * <td>Elliptic Curve</td>
180 * </tr>
181 * <tr>
182 * <td>ES384</td>
183 * <td>Elliptic Curve</td>
184 * </tr>
185 * <tr>
186 * <td>ES512</td>
187 * <td>Elliptic Curve</td>
188 * </tr>
189 * </tbody>
190 * </table>
191 *
192 * @return Returns the cryptographic family name of the signature algorithm.
193 *
194 * @since 0.5
195 */
196 public String getFamilyName() {
197 return familyName;
198 }
199
200 /**
201 * Returns the name of the JCA algorithm used to compute the signature.
202 *
203 * @return the name of the JCA algorithm used to compute the signature.
204 */
205 public String getJcaName() {
206 return jcaName;
207 }
208
209 /**
210 * Returns {@code true} if the algorithm is supported by standard JDK distributions or {@code false} if the
211 * algorithm implementation is not in the JDK and must be provided by a separate runtime JCA Provider (like
212 * BouncyCastle for example).
213 *
214 * @return {@code true} if the algorithm is supported by standard JDK distributions or {@code false} if the
215 * algorithm implementation is not in the JDK and must be provided by a separate runtime JCA Provider (like
216 * BouncyCastle for example).
217 */
218 public boolean isJdkStandard() {
219 return jdkStandard;
220 }
221
222 /**
223 * Returns {@code true} if the enum instance represents an HMAC signature algorithm, {@code false} otherwise.
224 *
225 * @return {@code true} if the enum instance represents an HMAC signature algorithm, {@code false} otherwise.
226 */
227 public boolean isHmac() {
228 return name().startsWith("HS");
229 }
230
231 /**
232 * Returns {@code true} if the enum instance represents an RSA public/private key pair signature algorithm,
233 * {@code false} otherwise.
234 *
235 * @return {@code true} if the enum instance represents an RSA public/private key pair signature algorithm,
236 * {@code false} otherwise.
237 */
238 public boolean isRsa() {
239 return getDescription().startsWith("RSASSA");
240 }
241
242 /**
243 * Returns {@code true} if the enum instance represents an Elliptic Curve signature algorithm, {@code false}
244 * otherwise.
245 *
246 * @return {@code true} if the enum instance represents an Elliptic Curve signature algorithm, {@code false}
247 * otherwise.
248 */
249 public boolean isEllipticCurve() {
250 return name().startsWith("ES");
251 }
252
253 /**
254 * Looks up and returns the corresponding {@code SignatureAlgorithm} enum instance based on a
255 * case-<em>insensitive</em> name comparison.
256 *
257 * @param value The case-insensitive name of the {@code SignatureAlgorithm} instance to return
258 * @return the corresponding {@code SignatureAlgorithm} enum instance based on a
259 * case-<em>insensitive</em> name comparison.
260 * @throws SignatureException if the specified value does not match any {@code SignatureAlgorithm}
261 * name.
262 */
263 public static SignatureAlgorithm forName(String value) throws SignatureException {
264 for (SignatureAlgorithm alg : values()) {
265 if (alg.getValue().equalsIgnoreCase(value)) {
266 return alg;
267 }
268 }
269
270 throw new SignatureException("Unsupported signature algorithm '" + value + "'");
271 }
272 }
273