001/*
002 * nimbus-jose-jwt
003 *
004 * Copyright 2012-2016, Connect2id Ltd and contributors.
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;
022import java.security.spec.ECParameterSpec;
023import java.util.Arrays;
024import java.util.Collections;
025import java.util.HashSet;
026import java.util.Set;
027
028import com.nimbusds.jose.JWSAlgorithm;
029import net.jcip.annotations.Immutable;
030
031
032/**
033 * Cryptographic curve. This class is immutable.
034 *
035 * <p>Includes constants for the following standard cryptographic curves:
036 *
037 * <ul>
038 *     <li>{@link #P_256}
039 *     <li>{@link #P_384}
040 *     <li>{@link #P_521}
041 *     <li>{@link #Ed25519}
042 *     <li>{@link #Ed448}
043 *     <li>{@link #X25519}
044 *     <li>{@link #X448}
045 * </ul>
046 *
047 * <p>See
048 *
049 * <ul>
050 *     <li>"Digital Signature Standard (DSS)", FIPS PUB 186-3, June 2009,
051 *         National Institute of Standards and Technology (NIST).
052 *     <li>CFRG Elliptic Curve Diffie-Hellman (ECDH) and Signatures in JSON
053 *         Object Signing and Encryption (JOSE) (RFC 8037).
054 * </ul>
055 *
056 * @author Vladimir Dzhuvinov
057 * @version 2018-08-23
058 */
059@Immutable
060public final class Curve implements Serializable {
061        
062        
063        private static final long serialVersionUID = 1L;
064        
065        
066        /**
067         * P-256 curve (secp256r1, also called prime256v1, OID =
068         * 1.2.840.10045.3.1.7).
069         */
070        public static final Curve P_256 = new Curve("P-256", "secp256r1", "1.2.840.10045.3.1.7");
071        
072        
073        /**
074         * P-384 curve (secp384r1, OID = 1.3.132.0.34).
075         */
076        public static final Curve P_384 = new Curve("P-384", "secp384r1", "1.3.132.0.34");
077        
078        
079        /**
080         * P-521 curve (secp521r1).
081         */
082        public static final Curve P_521 = new Curve("P-521", "secp521r1", "1.3.132.0.35");
083        
084        
085        /**
086         * Ed25519 signature algorithm key pairs.
087         */
088        public static final Curve Ed25519 = new Curve("Ed25519", "Ed25519", null);
089        
090        
091        /**
092         * Ed448 signature algorithm key pairs.
093         */
094        public static final Curve Ed448 = new Curve("Ed448", "Ed448", null);
095        
096        
097        /**
098         * X25519 function key pairs.
099         */
100        public static final Curve X25519 = new Curve("X25519", "X25519", null);
101        
102        
103        /**
104         * X448 function key pairs.
105         */
106        public static final Curve X448 = new Curve("X448", "X448", null);
107        
108        
109        /**
110         * The JOSE curve name.
111         */
112        private final String name;
113        
114        
115        /**
116         * The standard curve name, {@code null} if not specified.
117         */
118        private final String stdName;
119        
120        
121        /**
122         * The standard object identifier for the curve, {@code null}
123         * if not specified.
124         */
125        private final String oid;
126        
127        
128        /**
129         * Creates a new cryptographic curve with the specified JOSE name. A
130         * standard curve name and object identifier (OID) are not unspecified.
131         *
132         * @param name The JOSE name of the cryptographic curve. Must not be
133         *             {@code null}.
134         */
135        public Curve(final String name) {
136                
137                this(name, null, null);
138        }
139        
140        
141        /**
142         * Creates a new cryptographic curve with the specified JOSE name,
143         * standard name and object identifier (OID).
144         *
145         * @param name    The JOSE name of the cryptographic curve. Must not
146         *                be {@code null}.
147         * @param stdName The standard name of the cryptographic curve,
148         *                {@code null} if not specified.
149         * @param oid     The object identifier (OID) of the cryptographic
150         *                curve, {@code null} if not specified.
151         */
152        public Curve(final String name, final String stdName, final String oid) {
153                
154                if (name == null) {
155                        throw new IllegalArgumentException("The JOSE cryptographic curve name must not be null");
156                }
157                
158                this.name = name;
159                
160                this.stdName = stdName;
161                
162                this.oid = oid;
163        }
164        
165        
166        /**
167         * Returns the JOSE name of this cryptographic curve.
168         *
169         * @return The JOSE name.
170         */
171        public String getName() {
172                
173                return name;
174        }
175        
176        
177        /**
178         * Returns the standard name of this cryptographic curve.
179         *
180         * @return The standard name, {@code null} if not specified.
181         */
182        public String getStdName() {
183                
184                return stdName;
185        }
186        
187        
188        /**
189         * Returns the standard object identifier (OID) of this cryptographic
190         * curve.
191         *
192         * @return The OID, {@code null} if not specified.
193         */
194        public String getOID() {
195                
196                return oid;
197        }
198        
199        
200        /**
201         * Returns the parameter specification for this cryptographic curve.
202         *
203         * @return The EC parameter specification, {@code null} if it cannot be
204         *         determined.
205         */
206        public ECParameterSpec toECParameterSpec() {
207                
208                return ECParameterTable.get(this);
209        }
210        
211        
212        /**
213         * @see #getName
214         */
215        @Override
216        public String toString() {
217                
218                return getName();
219        }
220        
221        
222        @Override
223        public boolean equals(final Object object) {
224                
225                return object instanceof Curve &&
226                        this.toString().equals(object.toString());
227        }
228        
229        
230        /**
231         * Parses a cryptographic curve from the specified string.
232         *
233         * @param s The string to parse. Must not be {@code null} or empty.
234         *
235         * @return The cryptographic curve.
236         */
237        public static Curve parse(final String s) {
238                
239                if (s == null || s.trim().isEmpty()) {
240                        throw new IllegalArgumentException("The cryptographic curve string must not be null or empty");
241                }
242                
243                if (s.equals(P_256.getName())) {
244                        return P_256;
245                } else if (s.equals(P_384.getName())) {
246                        return P_384;
247                } else if (s.equals(P_521.getName())) {
248                        return P_521;
249                } else if (s.equals(Ed25519.getName())) {
250                        return Ed25519;
251                } else if (s.equals(Ed448.getName())) {
252                        return Ed448;
253                } else if (s.equals(X25519.getName())) {
254                        return X25519;
255                } else if (s.equals(X448.getName())) {
256                        return X448;
257                } else {
258                        return new Curve(s);
259                }
260        }
261        
262        
263        /**
264         * Gets the cryptographic curve for the specified standard
265         * name.
266         *
267         * @param stdName The standard curve name. May be {@code null}.
268         *
269         * @return The curve, {@code null} if it cannot be determined.
270         */
271        public static Curve forStdName(final String stdName) {
272                if( "secp256r1".equals(stdName) || "prime256v1".equals(stdName)) {
273                        return P_256;
274                } else if("secp384r1".equals(stdName)) {
275                        return P_384;
276                } else if("secp521r1".equals(stdName)) {
277                        return P_521;
278                } else if (Ed25519.getStdName().equals(stdName)) {
279                        return Ed25519;
280                } else if (Ed448.getStdName().equals(stdName)) {
281                        return Ed448;
282                } else if (X25519.getStdName().equals(stdName)) {
283                        return X25519;
284                } else if (X448.getStdName().equals(stdName)) {
285                        return X448;
286                } else {
287                        return null;
288                }
289        }
290        
291        
292        /**
293         * Gets the cryptographic curve for the specified object identifier
294         * (OID).
295         *
296         * @param oid The object OID. May be {@code null}.
297         *
298         * @return The curve, {@code null} if it cannot be determined.
299         */
300        public static Curve forOID(final String oid) {
301                
302                if (P_256.getOID().equals(oid)) {
303                        return P_256;
304                } else if (P_384.getOID().equals(oid)) {
305                        return P_384;
306                } else if (P_521.getOID().equals(oid)) {
307                        return P_521;
308                } else {
309                        return null;
310                }
311        }
312        
313        
314        /**
315         * Gets the cryptographic curve(s) for the specified JWS algorithm.
316         *
317         * @param alg The JWS algorithm. May be {@code null}.
318         *
319         * @return The curve(s), {@code null} if the JWS algorithm is not curve
320         *         based, or the JWS algorithm is not supported.
321         */
322        public static Set<Curve> forJWSAlgorithm(final JWSAlgorithm alg) {
323                
324                if (JWSAlgorithm.ES256.equals(alg)) {
325                        return Collections.singleton(P_256);
326                } else if (JWSAlgorithm.ES384.equals(alg)) {
327                        return Collections.singleton(P_384);
328                } else if (JWSAlgorithm.ES512.equals(alg)) {
329                        return Collections.singleton(P_521);
330                } else if (JWSAlgorithm.EdDSA.equals(alg)) {
331                        return Collections.unmodifiableSet(
332                                new HashSet<>(Arrays.asList(
333                                        Ed25519,
334                                        Ed448
335                                ))
336                        );
337                } else {
338                        return null;
339                }
340        }
341        
342        
343        /**
344         * Gets the cryptographic curve for the specified parameter
345         * specification.
346         *
347         * @param spec The EC parameter spec. May be {@code null}.
348         *
349         * @return The curve, {@code null} if it cannot be determined.
350         */
351        public static Curve forECParameterSpec(final ECParameterSpec spec) {
352                
353                return ECParameterTable.get(spec);
354        }
355}