2525import java .io .StreamCorruptedException ;
2626import java .io .UncheckedIOException ;
2727import java .math .BigInteger ;
28+ import java .security .AlgorithmParameters ;
29+ import java .security .GeneralSecurityException ;
2830import java .security .interfaces .ECKey ;
2931import java .security .spec .ECField ;
30- import java .security .spec .ECFieldFp ;
32+ import java .security .spec .ECGenParameterSpec ;
3133import java .security .spec .ECParameterSpec ;
3234import java .security .spec .ECPoint ;
3335import java .security .spec .EllipticCurve ;
4345import org .apache .sshd .common .NamedResource ;
4446import org .apache .sshd .common .OptionalFeature ;
4547import org .apache .sshd .common .config .keys .KeyEntryResolver ;
48+ import org .apache .sshd .common .config .keys .KeyUtils ;
4649import org .apache .sshd .common .digest .BuiltinDigests ;
4750import org .apache .sshd .common .digest .Digest ;
4851import org .apache .sshd .common .digest .DigestFactory ;
5962 * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
6063 */
6164public enum ECCurves implements KeyTypeIndicator , KeySizeIndicator , NamedResource , OptionalFeature {
62- nistp256 (Constants .NISTP256 , new int [] { 1 , 2 , 840 , 10045 , 3 , 1 , 7 },
63- new ECParameterSpec (
64- new EllipticCurve (
65- new ECFieldFp (
66- new BigInteger ("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF" , 16 )),
67- new BigInteger ("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC" , 16 ),
68- new BigInteger ("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b" , 16 )),
69- new ECPoint (
70- new BigInteger ("6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" , 16 ),
71- new BigInteger ("4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5" , 16 )),
72- new BigInteger ("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551" , 16 ),
73- 1 ),
74- 32 ,
75- BuiltinDigests .sha256 ),
76- nistp384 (Constants .NISTP384 , new int [] { 1 , 3 , 132 , 0 , 34 },
77- new ECParameterSpec (
78- new EllipticCurve (
79- new ECFieldFp (
80- new BigInteger (
81- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF" ,
82- 16 )),
83- new BigInteger (
84- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC" ,
85- 16 ),
86- new BigInteger (
87- "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF" ,
88- 16 )),
89- new ECPoint (
90- new BigInteger (
91- "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7" ,
92- 16 ),
93- new BigInteger (
94- "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F" ,
95- 16 )),
96- new BigInteger (
97- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973" ,
98- 16 ),
99- 1 ),
100- 48 ,
101- BuiltinDigests .sha384 ),
102- nistp521 (Constants .NISTP521 , new int [] { 1 , 3 , 132 , 0 , 35 },
103- new ECParameterSpec (
104- new EllipticCurve (
105- new ECFieldFp (
106- new BigInteger (
107- "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
108- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" ,
109- 16 )),
110- new BigInteger (
111- "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
112- + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC" ,
113- 16 ),
114- new BigInteger (
115- "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951"
116- + "EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00" ,
117- 16 )),
118- new ECPoint (
119- new BigInteger (
120- "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77"
121- + "EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66" ,
122- 16 ),
123- new BigInteger (
124- "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE7299"
125- + "5EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650" ,
126- 16 )),
127- new BigInteger (
128- "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B"
129- + "7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409" ,
130- 16 ),
131- 1 ),
132- 66 ,
133- BuiltinDigests .sha512 );
65+
66+ // See RFC 5656: https://datatracker.ietf.org/doc/html/rfc5656#section-10.1
67+ nistp256 (Constants .NISTP256 , "secp256r1" , new int [] { 1 , 2 , 840 , 10045 , 3 , 1 , 7 }, 32 , BuiltinDigests .sha256 ),
68+ nistp384 (Constants .NISTP384 , "secp384r1" , new int [] { 1 , 3 , 132 , 0 , 34 }, 48 , BuiltinDigests .sha384 ),
69+ nistp521 (Constants .NISTP521 , "secp521r1" , new int [] { 1 , 3 , 132 , 0 , 35 }, 66 , BuiltinDigests .sha512 );
13470
13571 /**
13672 * A {@link Set} of all the known curves
@@ -160,25 +96,41 @@ public enum ECCurves implements KeyTypeIndicator, KeySizeIndicator, NamedResourc
16096 .collect (Collectors .toList ()));
16197
16298 private final String name ;
99+ private final String secName ;
163100 private final String keyType ;
164101 private final String oidString ;
165102 private final List <Integer > oidValue ;
166- private final ECParameterSpec params ;
167- private final int keySize ;
103+ private ECParameterSpec params ;
104+ private volatile int keySize = - 1 ;
168105 private final int numOctets ;
169106 private final DigestFactory digestFactory ;
170107
171- ECCurves (String name , int [] oid , ECParameterSpec params , int numOctets , DigestFactory digestFactory ) {
108+ ECCurves (String name , String secName , int [] oid , int numOctets , DigestFactory digestFactory ) {
172109 this .name = ValidateUtils .checkNotNullAndNotEmpty (name , "No curve name" );
110+ this .secName = ValidateUtils .checkNotNullAndNotEmpty (secName , "No SEC curve name" );
173111 this .oidString = NumberUtils .join ('.' , ValidateUtils .checkNotNullAndNotEmpty (oid , "No OID" ));
174112 this .oidValue = Collections .unmodifiableList (NumberUtils .asList (oid ));
175113 this .keyType = Constants .ECDSA_SHA2_PREFIX + name ;
176- this .params = ValidateUtils .checkNotNull (params , "No EC params for %s" , name );
177- this .keySize = getCurveSize (params );
178114 this .numOctets = numOctets ;
179115 this .digestFactory = Objects .requireNonNull (digestFactory , "No digestFactory" );
180116 }
181117
118+ private ECParameterSpec getParams (String secName ) {
119+ try {
120+ AlgorithmParameters paramsFactory = SecurityUtils .getAlgorithmParameters (KeyUtils .EC_ALGORITHM );
121+ // Although ECGenParameterSpec exists since Java 1.5 the parameter names were documented only in Java 14
122+ // with JDK-8210755. But the names were available all the time and are also supported in Bouncy Castle.
123+ //
124+ // Note that the names must not be the NIST names but the SEC names.
125+ //
126+ // See also https://www.secg.org/sec2-v2.pdf for the name definitions and the exact numerical parameters.
127+ paramsFactory .init (new ECGenParameterSpec (secName ));
128+ return paramsFactory .getParameterSpec (ECParameterSpec .class );
129+ } catch (GeneralSecurityException e ) {
130+ return null ;
131+ }
132+ }
133+
182134 @ Override // The curve's standard name
183135 public final String getName () {
184136 return name ;
@@ -203,12 +155,22 @@ public final boolean isSupported() {
203155 }
204156
205157 public final ECParameterSpec getParameters () {
206- return params ;
158+ synchronized (this ) {
159+ if (params == null ) {
160+ params = ValidateUtils .checkNotNull (getParams (secName ), "No EC params for %s" , name );
161+ }
162+ return params ;
163+ }
207164 }
208165
209166 @ Override
210167 public final int getKeySize () {
211- return keySize ;
168+ int sz = keySize ;
169+ if (sz < 0 ) {
170+ sz = getCurveSize (getParameters ());
171+ keySize = sz ;
172+ }
173+ return sz ;
212174 }
213175
214176 /**
0 commit comments