Skip to content

Commit adca91b

Browse files
authored
Merge pull request #307 from headius/point_mul
Implement Point#mul
2 parents 55f71cb + 50fb847 commit adca91b

File tree

2 files changed

+157
-29
lines changed

2 files changed

+157
-29
lines changed

pom.xml

+2-3
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ DO NOT MODIFY - GENERATED CODE
6565
<invoker.test>${bc.versions}</invoker.test>
6666
<jruby.plugins.version>3.0.2</jruby.plugins.version>
6767
<jruby.switches>-W0</jruby.switches>
68-
<jruby.version>9.2.19.0</jruby.version>
69-
<jruby.versions>9.2.19.0</jruby.versions>
68+
<jruby.version>9.1.17.0</jruby.version>
69+
<jruby.versions>9.1.17.0</jruby.versions>
7070
<mavengem-wagon.version>2.0.2</mavengem-wagon.version>
7171
<mavengem.wagon.version>2.0.2</mavengem.wagon.version>
7272
<polyglot.dump.pom>pom.xml</polyglot.dump.pom>
@@ -274,7 +274,6 @@ DO NOT MODIFY - GENERATED CODE
274274
<configuration>
275275
<source>1.8</source>
276276
<target>1.8</target>
277-
<release>8</release>
278277
<encoding>UTF-8</encoding>
279278
<debug>true</debug>
280279
<showWarnings>true</showWarnings>

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

+155-26
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,14 @@
5858
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
5959
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
6060

61+
import org.bouncycastle.math.ec.ECAlgorithms;
62+
import org.bouncycastle.math.ec.ECCurve;
6163
import org.jruby.Ruby;
6264
import org.jruby.RubyArray;
65+
import org.jruby.RubyBignum;
6366
import org.jruby.RubyBoolean;
6467
import org.jruby.RubyClass;
68+
import org.jruby.RubyFixnum;
6569
import org.jruby.RubyModule;
6670
import org.jruby.RubyObject;
6771
import org.jruby.RubyString;
@@ -931,44 +935,54 @@ private static RaiseException newError(final Ruby runtime, final String message)
931935
return Utils.newError(runtime, Error, message);
932936
}
933937

