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