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