From 6345910ebf326f5778f67c124287b45e30e829f5 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Tue, 11 Jun 2024 10:13:04 -0500 Subject: [PATCH] Implement Point#mul --- .../java/org/jruby/ext/openssl/PKeyEC.java | 50 +++++++++++++++++++ 1 file changed, 50 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..bf86c60a 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyEC.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyEC.java @@ -58,6 +58,8 @@ 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.RubyBoolean; @@ -972,6 +974,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 +1071,53 @@ 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 = args[0], arg2 = args[1], arg3 = args[2]; + if (!(arg1 instanceof RubyArray)) { + BigInteger bn = ((BN) arg1).getValue(); + + if (!arg2.isNil()) { + bn_g = ((BN) arg2).getValue(); + } + + 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);