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.*;
024
025import com.nimbusds.jose.JWSAlgorithm;
026import net.jcip.annotations.Immutable;
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 2021-07-02
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                if (name == null) {
168                        throw new IllegalArgumentException("The JOSE cryptographic curve name must not be null");
169                }
170                
171                this.name = name;
172                
173                this.stdName = stdName;
174                
175                this.oid = oid;
176        }
177        
178        
179        /**
180         * Returns the JOSE name of this cryptographic curve.
181         *
182         * @return The JOSE name.
183         */
184        public String getName() {
185                
186                return name;
187        }
188        
189        
190        /**
191         * Returns the standard name of this cryptographic curve.
192         *
193         * @return The standard name, {@code null} if not specified.
194         */
195        public String getStdName() {
196                
197                return stdName;
198        }
199        
200        
201        /**
202         * Returns the standard object identifier (OID) of this cryptographic
203         * curve.
204         *
205         * @return The OID, {@code null} if not specified.
206         */
207        public String getOID() {
208                
209                return oid;
210        }
211        
212        
213        /**
214         * Returns the parameter specification for this cryptographic curve.
215         *
216         * @return The EC parameter specification, {@code null} if it cannot be
217         *         determined.
218         */
219        public ECParameterSpec toECParameterSpec() {
220                
221                return ECParameterTable.get(this);
222        }
223        
224        
225        /**
226         * @see #getName
227         */
228        @Override
229        public String toString() {
230                
231                return getName();
232        }
233        
234        
235        @Override
236        public boolean equals(final Object object) {
237                
238                return object instanceof Curve &&
239                        this.toString().equals(object.toString());
240        }
241        
242        
243        @Override
244        public int hashCode() {
245                return Objects.hash(getName());
246        }
247        
248        
249        /**
250         * Parses a cryptographic curve from the specified string.
251         *
252         * @param s The string to parse. Must not be {@code null} or empty.
253         *
254         * @return The cryptographic curve.
255         */
256        public static Curve parse(final String s) {
257                
258                if (s == null || s.trim().isEmpty()) {
259                        throw new IllegalArgumentException("The cryptographic curve string must not be null or empty");
260                }
261                
262                if (s.equals(P_256.getName())) {
263                        return P_256;
264                } else if (s.equals(P_256K.getName())) {
265                        return P_256K;
266                } else if (s.equals(SECP256K1.getName())) {
267                        return SECP256K1;
268                } else if (s.equals(P_384.getName())) {
269                        return P_384;
270                } else if (s.equals(P_521.getName())) {
271                        return P_521;
272                } else if (s.equals(Ed25519.getName())) {
273                        return Ed25519;
274                } else if (s.equals(Ed448.getName())) {
275                        return Ed448;
276                } else if (s.equals(X25519.getName())) {
277                        return X25519;
278                } else if (s.equals(X448.getName())) {
279                        return X448;
280                } else {
281                        return new Curve(s);
282                }
283        }
284        
285        
286        /**
287         * Gets the cryptographic curve for the specified standard
288         * name.
289         *
290         * @param stdName The standard curve name. May be {@code null}.
291         *
292         * @return The curve, {@code null} if it cannot be determined.
293         */
294        public static Curve forStdName(final String stdName) {
295                if( "secp256r1".equals(stdName) || "prime256v1".equals(stdName)) {
296                        return P_256;
297                } else if("secp256k1".equals(stdName)) {
298                        return SECP256K1;
299                } else if("secp384r1".equals(stdName)) {
300                        return P_384;
301                } else if("secp521r1".equals(stdName)) {
302                        return P_521;
303                } else if (Ed25519.getStdName().equals(stdName)) {
304                        return Ed25519;
305                } else if (Ed448.getStdName().equals(stdName)) {
306                        return Ed448;
307                } else if (X25519.getStdName().equals(stdName)) {
308                        return X25519;
309                } else if (X448.getStdName().equals(stdName)) {
310                        return X448;
311                } else {
312                        return null;
313                }
314        }
315        
316        
317        /**
318         * Gets the cryptographic curve for the specified object identifier
319         * (OID).
320         *
321         * @param oid The object OID. May be {@code null}.
322         *
323         * @return The curve, {@code null} if it cannot be determined.
324         */
325        public static Curve forOID(final String oid) {
326                
327                if (P_256.getOID().equals(oid)) {
328                        return P_256;
329                } else if (SECP256K1.getOID().equals(oid)) {
330                        return SECP256K1;
331                } else if (P_384.getOID().equals(oid)) {
332                        return P_384;
333                } else if (P_521.getOID().equals(oid)) {
334                        return P_521;
335                } else {
336                        return null;
337                }
338        }
339        
340        
341        /**
342         * Gets the cryptographic curve(s) for the specified JWS algorithm.
343         *
344         * @param alg The JWS algorithm. May be {@code null}.
345         *
346         * @return The curve(s), {@code null} if the JWS algorithm is not curve
347         *         based, or the JWS algorithm is not supported.
348         */
349        public static Set<Curve> forJWSAlgorithm(final JWSAlgorithm alg) {
350                
351                if (JWSAlgorithm.ES256.equals(alg)) {
352                        return Collections.singleton(P_256);
353                } else if (JWSAlgorithm.ES256K.equals(alg)) {
354                        return Collections.singleton(SECP256K1);
355                } else if (JWSAlgorithm.ES384.equals(alg)) {
356                        return Collections.singleton(P_384);
357                } else if (JWSAlgorithm.ES512.equals(alg)) {
358                        return Collections.singleton(P_521);
359                } else if (JWSAlgorithm.EdDSA.equals(alg)) {
360                        return Collections.unmodifiableSet(
361                                new HashSet<>(Arrays.asList(
362                                        Ed25519,
363                                        Ed448
364                                ))
365                        );
366                } else {
367                        return null;
368                }
369        }
370        
371        
372        /**
373         * Gets the cryptographic curve for the specified parameter
374         * specification.
375         *
376         * @param spec The EC parameter spec. May be {@code null}.
377         *
378         * @return The curve, {@code null} if it cannot be determined.
379         */
380        public static Curve forECParameterSpec(final ECParameterSpec spec) {
381                
382                return ECParameterTable.get(spec);
383        }
384}