934-
@JRubyMethod(rest = true, visibility = Visibility.PRIVATE)
935-
public IRubyObject initialize(final ThreadContext context, final IRubyObject[] args) {
936-
final Ruby runtime = context.runtime;
938+
@JRubyMethod(visibility = Visibility.PRIVATE)
939+
public IRubyObject initialize(final ThreadContext context, final IRubyObject groupOrPoint) {
940+
getPointAndGroup(context, groupOrPoint);
937941

938-
final int argc = Arity.checkArgumentCount(runtime, args, 1, 2);
939-
final IRubyObject arg = args[0];
942+
return this;
943+
}
940944

941-
if ( arg instanceof Point ) {
942-
this.group = ((Point) arg).group;
943-
this.point = ((Point) arg).point;
945+
@JRubyMethod(visibility = Visibility.PRIVATE)
946+
public IRubyObject initialize(final ThreadContext context, final IRubyObject groupOrPoint, final IRubyObject bn) {
947+
if (getPointAndGroup(context, groupOrPoint)) {
944948
return this;
945949
}
946950

947-
if ( arg instanceof Group ) {
948-
this.group = (Group) arg;
951+
final byte[] encoded;
952+
if (bn instanceof BN) {
953+
encoded = ((BN) bn).getValue().abs().toByteArray();
949954
} else {
950-
throw runtime.newTypeError(arg, _EC(runtime).getClass("Group"));
955+
encoded = bn.convertToString().getBytes();
951956
}
952-
953-
if ( argc == 2 ) { // (group, bn)
954-
final byte[] encoded;
955-
if (args[1] instanceof BN) {
956-
encoded = ((BN) args[1]).getValue().abs().toByteArray();
957-
} else {
958-
encoded = args[1].convertToString().getBytes();
959-
}
960-
try {
961-
this.point = ECPointUtil.decodePoint(group.getCurve(), encoded);
962-
}
963-
catch (IllegalArgumentException ex) {
964-
// MRI: OpenSSL::PKey::EC::Point::Error: invalid encoding
965-
throw newError(context.runtime, ex.getMessage());
966-
}
957+
try {
958+
this.point = ECPointUtil.decodePoint(group.getCurve(), encoded);
959+
}
960+
catch (IllegalArgumentException ex) {
961+
// MRI: OpenSSL::PKey::EC::Point::Error: invalid encoding
962+
throw newError(context.runtime, ex.getMessage());
967963
}
968964

969965
return this;
970966
}
971967

968+
private boolean getPointAndGroup(ThreadContext context, IRubyObject groupOrPoint) {
969+
final Ruby runtime = context.runtime;
970+
971+
if ( groupOrPoint instanceof Point) {
972+
this.group = ((Point) groupOrPoint).group;
973+
this.point = ((Point) groupOrPoint).point;
974+
return true;
975+
}
976+
977+
if ( groupOrPoint instanceof Group) {
978+
this.group = (Group) groupOrPoint;
979+
this.point = this.group.getParamSpec().getGenerator();
980+
} else {
981+
throw runtime.newTypeError(groupOrPoint, _EC(runtime).getClass("Group"));
982+
}
983+
return false;
984+
}
985+
972986
@Override
973987
@JRubyMethod(name = { "==", "eql?" })
974988
public IRubyObject op_equal(final ThreadContext context, final IRubyObject obj) {
@@ -1059,6 +1073,121 @@ public IRubyObject inspect() {
10591073
return ObjectSupport.inspect(this, (List) Collections.singletonList(entry));
10601074
}
10611075

1076+
@JRubyMethod(name = "add")
1077+
public IRubyObject add(final ThreadContext context, final IRubyObject other) {
1078+
Ruby runtime = context.runtime;
1079+
1080+
org.bouncycastle.math.ec.ECPoint pointSelf, pointOther, pointResult;
1081+
1082+
Group groupV = this.group;
1083+
Point result;
1084+
1085+
ECCurve selfCurve = EC5Util.convertCurve(groupV.getCurve());
1086+
pointSelf = EC5Util.convertPoint(selfCurve, asECPoint());
1087+
1088+
Point otherPoint = (Point) other;
1089+
ECCurve otherCurve = EC5Util.convertCurve(otherPoint.group.getCurve());
1090+
pointOther = EC5Util.convertPoint(otherCurve, otherPoint.asECPoint());
1091+
1092+
pointResult = pointSelf.add(pointOther);
1093+
if (pointResult == null) {
1094+
newECError(runtime, "EC_POINT_add");
1095+
}
1096+
1097+
result = new Point(runtime, EC5Util.convertPoint(pointResult), group);
1098+
1099+
return result;
1100+
}
1101+
1102+
@JRubyMethod(name = "mul")
1103+
public IRubyObject mul(final ThreadContext context, final IRubyObject bn1) {
1104+
Ruby runtime = context.runtime;
1105+
1106+
if (bn1 instanceof RubyArray) {
1107+
throw runtime.newNotImplementedError("calling #mul with arrays is not supported by this OpenSSL version");
1108+
}
1109+
1110+
org.bouncycastle.math.ec.ECPoint pointSelf;
1111+
1112+
Group groupV = this.group;
1113+
1114+
ECCurve selfCurve = EC5Util.convertCurve(groupV.getCurve());
1115+
pointSelf = EC5Util.convertPoint(selfCurve, asECPoint());
1116+
1117+
BigInteger bn = getBigInteger(context, bn1);
1118+
1119+
org.bouncycastle.math.ec.ECPoint mulPoint = ECAlgorithms.referenceMultiply(pointSelf, bn);
1120+
if (mulPoint == null) {
1121+
throw newECError(runtime, "bad multiply result");
1122+
}
1123+
1124+
return new Point(runtime, EC5Util.convertPoint(mulPoint), groupV);
1125+
}
1126+
1127+
@JRubyMethod(name = "mul")
1128+
public IRubyObject mul(final ThreadContext context, final IRubyObject bn1, final IRubyObject bn2) {
1129+
Ruby runtime = context.runtime;
1130+
1131+
if (bn1 instanceof RubyArray) {
1132+
throw runtime.newNotImplementedError("calling #mul with arrays is not supported by this OpenSSL version");
1133+
}
1134+
1135+
org.bouncycastle.math.ec.ECPoint pointSelf, pointResult;
1136+
1137+
Group groupV = this.group;
1138+
1139+
ECCurve selfCurve = EC5Util.convertCurve(groupV.getCurve());
1140+
pointSelf = EC5Util.convertPoint(selfCurve, asECPoint());
1141+
1142+
ECCurve resultCurve = EC5Util.convertCurve(groupV.getCurve());
1143+
pointResult = EC5Util.convertPoint(resultCurve, ((Point) groupV.generator(context)).asECPoint());
1144+
1145+
BigInteger bn = getBigInteger(context, bn1);
1146+
BigInteger bn_g = getBigInteger(context, bn2);
1147+
1148+
org.bouncycastle.math.ec.ECPoint mulPoint = ECAlgorithms.sumOfTwoMultiplies(pointResult, bn_g, pointSelf, bn);
1149+
1150+
if (mulPoint == null) {
1151+
throw newECError(runtime, "bad multiply result");
1152+
}
1153+
1154+
return new Point(runtime, EC5Util.convertPoint(mulPoint), groupV);
1155+
}
1156+
1157+
@JRubyMethod(name = "mul")
1158+
public IRubyObject mul(final ThreadContext context, final IRubyObject bns, final IRubyObject points, final IRubyObject bn2) {
1159+
throw context.runtime.newNotImplementedError("calling #mul with arrays is not supported by this OpenSSL version");
1160+
}
1161+
1162+
@Deprecated
1163+
public IRubyObject initialize(final ThreadContext context, final IRubyObject[] args) {
1164+
final int argc = Arity.checkArgumentCount(context.runtime, args, 1, 2);
1165+
1166+
switch (argc) {
1167+
case 1:
1168+
return initialize(context, args[0]);
1169+
case 2:
1170+
return initialize(context, args[0], args[1]);
1171+
default:
1172+
throw context.runtime.newArgumentError(args.length, 1);
1173+
}
1174+
}
1175+
1176+
}
1177+
1178+
private static BigInteger getBigInteger(ThreadContext context, IRubyObject arg1) {
1179+
BigInteger bn;
1180+
if (arg1 instanceof RubyFixnum) {
1181+
bn = BigInteger.valueOf(arg1.convertToInteger().getLongValue());
1182+
} else if (arg1 instanceof RubyBignum) {
1183+
bn = ((RubyBignum) arg1).getValue();
1184+
} else if (arg1 instanceof BN) {
1185+
bn = ((BN) arg1).getValue();
1186+
} else {
1187+
Ruby runtime = context.runtime;
1188+
throw runtime.newTypeError(arg1, runtime.getInteger());
1189+
}
1190+
return bn;
10621191
}
10631192

10641193
static byte[] encode(final ECPublicKey pubKey) {

0 commit comments

Comments
 (0)