Skip to content

Commit 5315832

Browse files
committed
[fix] make sure PKeyEC#group.curve_name is always set
1 parent 6af9858 commit 5315832

File tree

2 files changed

+25
-15
lines changed

2 files changed

+25
-15
lines changed

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

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ public PKeyEC(Ruby runtime, RubyClass type) {
202202
setPrivateKey((ECPrivateKey) privKey);
203203
} else {
204204
this.privateKey = privKey;
205+
setCurveNameFromPublicKeyIfNeeded();
205206
}
206207
}
207208

@@ -353,14 +354,18 @@ else if ( key instanceof ECPublicKey ) {
353354
throw newECError(runtime, "Neither PUB key nor PRIV key: ");
354355
}
355356

356-
if ( curveName == null && publicKey != null ) {
357-
final String oid = getCurveNameObjectIdFromKey(context, publicKey);
357+
setCurveNameFromPublicKeyIfNeeded();
358+
359+
return this;
360+
}
361+
362+
private void setCurveNameFromPublicKeyIfNeeded() {
363+
if (curveName == null && publicKey != null) {
364+
final String oid = getCurveNameObjectIdFromKey(getRuntime(), publicKey);
358365
if (isCurveName(oid)) {
359366
this.curveName = getCurveName(new ASN1ObjectIdentifier(oid));
360367
}
361368
}
362-
363-
return this;
364369
}
365370

366371
void setPrivateKey(final ECPrivateKey key) {
@@ -376,17 +381,17 @@ private void unwrapPrivateKeyWithName() {
376381
}
377382
}
378383

379-
private static String getCurveNameObjectIdFromKey(final ThreadContext context, final ECPublicKey key) {
384+
private static String getCurveNameObjectIdFromKey(final Ruby runtime, final ECPublicKey key) {
380385
try {
381386
AlgorithmParameters algParams = AlgorithmParameters.getInstance("EC");
382387
algParams.init(key.getParams());
383388
return algParams.getParameterSpec(ECGenParameterSpec.class).getName();
384389
}
385390
catch (NoSuchAlgorithmException|InvalidParameterSpecException ex) {
386-
throw newECError(context.runtime, ex.getMessage());
391+
throw newECError(runtime, ex.getMessage());
387392
}
388393
catch (Exception ex) {
389-
throw (RaiseException) newECError(context.runtime, ex.toString()).initCause(ex);
394+
throw (RaiseException) newECError(runtime, ex.toString()).initCause(ex);
390395
}
391396
}
392397

@@ -535,10 +540,7 @@ public IRubyObject oid() {
535540

536541
private Group getGroup(boolean required) {
537542
if (group == null) {
538-
if (publicKey != null) {
539-
return group = new Group(getRuntime(), this);
540-
}
541-
if (required) throw new IllegalStateException("no group (without public key)");
543+
return group = new Group(getRuntime(), this);
542544
}
543545
return group;
544546
}
@@ -748,7 +750,6 @@ public Group(Ruby runtime, RubyClass type) {
748750
Group(Ruby runtime, PKeyEC key) {
749751
this(runtime, _EC(runtime).getClass("Group"));
750752
this.key = key;
751-
this.paramSpec = key.publicKey.getParams();
752753
}
753754

754755
@JRubyMethod(rest = true, visibility = Visibility.PRIVATE)
@@ -759,8 +760,7 @@ public IRubyObject initialize(final ThreadContext context, final IRubyObject[] a
759760
IRubyObject arg = args[0];
760761

761762
if ( arg instanceof Group ) {
762-
IRubyObject curve_name = ((Group) arg).curve_name(context);
763-
this.curve_name = curve_name.isNil() ? null : (RubyString) curve_name;
763+
this.curve_name = ((Group) arg).implCurveName(runtime);
764764
return this;
765765
}
766766

@@ -771,6 +771,7 @@ public IRubyObject initialize(final ThreadContext context, final IRubyObject[] a
771771

772772
private String getCurveName() {
773773
if (key != null) return key.getCurveName();
774+
assert curve_name != null;
774775
return curve_name.toString();
775776
}
776777

@@ -792,6 +793,7 @@ public IRubyObject curve_name(final ThreadContext context) {
792793

793794
private RubyString implCurveName(final Ruby runtime) {
794795
if (curve_name == null) {
796+
assert key != null;
795797
String prefix, curveName = key.getCurveName();
796798
// BC 1.54: "brainpoolP512t1" 1.55: "brainpoolp512t1"
797799
if (curveName.startsWith(prefix = "brainpoolp")) {
@@ -854,7 +856,11 @@ public RubyString to_pem(final ThreadContext context, final IRubyObject[] args)
854856

855857
private ECParameterSpec getParamSpec() {
856858
if (paramSpec == null) {
857-
paramSpec = PKeyEC.getParamSpec(getCurveName());
859+
if (key != null) {
860+
return paramSpec = key.getParamSpec();
861+
}
862+
assert curve_name != null;
863+
return paramSpec = PKeyEC.getParamSpec(getCurveName());
858864
}
859865
return paramSpec;
860866
}

src/test/ruby/test_pkey.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def test_read_files
2424
key = OpenSSL::PKey.read(File.read(File.join(custom_fixtures_path, 'ec256k-private.pem')))
2525
assert_equal OpenSSL::PKey::EC, key.class
2626
assert key.private_key?
27+
assert_equal 'secp256k1', key.group.curve_name
2728

2829
key = OpenSSL::PKey.read(File.read(File.join(custom_fixtures_path, 'ec256k-public.pem')))
2930
assert_equal OpenSSL::PKey::EC, key.class
@@ -32,14 +33,17 @@ def test_read_files
3233
key = OpenSSL::PKey.read(File.read(File.join(custom_fixtures_path, 'ec256-public-v2.pem')))
3334
assert_equal OpenSSL::PKey::EC, key.class
3435
assert key.public_key?
36+
assert_equal 'prime256v1', key.group.curve_name
3537

3638
key = OpenSSL::PKey.read(File.read(File.join(custom_fixtures_path, 'ec512-private.pem')))
3739
assert_equal OpenSSL::PKey::EC, key.class
3840
assert key.private_key?
41+
assert_equal 'secp521r1', key.group.curve_name
3942

4043
key = OpenSSL::PKey.read(File.read(File.join(custom_fixtures_path, 'ec512-public.pem')))
4144
assert_equal OpenSSL::PKey::EC, key.class
4245
assert key.public_key?
46+
assert_equal 'secp521r1', key.group.curve_name
4347

4448
key = OpenSSL::PKey.read(File.read(File.join(custom_fixtures_path, 'rsa-2048-private.pem')))
4549
assert_equal OpenSSL::PKey::RSA, key.class

0 commit comments

Comments
 (0)