Skip to content

Commit 78a6434

Browse files
committed
[feat] try resolving curve-name from EC public key
1 parent a56fcb5 commit 78a6434

File tree

1 file changed

+33
-15
lines changed

1 file changed

+33
-15
lines changed

src/main/java/org/jruby/ext/openssl/PKeyEC.java

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.io.StringReader;
1212
import java.io.StringWriter;
1313
import java.math.BigInteger;
14+
import java.security.AlgorithmParameters;
1415
import java.security.GeneralSecurityException;
1516
import java.security.InvalidKeyException;
1617
import java.security.KeyFactory;
@@ -36,6 +37,7 @@
3637
import java.util.Collections;
3738
import java.util.Enumeration;
3839
import java.util.List;
40+
import java.util.Optional;
3941
import javax.crypto.KeyAgreement;
4042
import org.bouncycastle.asn1.ASN1EncodableVector;
4143
import org.bouncycastle.asn1.ASN1Encoding;
@@ -82,7 +84,6 @@
8284
import static org.jruby.ext.openssl.impl.PKey.readECPrivateKey;
8385
import org.jruby.ext.openssl.util.ByteArrayOutputStream;
8486
import org.jruby.ext.openssl.x509store.PEMInputOutput;
85-
import org.jruby.util.ByteList;
8687

8788
/**
8889
* OpenSSL::PKey::EC implementation.
@@ -170,24 +171,21 @@ public static RubyArray builtin_curves(ThreadContext context, IRubyObject self)
170171
return curves;
171172
}
172173

173-
private static ASN1ObjectIdentifier getCurveOID(final String curveName) {
174+
private static Optional<ASN1ObjectIdentifier> getCurveOID(final String curveName) {
174175
ASN1ObjectIdentifier id;
175176
id = org.bouncycastle.asn1.sec.SECNamedCurves.getOID(curveName);
176-
if ( id != null ) return id;
177+
if ( id != null ) return Optional.of(id);
177178
id = org.bouncycastle.asn1.x9.X962NamedCurves.getOID(curveName);
178-
if ( id != null ) return id;
179+
if ( id != null ) return Optional.of(id);
179180
id = org.bouncycastle.asn1.nist.NISTNamedCurves.getOID(curveName);
180-
if ( id != null ) return id;
181+
if ( id != null ) return Optional.of(id);
181182
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();
184185
}
185186

186187
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();
191189
}
192190

193191
private static String getCurveName(final ASN1ObjectIdentifier oid) {
@@ -365,14 +363,18 @@ else if ( key instanceof ECPrivateKey ) {
365363
setPrivateKey((ECPrivateKey) key);
366364
}
367365
else if ( key instanceof ECPublicKey ) {
368-
this.publicKey = (ECPublicKey) key; this.privateKey = null;
366+
this.publicKey = (ECPublicKey) key;
367+
this.privateKey = null;
369368
}
370369
else {
371370
throw newECError(runtime, "Neither PUB key nor PRIV key: " + key.getClass().getName());
372371
}
373372

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+
}
376378
}
377379

378380
return this;
@@ -391,6 +393,20 @@ private void unwrapPrivateKeyWithName() {
391393
}
392394
}
393395

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+
394410
private void setGroup(final Group group) {
395411
this.group = group;
396412
this.curveName = this.group.getCurveName();
@@ -806,7 +822,9 @@ public RubyString to_pem(final ThreadContext context, final IRubyObject[] args)
806822

807823
try {
808824
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);
810828
return RubyString.newString(context.runtime, writer.getBuffer());
811829
}
812830
catch (IOException ex) {

0 commit comments

Comments
 (0)