From aa1db883029558ddec076d003208f8b4fc615d48 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Thu, 6 Jun 2024 11:47:54 -0500 Subject: [PATCH 1/6] Arity-split Point#initialize --- .../java/org/jruby/ext/openssl/PKeyEC.java | 75 ++++++++++++------- 1 file changed, 49 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/jruby/ext/openssl/PKeyEC.java b/src/main/java/org/jruby/ext/openssl/PKeyEC.java index 21d9733d..47668444 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyEC.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyEC.java @@ -931,44 +931,53 @@ private static RaiseException newError(final Ruby runtime, final String message) return Utils.newError(runtime, Error, message); } - @JRubyMethod(rest = true, visibility = Visibility.PRIVATE) - public IRubyObject initialize(final ThreadContext context, final IRubyObject[] args) { - final Ruby runtime = context.runtime; + @JRubyMethod(visibility = Visibility.PRIVATE) + public IRubyObject initialize(final ThreadContext context, final IRubyObject groupOrPoint) { + getPointAndGroup(context, groupOrPoint); - final int argc = Arity.checkArgumentCount(runtime, args, 1, 2); - final IRubyObject arg = args[0]; + return this; + } - if ( arg instanceof Point ) { - this.group = ((Point) arg).group; - this.point = ((Point) arg).point; + @JRubyMethod(visibility = Visibility.PRIVATE) + public IRubyObject initialize(final ThreadContext context, final IRubyObject groupOrPoint, final IRubyObject bn) { + if (getPointAndGroup(context, groupOrPoint)) { return this; } - if ( arg instanceof Group ) { - this.group = (Group) arg; + final byte[] encoded; + if (bn instanceof BN) { + encoded = ((BN) bn).getValue().abs().toByteArray(); } else { - throw runtime.newTypeError(arg, _EC(runtime).getClass("Group")); + encoded = bn.convertToString().getBytes(); } - - if ( argc == 2 ) { // (group, bn) - final byte[] encoded; - if (args[1] instanceof BN) { - encoded = ((BN) args[1]).getValue().abs().toByteArray(); - } else { - encoded = args[1].convertToString().getBytes(); - } - try { - this.point = ECPointUtil.decodePoint(group.getCurve(), encoded); - } - catch (IllegalArgumentException ex) { - // MRI: OpenSSL::PKey::EC::Point::Error: invalid encoding - throw newError(context.runtime, ex.getMessage()); - } + try { + this.point = ECPointUtil.decodePoint(group.getCurve(), encoded); + } + catch (IllegalArgumentException ex) { + // MRI: OpenSSL::PKey::EC::Point::Error: invalid encoding + throw newError(context.runtime, ex.getMessage()); } return this; } + private boolean getPointAndGroup(ThreadContext context, IRubyObject groupOrPoint) { + final Ruby runtime = context.runtime; + + if ( groupOrPoint instanceof Point) { + this.group = ((Point) groupOrPoint).group; + this.point = ((Point) groupOrPoint).point; + return true; + } + + if ( groupOrPoint instanceof Group) { + this.group = (Group) groupOrPoint; + } else { + throw runtime.newTypeError(groupOrPoint, _EC(runtime).getClass("Group")); + } + return false; + } + @Override @JRubyMethod(name = { "==", "eql?" }) public IRubyObject op_equal(final ThreadContext context, final IRubyObject obj) { @@ -1059,6 +1068,20 @@ public IRubyObject inspect() { return ObjectSupport.inspect(this, (List) Collections.singletonList(entry)); } + @Deprecated + public IRubyObject initialize(final ThreadContext context, final IRubyObject[] args) { + final int argc = Arity.checkArgumentCount(context.runtime, args, 1, 2); + + switch (argc) { + case 1: + return initialize(context, args[0]); + case 2: + return initialize(context, args[0], args[1]); + default: + throw context.runtime.newArgumentError(args.length, 1); + } + } + } static byte[] encode(final ECPublicKey pubKey) { From 9c100aae0c91a2b01a856c456e34e36ab0a3bea5 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Tue, 11 Jun 2024 10:13:04 -0500 Subject: [PATCH 2/6] Implement Point#mul --- .../java/org/jruby/ext/openssl/PKeyEC.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/main/java/org/jruby/ext/openssl/PKeyEC.java b/src/main/java/org/jruby/ext/openssl/PKeyEC.java index 47668444..3294a858 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyEC.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyEC.java @@ -58,10 +58,14 @@ import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.jce.spec.ECNamedCurveSpec; +import org.bouncycastle.math.ec.ECAlgorithms; +import org.bouncycastle.math.ec.ECCurve; import org.jruby.Ruby; import org.jruby.RubyArray; +import org.jruby.RubyBignum; import org.jruby.RubyBoolean; import org.jruby.RubyClass; +import org.jruby.RubyFixnum; import org.jruby.RubyModule; import org.jruby.RubyObject; import org.jruby.RubyString; @@ -972,6 +976,7 @@ private boolean getPointAndGroup(ThreadContext context, IRubyObject groupOrPoint if ( groupOrPoint instanceof Group) { this.group = (Group) groupOrPoint; + this.point = (ECPoint) ((Group) groupOrPoint).generator(context); } else { throw runtime.newTypeError(groupOrPoint, _EC(runtime).getClass("Group")); } @@ -1068,6 +1073,76 @@ public IRubyObject inspect() { return ObjectSupport.inspect(this, (List) Collections.singletonList(entry)); } + @JRubyMethod(name = "mul", required = 1, optional = 2) + public IRubyObject mul(final ThreadContext context, final IRubyObject[] args) { + Ruby runtime = context.runtime; + + org.bouncycastle.math.ec.ECPoint pointSelf, pointResult; + + Group groupV = this.group; + + Point result; + + BigInteger bn_g = null; + + ECCurve selfCurve = EC5Util.convertCurve(group.getCurve()); + pointSelf = EC5Util.convertPoint(selfCurve, asECPoint()); + + result = new Point(runtime, getMetaClass()); + result.initialize(context, groupV); + ECCurve resultCurve = EC5Util.convertCurve(result.group.getCurve()); + pointResult = EC5Util.convertPoint(resultCurve, result.point); + + int argc = Arity.checkArgumentCount(runtime, args, 1, 3); + IRubyObject arg1 = null, arg2 = null; + switch (argc) { + case 2: + arg2 = args[1]; + case 1: + arg1 = args[0]; + } + if (!(arg1 instanceof RubyArray)) { + BigInteger bn; + if (arg1 instanceof RubyFixnum) { + bn = BigInteger.valueOf(arg1.convertToInteger().getLongValue()); + } else if (arg1 instanceof RubyBignum) { + bn = ((RubyBignum) arg1).getValue(); + } else if (arg1 instanceof BN) { + bn = ((BN) arg1).getValue(); + } else { + throw runtime.newTypeError(arg1, runtime.getInteger()); + } + + if (arg2 != null) { + if (arg2 instanceof RubyFixnum) { + bn_g = BigInteger.valueOf(arg2.convertToInteger().getLongValue()); + } else if (arg2 instanceof RubyBignum) { + bn_g = ((RubyBignum) arg2).getValue(); + } else if (arg2 instanceof BN) { + bn_g = ((BN) arg2).getValue(); + } else { + throw runtime.newTypeError(arg2, runtime.getInteger()); + } + } + + if (bn_g == null) { + org.bouncycastle.math.ec.ECPoint mulPoint = ECAlgorithms.referenceMultiply(pointSelf, bn); + result = new Point(runtime, EC5Util.convertPoint(mulPoint), result.group); + } else { + org.bouncycastle.math.ec.ECPoint mulPoint = ECAlgorithms.sumOfTwoMultiplies(pointResult, bn_g, pointSelf, bn); + result = new Point(runtime, EC5Util.convertPoint(mulPoint), result.group); + } + + if (result == null) { + newECError(runtime, "bad multiply result"); + } + } else { + throw runtime.newNotImplementedError("calling #mul with arrays is not supported by this OpenSSL version"); + } + + return result; + } + @Deprecated public IRubyObject initialize(final ThreadContext context, final IRubyObject[] args) { final int argc = Arity.checkArgumentCount(context.runtime, args, 1, 2); From dd59f740e22a89a7963b793129a4448fc2cb3781 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Tue, 11 Jun 2024 12:47:34 -0500 Subject: [PATCH 3/6] Add Point#mul --- .../java/org/jruby/ext/openssl/PKeyEC.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/main/java/org/jruby/ext/openssl/PKeyEC.java b/src/main/java/org/jruby/ext/openssl/PKeyEC.java index 3294a858..ca7ff976 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyEC.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyEC.java @@ -1073,6 +1073,32 @@ public IRubyObject inspect() { return ObjectSupport.inspect(this, (List) Collections.singletonList(entry)); } + @JRubyMethod(name = "add") + public IRubyObject add(final ThreadContext context, final IRubyObject other) { + Ruby runtime = context.runtime; + + org.bouncycastle.math.ec.ECPoint pointSelf, pointOther, pointResult; + + Group groupV = this.group; + Point result; + + ECCurve selfCurve = EC5Util.convertCurve(groupV.getCurve()); + pointSelf = EC5Util.convertPoint(selfCurve, asECPoint()); + + Point otherPoint = (Point) other; + ECCurve otherCurve = EC5Util.convertCurve(otherPoint.group.getCurve()); + pointOther = EC5Util.convertPoint(otherCurve, otherPoint.asECPoint()); + + pointResult = pointSelf.add(pointOther); + if (pointResult == null) { + newECError(runtime, "EC_POINT_add"); + } + + result = new Point(runtime, EC5Util.convertPoint(pointResult), group); + + return result; + } + @JRubyMethod(name = "mul", required = 1, optional = 2) public IRubyObject mul(final ThreadContext context, final IRubyObject[] args) { Ruby runtime = context.runtime; From 23ff68482d679a934e1a2b36d3d483bf69b2f223 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Tue, 11 Jun 2024 12:58:18 -0500 Subject: [PATCH 4/6] Refactor and arity-split Point#mul --- .../java/org/jruby/ext/openssl/PKeyEC.java | 111 +++++++++--------- 1 file changed, 58 insertions(+), 53 deletions(-) diff --git a/src/main/java/org/jruby/ext/openssl/PKeyEC.java b/src/main/java/org/jruby/ext/openssl/PKeyEC.java index ca7ff976..68203906 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyEC.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyEC.java @@ -1099,74 +1099,64 @@ public IRubyObject add(final ThreadContext context, final IRubyObject other) { return result; } - @JRubyMethod(name = "mul", required = 1, optional = 2) - public IRubyObject mul(final ThreadContext context, final IRubyObject[] args) { + @JRubyMethod(name = "mul") + public IRubyObject mul(final ThreadContext context, final IRubyObject bn1) { Ruby runtime = context.runtime; - org.bouncycastle.math.ec.ECPoint pointSelf, pointResult; - - Group groupV = this.group; + if (bn1 instanceof RubyArray) { + throw runtime.newNotImplementedError("calling #mul with arrays is not supported by this OpenSSL version"); + } - Point result; + org.bouncycastle.math.ec.ECPoint pointSelf; - BigInteger bn_g = null; + Group groupV = this.group; - ECCurve selfCurve = EC5Util.convertCurve(group.getCurve()); + ECCurve selfCurve = EC5Util.convertCurve(groupV.getCurve()); pointSelf = EC5Util.convertPoint(selfCurve, asECPoint()); - result = new Point(runtime, getMetaClass()); - result.initialize(context, groupV); - ECCurve resultCurve = EC5Util.convertCurve(result.group.getCurve()); - pointResult = EC5Util.convertPoint(resultCurve, result.point); + BigInteger bn = getBigInteger(context, bn1); - int argc = Arity.checkArgumentCount(runtime, args, 1, 3); - IRubyObject arg1 = null, arg2 = null; - switch (argc) { - case 2: - arg2 = args[1]; - case 1: - arg1 = args[0]; + org.bouncycastle.math.ec.ECPoint mulPoint = ECAlgorithms.referenceMultiply(pointSelf, bn); + if (mulPoint == null) { + throw newECError(runtime, "bad multiply result"); } - if (!(arg1 instanceof RubyArray)) { - BigInteger bn; - if (arg1 instanceof RubyFixnum) { - bn = BigInteger.valueOf(arg1.convertToInteger().getLongValue()); - } else if (arg1 instanceof RubyBignum) { - bn = ((RubyBignum) arg1).getValue(); - } else if (arg1 instanceof BN) { - bn = ((BN) arg1).getValue(); - } else { - throw runtime.newTypeError(arg1, runtime.getInteger()); - } - if (arg2 != null) { - if (arg2 instanceof RubyFixnum) { - bn_g = BigInteger.valueOf(arg2.convertToInteger().getLongValue()); - } else if (arg2 instanceof RubyBignum) { - bn_g = ((RubyBignum) arg2).getValue(); - } else if (arg2 instanceof BN) { - bn_g = ((BN) arg2).getValue(); - } else { - throw runtime.newTypeError(arg2, runtime.getInteger()); - } - } + return new Point(runtime, EC5Util.convertPoint(mulPoint), groupV); + } - if (bn_g == null) { - org.bouncycastle.math.ec.ECPoint mulPoint = ECAlgorithms.referenceMultiply(pointSelf, bn); - result = new Point(runtime, EC5Util.convertPoint(mulPoint), result.group); - } else { - org.bouncycastle.math.ec.ECPoint mulPoint = ECAlgorithms.sumOfTwoMultiplies(pointResult, bn_g, pointSelf, bn); - result = new Point(runtime, EC5Util.convertPoint(mulPoint), result.group); - } + @JRubyMethod(name = "mul") + public IRubyObject mul(final ThreadContext context, final IRubyObject bn1, final IRubyObject bn2) { + Ruby runtime = context.runtime; - if (result == null) { - newECError(runtime, "bad multiply result"); - } - } else { + if (bn1 instanceof RubyArray) { throw runtime.newNotImplementedError("calling #mul with arrays is not supported by this OpenSSL version"); } - return result; + org.bouncycastle.math.ec.ECPoint pointSelf, pointResult; + + Group groupV = this.group; + + ECCurve selfCurve = EC5Util.convertCurve(groupV.getCurve()); + pointSelf = EC5Util.convertPoint(selfCurve, asECPoint()); + + ECCurve resultCurve = EC5Util.convertCurve(groupV.getCurve()); + pointResult = EC5Util.convertPoint(resultCurve, ((Point) groupV.generator(context)).asECPoint()); + + BigInteger bn = getBigInteger(context, bn1); + BigInteger bn_g = getBigInteger(context, bn2); + + org.bouncycastle.math.ec.ECPoint mulPoint = ECAlgorithms.sumOfTwoMultiplies(pointResult, bn_g, pointSelf, bn); + + if (mulPoint == null) { + throw newECError(runtime, "bad multiply result"); + } + + return new Point(runtime, EC5Util.convertPoint(mulPoint), groupV); + } + + @JRubyMethod(name = "mul") + public IRubyObject mul(final ThreadContext context, final IRubyObject bns, final IRubyObject points, final IRubyObject bn2) { + throw context.runtime.newNotImplementedError("calling #mul with arrays is not supported by this OpenSSL version"); } @Deprecated @@ -1185,6 +1175,21 @@ public IRubyObject initialize(final ThreadContext context, final IRubyObject[] a } + private static BigInteger getBigInteger(ThreadContext context, IRubyObject arg1) { + BigInteger bn; + if (arg1 instanceof RubyFixnum) { + bn = BigInteger.valueOf(arg1.convertToInteger().getLongValue()); + } else if (arg1 instanceof RubyBignum) { + bn = ((RubyBignum) arg1).getValue(); + } else if (arg1 instanceof BN) { + bn = ((BN) arg1).getValue(); + } else { + Ruby runtime = context.runtime; + throw runtime.newTypeError(arg1, runtime.getInteger()); + } + return bn; + } + static byte[] encode(final ECPublicKey pubKey) { return encodeUncompressed(pubKey.getParams().getOrder().bitLength(), pubKey.getW()); } From 3ea09d21c82ffae71defc55743a6c48fac1f87eb Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Mon, 17 Jun 2024 11:50:43 -0500 Subject: [PATCH 5/6] Updates to pom --- pom.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index c8bc2c78..3ace1b00 100644 --- a/pom.xml +++ b/pom.xml @@ -65,8 +65,8 @@ DO NOT MODIFY - GENERATED CODE ${bc.versions} 3.0.2 -W0 - 9.2.19.0 - 9.2.19.0 + 9.1.17.0 + 9.1.17.0 2.0.2 2.0.2 pom.xml @@ -274,7 +274,6 @@ DO NOT MODIFY - GENERATED CODE 1.8 1.8 - 8 UTF-8 true true From 50fb847efc4f4a8914e987f43fc73638f9d0fdb5 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Mon, 17 Jun 2024 11:50:50 -0500 Subject: [PATCH 6/6] Get generator point from Group's paramSpec --- src/main/java/org/jruby/ext/openssl/PKeyEC.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jruby/ext/openssl/PKeyEC.java b/src/main/java/org/jruby/ext/openssl/PKeyEC.java index 68203906..5e4a8624 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyEC.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyEC.java @@ -976,7 +976,7 @@ private boolean getPointAndGroup(ThreadContext context, IRubyObject groupOrPoint if ( groupOrPoint instanceof Group) { this.group = (Group) groupOrPoint; - this.point = (ECPoint) ((Group) groupOrPoint).generator(context); + this.point = this.group.getParamSpec().getGenerator(); } else { throw runtime.newTypeError(groupOrPoint, _EC(runtime).getClass("Group")); }