11
11
import java .io .StringReader ;
12
12
import java .io .StringWriter ;
13
13
import java .math .BigInteger ;
14
+ import java .security .AlgorithmParameters ;
14
15
import java .security .GeneralSecurityException ;
15
16
import java .security .InvalidKeyException ;
16
17
import java .security .KeyFactory ;
36
37
import java .util .Collections ;
37
38
import java .util .Enumeration ;
38
39
import java .util .List ;
40
+ import java .util .Optional ;
39
41
import javax .crypto .KeyAgreement ;
40
42
import org .bouncycastle .asn1 .ASN1EncodableVector ;
41
43
import org .bouncycastle .asn1 .ASN1Encoding ;
82
84
import static org .jruby .ext .openssl .impl .PKey .readECPrivateKey ;
83
85
import org .jruby .ext .openssl .util .ByteArrayOutputStream ;
84
86
import org .jruby .ext .openssl .x509store .PEMInputOutput ;
85
- import org .jruby .util .ByteList ;
86
87
87
88
/**
88
89
* OpenSSL::PKey::EC implementation.
@@ -170,24 +171,21 @@ public static RubyArray builtin_curves(ThreadContext context, IRubyObject self)
170
171
return curves ;
171
172
}
172
173
173
- private static ASN1ObjectIdentifier getCurveOID (final String curveName ) {
174
+ private static Optional < ASN1ObjectIdentifier > getCurveOID (final String curveName ) {
174
175
ASN1ObjectIdentifier id ;
175
176
id = org .bouncycastle .asn1 .sec .SECNamedCurves .getOID (curveName );
176
- if ( id != null ) return id ;
177
+ if ( id != null ) return Optional . of ( id ) ;
177
178
id = org .bouncycastle .asn1 .x9 .X962NamedCurves .getOID (curveName );
178
- if ( id != null ) return id ;
179
+ if ( id != null ) return Optional . of ( id ) ;
179
180
id = org .bouncycastle .asn1 .nist .NISTNamedCurves .getOID (curveName );
180
- if ( id != null ) return id ;
181
+ if ( id != null ) return Optional . of ( id ) ;
181
182
id = org .bouncycastle .asn1 .teletrust .TeleTrusTNamedCurves .getOID (curveName );
182
- if ( id != null ) return id ;
183
- throw new IllegalStateException ( "could not identify curve name: " + curveName );
183
+ if ( id != null ) return Optional . of ( id ) ;
184
+ return Optional . empty ( );
184
185
}
185
186
186
187
private static boolean isCurveName (final String curveName ) {
187
- try {
188
- return getCurveOID (curveName ) != null ;
189
- }
190
- catch (IllegalStateException ex ) { return false ; }
188
+ return getCurveOID (curveName ).isPresent ();
191
189
}
192
190
193
191
private static String getCurveName (final ASN1ObjectIdentifier oid ) {
@@ -365,14 +363,18 @@ else if ( key instanceof ECPrivateKey ) {
365
363
setPrivateKey ((ECPrivateKey ) key );
366
364
}
367
365
else if ( key instanceof ECPublicKey ) {
368
- this .publicKey = (ECPublicKey ) key ; this .privateKey = null ;
366
+ this .publicKey = (ECPublicKey ) key ;
367
+ this .privateKey = null ;
369
368
}
370
369
else {
371
370
throw newECError (runtime , "Neither PUB key nor PRIV key: " + key .getClass ().getName ());
372
371
}
373
372
374
- if ( publicKey != null ) {
375
- publicKey .getParams ().getCurve ();
373
+ if ( curveName == null && publicKey != null ) {
374
+ final String oid = getCurveNameObjectIdFromKey (context , publicKey );
375
+ if (isCurveName (oid )) {
376
+ this .curveName = getCurveName (new ASN1ObjectIdentifier (oid ));
377
+ }
376
378
}
377
379
378
380
return this ;
@@ -391,6 +393,20 @@ private void unwrapPrivateKeyWithName() {
391
393
}
392
394
}
393
395
396
+ private static String getCurveNameObjectIdFromKey (final ThreadContext context , final ECPublicKey key ) {
397
+ try {
398
+ AlgorithmParameters algParams = AlgorithmParameters .getInstance ("EC" );
399
+ algParams .init (key .getParams ());
400
+ return algParams .getParameterSpec (ECGenParameterSpec .class ).getName ();
401
+ }
402
+ catch (NoSuchAlgorithmException |InvalidParameterSpecException ex ) {
403
+ throw newECError (context .runtime , ex .getMessage ());
404
+ }
405
+ catch (Exception ex ) {
406
+ throw (RaiseException ) newECError (context .runtime , ex .toString ()).initCause (ex );
407
+ }
408
+ }
409
+
394
410
private void setGroup (final Group group ) {
395
411
this .group = group ;
396
412
this .curveName = this .group .getCurveName ();
@@ -806,7 +822,9 @@ public RubyString to_pem(final ThreadContext context, final IRubyObject[] args)
806
822
807
823
try {
808
824
final StringWriter writer = new StringWriter ();
809
- PEMInputOutput .writeECParameters (writer , getCurveOID (getCurveName ()), spec , passwd );
825
+ final ASN1ObjectIdentifier oid = getCurveOID (getCurveName ())
826
+ .orElseThrow (() -> newECError (context .runtime , "invalid curve name: " + getCurveName ()));
827
+ PEMInputOutput .writeECParameters (writer , oid , spec , passwd );
810
828
return RubyString .newString (context .runtime , writer .getBuffer ());
811
829
}
812
830
catch (IOException ex ) {
0 commit comments