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