aboutsummaryrefslogtreecommitdiff
path: root/src/cz/crcs/ectester/common
diff options
context:
space:
mode:
authorJ08nY2019-03-18 11:01:24 +0100
committerJ08nY2019-03-18 11:01:24 +0100
commit529ab9c66b20e4308f88b63ead3318fd52e47eab (patch)
tree88b4fd80c4044b6febba2e28e6f1cdabdfceccb4 /src/cz/crcs/ectester/common
parentf535cb56d88e2bcc17dde1f15d021a17d1f1f511 (diff)
parent648d8718af10186e5c585844f6bb8c32e244c3a0 (diff)
downloadECTester-529ab9c66b20e4308f88b63ead3318fd52e47eab.tar.gz
ECTester-529ab9c66b20e4308f88b63ead3318fd52e47eab.tar.zst
ECTester-529ab9c66b20e4308f88b63ead3318fd52e47eab.zip
Merge branch 'devel'
Diffstat (limited to '')
-rw-r--r--src/cz/crcs/ectester/common/ec/EC_Category.java31
-rw-r--r--src/cz/crcs/ectester/common/ec/EC_Curve.java30
-rw-r--r--src/cz/crcs/ectester/common/output/BaseTextTestWriter.java3
-rw-r--r--src/cz/crcs/ectester/common/util/ECUtil.java187
-rw-r--r--src/cz/crcs/ectester/common/util/Util.java15
5 files changed, 234 insertions, 32 deletions
diff --git a/src/cz/crcs/ectester/common/ec/EC_Category.java b/src/cz/crcs/ectester/common/ec/EC_Category.java
index 1eb818f..154403e 100644
--- a/src/cz/crcs/ectester/common/ec/EC_Category.java
+++ b/src/cz/crcs/ectester/common/ec/EC_Category.java
@@ -2,10 +2,8 @@ package cz.crcs.ectester.common.ec;
import cz.crcs.ectester.common.cli.Colors;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Objects;
-import java.util.TreeMap;
+import java.util.*;
+import java.util.stream.Collectors;
/**
* A category of EC_Data objects, has a name, description and represents a directory in
@@ -78,28 +76,17 @@ public class EC_Category {
out.append("\t- ").append(Colors.bold(name)).append((desc == null || desc.equals("")) ? "" : ": " + desc);
out.append(System.lineSeparator());
- Map<String, EC_Curve> curves = getObjects(EC_Curve.class);
- int size = curves.size();
- if (size > 0) {
- out.append(Colors.bold("\t\tCurves: "));
- for (Map.Entry<String, EC_Curve> curve : curves.entrySet()) {
- out.append(curve.getKey());
- size--;
- if (size > 0)
- out.append(", ");
- }
- out.append(System.lineSeparator());
- }
-
- String[] headers = new String[]{"Public keys", "Private keys", "KeyPairs", "Results(KA)", "Results(SIG)"};
- Class<EC_Data>[] classes = new Class[]{EC_Key.Public.class, EC_Key.Private.class, EC_Keypair.class, EC_KAResult.class, EC_SigResult.class};
+ String[] headers = new String[]{"Curves", "Public keys", "Private keys", "KeyPairs", "Results(KA)", "Results(SIG)"};
+ Class<EC_Data>[] classes = new Class[]{EC_Curve.class, EC_Key.Public.class, EC_Key.Private.class, EC_Keypair.class, EC_KAResult.class, EC_SigResult.class};
for (int i = 0; i < headers.length; ++i) {
Map<String, EC_Data> data = getObjects(classes[i]);
- size = data.size();
+ int size = data.size();
if (size > 0) {
out.append(Colors.bold(String.format("\t\t%s: ", headers[i])));
- for (Map.Entry<String, EC_Data> key : data.entrySet()) {
- out.append(key.getKey());
+ List<EC_Data> sorted = new ArrayList<>(data.values());
+ Collections.sort(sorted);
+ for (EC_Data element : sorted) {
+ out.append(element.getId());
size--;
if (size > 0)
out.append(", ");
diff --git a/src/cz/crcs/ectester/common/ec/EC_Curve.java b/src/cz/crcs/ectester/common/ec/EC_Curve.java
index 6c0d060..d5d1516 100644
--- a/src/cz/crcs/ectester/common/ec/EC_Curve.java
+++ b/src/cz/crcs/ectester/common/ec/EC_Curve.java
@@ -3,6 +3,7 @@ package cz.crcs.ectester.common.ec;
import cz.crcs.ectester.applet.EC_Consts;
import cz.crcs.ectester.common.util.ByteUtil;
import javacard.security.KeyPair;
+import org.bouncycastle.math.ec.ECCurve;
import java.math.BigInteger;
import java.security.spec.*;
@@ -64,7 +65,12 @@ public class EC_Curve extends EC_Params {
int e1 = ByteUtil.getShort(fieldData[1], 0);
int e2 = ByteUtil.getShort(fieldData[2], 0);
int e3 = ByteUtil.getShort(fieldData[3], 0);
- int[] powers = new int[]{e1, e2, e3};
+ int[] powers;
+ if (e2 == 0 && e3 == 0) {
+ powers = new int[]{e1};
+ } else {
+ powers = new int[]{e1, e2, e3};
+ }
field = new ECFieldF2m(m, powers);
}
@@ -74,6 +80,28 @@ public class EC_Curve extends EC_Params {
return new EllipticCurve(field, a, b);
}
+ public ECCurve toBCCurve() {
+ if (this.field == KeyPair.ALG_EC_FP) {
+ BigInteger p = new BigInteger(1, getParam(EC_Consts.PARAMETER_FP)[0]);
+ BigInteger a = new BigInteger(1, getParam(EC_Consts.PARAMETER_A)[0]);
+ BigInteger b = new BigInteger(1, getParam(EC_Consts.PARAMETER_B)[0]);
+ BigInteger r = new BigInteger(1, getParam(EC_Consts.PARAMETER_R)[0]);
+ BigInteger k = new BigInteger(1, getParam(EC_Consts.PARAMETER_K)[0]);
+ return new ECCurve.Fp(p, a, b, r, k);
+ } else {
+ byte[][] fieldData = getParam(EC_Consts.PARAMETER_F2M);
+ int m = ByteUtil.getShort(fieldData[0], 0);
+ int e1 = ByteUtil.getShort(fieldData[1], 0);
+ int e2 = ByteUtil.getShort(fieldData[2], 0);
+ int e3 = ByteUtil.getShort(fieldData[3], 0);
+ BigInteger a = new BigInteger(1, getParam(EC_Consts.PARAMETER_A)[0]);
+ BigInteger b = new BigInteger(1, getParam(EC_Consts.PARAMETER_B)[0]);
+ BigInteger r = new BigInteger(1, getParam(EC_Consts.PARAMETER_R)[0]);
+ BigInteger k = new BigInteger(1, getParam(EC_Consts.PARAMETER_K)[0]);
+ return new ECCurve.F2m(m, e1, e2, e3, a, b, r, k);
+ }
+ }
+
public ECParameterSpec toSpec() {
EllipticCurve curve = toCurve();
diff --git a/src/cz/crcs/ectester/common/output/BaseTextTestWriter.java b/src/cz/crcs/ectester/common/output/BaseTextTestWriter.java
index 8ad50c7..5c449db 100644
--- a/src/cz/crcs/ectester/common/output/BaseTextTestWriter.java
+++ b/src/cz/crcs/ectester/common/output/BaseTextTestWriter.java
@@ -123,11 +123,12 @@ public abstract class BaseTextTestWriter implements TestWriter {
private String errorString(Throwable error) {
StringBuilder sb = new StringBuilder();
+ sb.append("═══ Exception: ═══").append(System.lineSeparator());
for (Throwable t = error; t != null; t = t.getCause()) {
sb.append("═══ ").append(t.toString()).append(" ═══");
sb.append(System.lineSeparator());
}
- sb.append("═══ ═══").append(System.lineSeparator());
+ sb.append("═══ Stack trace: ═══").append(System.lineSeparator());
for (StackTraceElement s : error.getStackTrace()) {
sb.append("═══ ").append(s.toString()).append(" ═══");
sb.append(System.lineSeparator());
diff --git a/src/cz/crcs/ectester/common/util/ECUtil.java b/src/cz/crcs/ectester/common/util/ECUtil.java
index 511f93f..d5e8006 100644
--- a/src/cz/crcs/ectester/common/util/ECUtil.java
+++ b/src/cz/crcs/ectester/common/util/ECUtil.java
@@ -9,20 +9,26 @@ import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERSequenceParser;
import org.bouncycastle.crypto.digests.SHA1Digest;
+import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.ECKey;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.*;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
/**
* @author Jan Jancar johny@neuromancer.sk
*/
public class ECUtil {
+ private static Random rand = new Random();
public static byte[] toByteArray(BigInteger what, int bits) {
byte[] raw = what.toByteArray();
@@ -95,7 +101,7 @@ public class ECUtil {
private static boolean isResidue(BigInteger a, BigInteger p) {
BigInteger exponent = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));
BigInteger result = a.modPow(exponent, p);
- return result.intValueExact() == 1;
+ return result.equals(BigInteger.ONE);
}
private static BigInteger modSqrt(BigInteger a, BigInteger p) {
@@ -192,7 +198,7 @@ public class ECUtil {
}
}
- public static byte[] semiRandomKey(EC_Curve curve) {
+ private static byte[] hashCurve(EC_Curve curve) {
int bytes = (curve.getBits() + 7) / 8;
byte[] result = new byte[bytes];
SHA1Digest digest = new SHA1Digest();
@@ -207,19 +213,102 @@ public class ECUtil {
written += toWrite;
digest.update(dig, 0, dig.length);
}
+ return result;
+ }
+
+ public static EC_Params fullRandomKey(EC_Curve curve) {
+ int bytes = (curve.getBits() + 7) / 8;
+ byte[] result = new byte[bytes];
+ rand.nextBytes(result);
BigInteger priv = new BigInteger(1, result);
BigInteger order = new BigInteger(1, curve.getParam(EC_Consts.PARAMETER_R)[0]);
priv = priv.mod(order);
- return toByteArray(priv, curve.getBits());
+ return new EC_Params(EC_Consts.PARAMETER_S, new byte[][]{toByteArray(priv, curve.getBits())});
+ }
+
+ public static EC_Params fixedRandomKey(EC_Curve curve) {
+ byte[] hash = hashCurve(curve);
+ BigInteger priv = new BigInteger(1, hash);
+ BigInteger order = new BigInteger(1, curve.getParam(EC_Consts.PARAMETER_R)[0]);
+ priv = priv.mod(order);
+ return new EC_Params(EC_Consts.PARAMETER_S, new byte[][]{toByteArray(priv, curve.getBits())});
+ }
+
+ private static BigInteger computeRHS(BigInteger x, BigInteger a, BigInteger b, BigInteger p) {
+ BigInteger rhs = x.modPow(BigInteger.valueOf(3), p);
+ rhs = rhs.add(a.multiply(x)).mod(p);
+ rhs = rhs.add(b).mod(p);
+ return rhs;
+ }
+
+ public static EC_Params fullRandomPoint(EC_Curve curve) {
+ EllipticCurve ecCurve = curve.toCurve();
+
+ BigInteger p;
+ if (ecCurve.getField() instanceof ECFieldFp) {
+ ECFieldFp fp = (ECFieldFp) ecCurve.getField();
+ p = fp.getP();
+ if (!p.isProbablePrime(20)) {
+ return null;
+ }
+ } else {
+ //TODO
+ return null;
+ }
+ BigInteger x;
+ BigInteger rhs;
+ do {
+ x = new BigInteger(ecCurve.getField().getFieldSize(), rand).mod(p);
+ rhs = computeRHS(x, ecCurve.getA(), ecCurve.getB(), p);
+ } while (!isResidue(rhs, p));
+ BigInteger y = modSqrt(rhs, p);
+ if (rand.nextBoolean()) {
+ y = p.subtract(y);
+ }
+
+ byte[] xArr = toByteArray(x, ecCurve.getField().getFieldSize());
+ byte[] yArr = toByteArray(y, ecCurve.getField().getFieldSize());
+ return new EC_Params(EC_Consts.PARAMETER_W, new byte[][]{xArr, yArr});
+ }
+
+ public static EC_Params fixedRandomPoint(EC_Curve curve) {
+ EllipticCurve ecCurve = curve.toCurve();
+
+ BigInteger p;
+ if (ecCurve.getField() instanceof ECFieldFp) {
+ ECFieldFp fp = (ECFieldFp) ecCurve.getField();
+ p = fp.getP();
+ if (!p.isProbablePrime(20)) {
+ return null;
+ }
+ } else {
+ //TODO
+ return null;
+ }
+
+ BigInteger x = new BigInteger(1, hashCurve(curve)).mod(p);
+ BigInteger rhs = computeRHS(x, ecCurve.getA(), ecCurve.getB(), p);
+ while (!isResidue(rhs, p)) {
+ x = x.add(BigInteger.ONE).mod(p);
+ rhs = computeRHS(x, ecCurve.getA(), ecCurve.getB(), p);
+ }
+ BigInteger y = modSqrt(rhs, p);
+ if (y.bitCount() % 2 == 0) {
+ y = p.subtract(y);
+ }
+
+ byte[] xArr = toByteArray(x, ecCurve.getField().getFieldSize());
+ byte[] yArr = toByteArray(y, ecCurve.getField().getFieldSize());
+ return new EC_Params(EC_Consts.PARAMETER_W, new byte[][]{xArr, yArr});
}
- private static ECPoint toPoint(EC_Params params) {
+ public static ECPoint toPoint(EC_Params params) {
return new ECPoint(
new BigInteger(1, params.getParam(EC_Consts.PARAMETER_W)[0]),
new BigInteger(1, params.getParam(EC_Consts.PARAMETER_W)[1]));
}
- private static BigInteger toScalar(EC_Params params) {
+ public static BigInteger toScalar(EC_Params params) {
return new BigInteger(1, params.getParam(EC_Consts.PARAMETER_S)[0]);
}
@@ -273,11 +362,22 @@ public class ECUtil {
public static BigInteger recoverSignatureNonce(byte[] signature, byte[] data, BigInteger privkey, ECParameterSpec params, String hashType) {
try {
int bitSize = params.getOrder().bitLength();
- MessageDigest md = MessageDigest.getInstance(hashType);
- byte[] hash = md.digest(data);
+ // Hash the data.
+ byte[] hash;
+ if (hashType.equals("NONE")) {
+ hash = data;
+ } else {
+ MessageDigest md = MessageDigest.getInstance(hashType);
+ hash = md.digest(data);
+ }
+ // Trim bitSize of rightmost bits.
BigInteger hashInt = new BigInteger(1, hash);
- hashInt = hashInt.and(BigInteger.ONE.shiftLeft(bitSize + 1).subtract(BigInteger.ONE));
+ int hashBits = hashInt.bitLength();
+ if (hashBits > bitSize) {
+ hashInt = hashInt.shiftRight(hashBits - bitSize);
+ }
+ // Parse DERSignature
BigInteger[] sigPair = fromDERSignature(signature);
BigInteger r = sigPair[0];
BigInteger s = sigPair[1];
@@ -290,4 +390,75 @@ public class ECUtil {
return null;
}
}
+
+ public static EC_Params joinParams(EC_Params... params) {
+ List<EC_Params> paramList = new LinkedList<>();
+ short paramMask = 0;
+ int len = 0;
+ for (EC_Params param : params) {
+ if (param == null) {
+ continue;
+ }
+ int i = 0;
+ for (; i + 1 < paramList.size(); ++i) {
+ if (paramList.get(i + 1).getParams() == param.getParams()) {
+ throw new IllegalArgumentException();
+ }
+ if (paramList.get(i + 1).getParams() < param.getParams()) {
+ break;
+ }
+ }
+ paramList.add(i, param);
+ paramMask |= param.getParams();
+ len += param.numParams();
+ }
+
+ byte[][] res = new byte[len][];
+ int i = 0;
+ for (EC_Params param : params) {
+ for (byte[] data : param.getData()) {
+ res[i++] = data.clone();
+ }
+ }
+ return new EC_Params(paramMask, res);
+ }
+
+ public static EC_Params loadParams(short params, String named, String file) throws IOException {
+ EC_Params result = null;
+ if (file != null) {
+ result = new EC_Params(params);
+
+ FileInputStream in = new FileInputStream(file);
+ result.readCSV(in);
+ in.close();
+ } else if (named != null) {
+ if (params == EC_Consts.PARAMETER_W) {
+ result = EC_Store.getInstance().getObject(EC_Key.Public.class, named);
+ } else if (params == EC_Consts.PARAMETER_S) {
+ result = EC_Store.getInstance().getObject(EC_Key.Private.class, named);
+ }
+
+ if (result == null) {
+ result = EC_Store.getInstance().getObject(EC_Keypair.class, named);
+ }
+ }
+ return result;
+ }
+
+ public static ECKey loadKey(short params, String named, String file, ECParameterSpec spec) throws IOException {
+ if (params == EC_Consts.PARAMETERS_KEYPAIR) {
+ throw new IllegalArgumentException();
+ }
+ EC_Params param = loadParams(params, named, file);
+ if (param != null) {
+ if (params == EC_Consts.PARAMETER_W) {
+ return new RawECPublicKey(toPoint(param), spec);
+ } else if (params == EC_Consts.PARAMETER_S) {
+ return new RawECPrivateKey(toScalar(param), spec);
+ }
+ }
+ return null;
+ }
+
+
}
diff --git a/src/cz/crcs/ectester/common/util/Util.java b/src/cz/crcs/ectester/common/util/Util.java
new file mode 100644
index 0000000..7f18368
--- /dev/null
+++ b/src/cz/crcs/ectester/common/util/Util.java
@@ -0,0 +1,15 @@
+package cz.crcs.ectester.common.util;
+
+public class Util {
+ public static long convertTime(long nanos, String timeUnit) {
+ switch (timeUnit) {
+ default:
+ case "nano":
+ return nanos;
+ case "micro":
+ return nanos / 1000;
+ case "milli":
+ return nanos / 1000000;
+ }
+ }
+}