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 diff --git a/src/main/java/org/jruby/ext/openssl/PKeyEC.java b/src/main/java/org/jruby/ext/openssl/PKeyEC.java index 21d9733d..5e4a8624 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; @@ -931,44 +935,54 @@ 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; + this.point = this.group.getParamSpec().getGenerator(); + } 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 +1073,121 @@ 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") + public IRubyObject mul(final ThreadContext context, final IRubyObject bn1) { + Ruby runtime = context.runtime; + + if (bn1 instanceof RubyArray) { + throw runtime.newNotImplementedError("calling #mul with arrays is not supported by this OpenSSL version"); + } + + org.bouncycastle.math.ec.ECPoint pointSelf; + + Group groupV = this.group; + + ECCurve selfCurve = EC5Util.convertCurve(groupV.getCurve()); + pointSelf = EC5Util.convertPoint(selfCurve, asECPoint()); + + BigInteger bn = getBigInteger(context, bn1); + + org.bouncycastle.math.ec.ECPoint mulPoint = ECAlgorithms.referenceMultiply(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 bn1, final IRubyObject bn2) { + Ruby runtime = context.runtime; + + if (bn1 instanceof RubyArray) { + throw runtime.newNotImplementedError("calling #mul with arrays is not supported by this OpenSSL version"); + } + + 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 + 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); + } + } + + } + + 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) {