Skip to content

Commit

Permalink
Merge pull request #307 from headius/point_mul
Browse files Browse the repository at this point in the history
Implement Point#mul
  • Loading branch information
headius authored Jun 17, 2024
2 parents 55f71cb + 50fb847 commit adca91b
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 29 deletions.
5 changes: 2 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ DO NOT MODIFY - GENERATED CODE
<invoker.test>${bc.versions}</invoker.test>
<jruby.plugins.version>3.0.2</jruby.plugins.version>
<jruby.switches>-W0</jruby.switches>
<jruby.version>9.2.19.0</jruby.version>
<jruby.versions>9.2.19.0</jruby.versions>
<jruby.version>9.1.17.0</jruby.version>
<jruby.versions>9.1.17.0</jruby.versions>
<mavengem-wagon.version>2.0.2</mavengem-wagon.version>
<mavengem.wagon.version>2.0.2</mavengem.wagon.version>
<polyglot.dump.pom>pom.xml</polyglot.dump.pom>
Expand Down Expand Up @@ -274,7 +274,6 @@ DO NOT MODIFY - GENERATED CODE
<configuration>
<source>1.8</source>
<target>1.8</target>
<release>8</release>
<encoding>UTF-8</encoding>
<debug>true</debug>
<showWarnings>true</showWarnings>
Expand Down
181 changes: 155 additions & 26 deletions src/main/java/org/jruby/ext/openssl/PKeyEC.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit adca91b

Please sign in to comment.