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"nullfalse),
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 trueif the algorithm is supported by standard JDK distributions or {@code falseif 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 trueif the algorithm is supported by standard JDK distributions or {@code falseif 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 trueif the enum instance represents an HMAC signature algorithm, {@code false} otherwise.
224      *
225      * @return {@code trueif 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 trueif the enum instance represents an RSA public/private key pair signature algorithm,
233      * {@code false} otherwise.
234      *
235      * @return {@code trueif 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 trueif the enum instance represents an Elliptic Curve signature algorithm, {@code false}
244      * otherwise.
245      *
246      * @return {@code trueif 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