aboutsummaryrefslogtreecommitdiff
path: root/common/src/main/java
diff options
context:
space:
mode:
authorquapka2024-06-21 16:31:37 +0200
committerquapka2024-06-21 16:31:37 +0200
commitada61982cc70a2c72a6fc765dc9b4a9c01202a27 (patch)
treed92bee42106e850d4da90ad7174ac609ca175eda /common/src/main/java
parentc051ef2ecfa92723d6dea675ac8c345be92cf165 (diff)
parentc112d3e49bbbbf33cc70d12d196e109543c19a3c (diff)
downloadECTester-ada61982cc70a2c72a6fc765dc9b4a9c01202a27.tar.gz
ECTester-ada61982cc70a2c72a6fc765dc9b4a9c01202a27.tar.zst
ECTester-ada61982cc70a2c72a6fc765dc9b4a9c01202a27.zip
Merge branch 'master' into build-with-nix
Diffstat (limited to 'common/src/main/java')
-rw-r--r--common/src/main/java/cz/crcs/ectester/common/ec/CustomECFieldFp.java2
-rw-r--r--common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java35
-rw-r--r--common/src/main/java/cz/crcs/ectester/common/output/BaseXMLTestWriter.java10
-rw-r--r--common/src/main/java/cz/crcs/ectester/common/output/BaseYAMLTestWriter.java10
-rw-r--r--common/src/main/java/cz/crcs/ectester/common/output/TeeTestWriter.java14
-rw-r--r--common/src/main/java/cz/crcs/ectester/common/output/TestWriter.java24
-rw-r--r--common/src/main/java/cz/crcs/ectester/common/test/TestSuite.java2
-rw-r--r--common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java115
-rw-r--r--common/src/main/java/cz/crcs/ectester/common/util/FileUtil.java11
9 files changed, 202 insertions, 21 deletions
diff --git a/common/src/main/java/cz/crcs/ectester/common/ec/CustomECFieldFp.java b/common/src/main/java/cz/crcs/ectester/common/ec/CustomECFieldFp.java
index eafcb72..1fe6eb0 100644
--- a/common/src/main/java/cz/crcs/ectester/common/ec/CustomECFieldFp.java
+++ b/common/src/main/java/cz/crcs/ectester/common/ec/CustomECFieldFp.java
@@ -19,7 +19,7 @@ public class CustomECFieldFp extends ECFieldFp {
@Override
public int getFieldSize() {
- return p.bitCount();
+ return p.bitLength();
}
@Override
diff --git a/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java b/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java
index 5c449db..538539b 100644
--- a/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java
+++ b/common/src/main/java/cz/crcs/ectester/common/output/BaseTextTestWriter.java
@@ -51,11 +51,13 @@ public abstract class BaseTextTestWriter implements TestWriter {
private String testString(Test t, String prefix, int index) {
boolean compound = t instanceof CompoundTest;
+ boolean cont = compound ? ((CompoundTest) t).getStartedTests().length > 0 : false;
+ boolean root = prefix.equals("");
Result result = t.getResult();
String line = "";
- if (prefix.equals("")) {
+ if (root) {
char[] charLine = new char[BASE_WIDTH + 24];
new String(new char[BASE_WIDTH + 24]).replace("\0", "━").getChars(0, charLine.length - 1, charLine, 0);
charLine[0] = '■';
@@ -68,10 +70,20 @@ public abstract class BaseTextTestWriter implements TestWriter {
StringBuilder out = new StringBuilder();
out.append(t.ok() ? Colors.ok(" OK ") : Colors.error("NOK "));
- out.append(compound ? (prefix.equals("") ? "╋ " : "┳ ") : "━ ");
+ String marker;
+ if (compound) {
+ if (root) {
+ marker = cont ? "╋" : "┻";
+ } else {
+ marker = cont ? "┳" : "━";
+ }
+ } else {
+ marker = "━";
+ }
+ out.append(marker + " ");
int width = BASE_WIDTH - (prefix.length() + 6);
String widthSpec = "%-" + width + "s";
- String desc = ((prefix.equals("")) ? "(" + index + ") " : "") + t.getDescription();
+ String desc = ((root) ? "(" + index + ") " : "") + t.getDescription();
out.append(String.format(widthSpec, desc));
out.append(" ┃ ");
Colors.Foreground valueColor;
@@ -114,6 +126,23 @@ public abstract class BaseTextTestWriter implements TestWriter {
}
@Override
+ public void beginTest(Test t) {
+ if (System.console() != null) {
+ output.print("Running ▶ " + t.getDescription());
+ output.flush();
+ }
+ }
+
+
+ @Override
+ public void endTest(Test t) {
+ if (System.console() != null) {
+ output.print("\33[2K\r");
+ output.flush();
+ }
+ }
+
+ @Override
public void outputTest(Test t, int index) {
if (!t.hasRun())
return;
diff --git a/common/src/main/java/cz/crcs/ectester/common/output/BaseXMLTestWriter.java b/common/src/main/java/cz/crcs/ectester/common/output/BaseXMLTestWriter.java
index 53970dd..5157ef0 100644
--- a/common/src/main/java/cz/crcs/ectester/common/output/BaseXMLTestWriter.java
+++ b/common/src/main/java/cz/crcs/ectester/common/output/BaseXMLTestWriter.java
@@ -116,6 +116,16 @@ public abstract class BaseXMLTestWriter implements TestWriter {
}
@Override
+ public void beginTest(Test t) {
+
+ }
+
+ @Override
+ public void endTest(Test t) {
+
+ }
+
+ @Override
public void outputTest(Test t, int index) {
if (!t.hasRun())
return;
diff --git a/common/src/main/java/cz/crcs/ectester/common/output/BaseYAMLTestWriter.java b/common/src/main/java/cz/crcs/ectester/common/output/BaseYAMLTestWriter.java
index e054563..c3a42ea 100644
--- a/common/src/main/java/cz/crcs/ectester/common/output/BaseYAMLTestWriter.java
+++ b/common/src/main/java/cz/crcs/ectester/common/output/BaseYAMLTestWriter.java
@@ -92,6 +92,16 @@ public abstract class BaseYAMLTestWriter implements TestWriter {
}
@Override
+ public void beginTest(Test t) {
+
+ }
+
+ @Override
+ public void endTest(Test t) {
+
+ }
+
+ @Override
public void outputTest(Test t, int index) {
if (!t.hasRun())
return;
diff --git a/common/src/main/java/cz/crcs/ectester/common/output/TeeTestWriter.java b/common/src/main/java/cz/crcs/ectester/common/output/TeeTestWriter.java
index 58a0a15..7635644 100644
--- a/common/src/main/java/cz/crcs/ectester/common/output/TeeTestWriter.java
+++ b/common/src/main/java/cz/crcs/ectester/common/output/TeeTestWriter.java
@@ -21,6 +21,20 @@ public class TeeTestWriter implements TestWriter {
}
@Override
+ public void beginTest(Test t) {
+ for (TestWriter writer : writers) {
+ writer.beginTest(t);
+ }
+ }
+
+ @Override
+ public void endTest(Test t) {
+ for (TestWriter writer : writers) {
+ writer.endTest(t);
+ }
+ }
+
+ @Override
public void outputTest(Test t, int index) {
for (TestWriter writer : writers) {
writer.outputTest(t, index);
diff --git a/common/src/main/java/cz/crcs/ectester/common/output/TestWriter.java b/common/src/main/java/cz/crcs/ectester/common/output/TestWriter.java
index 67aeccb..7368c0a 100644
--- a/common/src/main/java/cz/crcs/ectester/common/output/TestWriter.java
+++ b/common/src/main/java/cz/crcs/ectester/common/output/TestWriter.java
@@ -19,20 +19,32 @@ public interface TestWriter {
void begin(TestSuite suite);
/**
- * @param t
- * @param index
+ * Begin the test (before it is run).
+ * @param t Test to begin output of.
+ */
+ void beginTest(Test t);
+
+ /**
+ * End the test (after it is run, or errored out).
+ * @param t Test to end output of.
+ */
+ void endTest(Test t);
+
+ /**
+ * @param t Test to output.
+ * @param index Index of the test.
*/
void outputTest(Test t, int index);
/**
- * @param t
- * @param cause
- * @param index
+ * @param t Test to output the error from.
+ * @param cause Throwable to output.
+ * @param index Index of the test.
*/
void outputError(Test t, Throwable cause, int index);
/**
- *
+ * End writing the TestSuite.
*/
void end();
}
diff --git a/common/src/main/java/cz/crcs/ectester/common/test/TestSuite.java b/common/src/main/java/cz/crcs/ectester/common/test/TestSuite.java
index b12680a..091b008 100644
--- a/common/src/main/java/cz/crcs/ectester/common/test/TestSuite.java
+++ b/common/src/main/java/cz/crcs/ectester/common/test/TestSuite.java
@@ -55,7 +55,9 @@ public abstract class TestSuite {
*/
protected <T extends Test> T runTest(T t) {
running = t;
+ writer.beginTest(t);
t.run();
+ writer.endTest(t);
running = null;
return t;
}
diff --git a/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java b/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java
index f9be536..e7f138e 100644
--- a/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java
+++ b/common/src/main/java/cz/crcs/ectester/common/util/ECUtil.java
@@ -2,20 +2,25 @@ package cz.crcs.ectester.common.util;
import cz.crcs.ectester.common.ec.*;
import cz.crcs.ectester.data.EC_Store;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.signers.PlainDSAEncoding;
import org.bouncycastle.crypto.signers.StandardDSAEncoding;
+import org.bouncycastle.jcajce.interfaces.EdDSAPrivateKey;
+import org.bouncycastle.jcajce.interfaces.EdDSAPublicKey;
+import org.bouncycastle.jcajce.interfaces.XDHPrivateKey;
+import org.bouncycastle.jcajce.interfaces.XDHPublicKey;
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.*;
+import java.security.interfaces.*;
import java.security.spec.*;
import java.util.LinkedList;
import java.util.List;
@@ -344,6 +349,39 @@ public class ECUtil {
return new KeyPair(pubkey, privkey);
}
+ /**
+ * Validate DER or PLAIN signature format.
+ *
+ * @throws IllegalArgumentException in case of invalid format.
+ * @param signature
+ * @param params
+ * @param hashAlgo
+ * @param sigType
+ */
+ public static void validateSignatureFormat(byte[] signature, ECParameterSpec params, String hashAlgo, String sigType) {
+ BigInteger n = params.getOrder();
+ try {
+ if (sigType.contains("CVC") || sigType.contains("PLAIN")) {
+ PlainDSAEncoding.INSTANCE.decode(n, signature);
+ } else {
+ StandardDSAEncoding.INSTANCE.decode(n, signature);
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Recover the ECDSA signature nonce.
+ *
+ * @param signature
+ * @param data
+ * @param privkey
+ * @param params
+ * @param hashAlgo
+ * @param sigType
+ * @return The nonce.
+ */
public static BigInteger recoverSignatureNonce(byte[] signature, byte[] data, BigInteger privkey, ECParameterSpec params, String hashAlgo, String sigType) {
// We do not know how to reconstruct those nonces so far.
// sigType.contains("ECKCDSA") || sigType.contains("ECNR") || sigType.contains("SM2")
@@ -369,14 +407,18 @@ public class ECUtil {
}
// Parse signature
- BigInteger[] sigPair;
+ BigInteger r;
+ BigInteger s;
if (sigType.contains("CVC") || sigType.contains("PLAIN")) {
- sigPair = PlainDSAEncoding.INSTANCE.decode(n, signature);
+ BigInteger[] sigPair = PlainDSAEncoding.INSTANCE.decode(n, signature);
+ r = sigPair[0];
+ s = sigPair[1];
} else {
- sigPair = StandardDSAEncoding.INSTANCE.decode(n, signature);
+ ASN1Sequence seq = (ASN1Sequence) ASN1Primitive.fromByteArray(signature);
+ r = ((ASN1Integer) seq.getObjectAt(0)).getValue();
+ s = ((ASN1Integer) seq.getObjectAt(1)).getValue();
}
- BigInteger r = sigPair[0];
- BigInteger s = sigPair[1];
+
BigInteger rd = privkey.multiply(r).mod(n);
BigInteger hrd = hashInt.add(rd).mod(n);
@@ -456,6 +498,46 @@ public class ECUtil {
return null;
}
+ public static byte[] pubkeyToBytes(PublicKey pubkey) {
+ if (pubkey instanceof ECPublicKey) {
+ ECPublicKey ecPublicKey = (ECPublicKey) pubkey;
+ return ECUtil.toX962Uncompressed(ecPublicKey.getW(), ecPublicKey.getParams());
+ } else if (pubkey instanceof XECPublicKey) {
+ XECPublicKey xedPublicKey = (XECPublicKey) pubkey;
+ return xedPublicKey.getU().toByteArray();
+ } else if (pubkey instanceof EdECPublicKey) {
+ EdECPublicKey edECPublicKey = (EdECPublicKey) pubkey;
+ return edECPublicKey.getPoint().getY().toByteArray();
+ } else if (pubkey instanceof XDHPublicKey) {
+ XDHPublicKey xdhPublicKey = (XDHPublicKey) pubkey;
+ return xdhPublicKey.getU().toByteArray();
+ // Special-case BouncyCastle XDH
+ } else if (pubkey instanceof EdDSAPublicKey) {
+ EdDSAPublicKey edDSAPublicKey = (EdDSAPublicKey) pubkey;
+ // Special-case BouncyCastle EdDSA
+ return edDSAPublicKey.getPointEncoding();
+ }
+ return null;
+ }
+
+ public static byte[] privkeyToBytes(PrivateKey privkey) {
+ if (privkey instanceof ECPrivateKey) {
+ ECPrivateKey ecPrivateKey = (ECPrivateKey) privkey;
+ return ecPrivateKey.getS().toByteArray();
+ } else if (privkey instanceof XECPrivateKey) {
+ XECPrivateKey xecPrivateKey = (XECPrivateKey) privkey;
+ return xecPrivateKey.getScalar().get();
+ } else if (privkey instanceof EdECPrivateKey) {
+ EdECPrivateKey edECPrivateKey = (EdECPrivateKey) privkey;
+ return edECPrivateKey.getBytes().get();
+ } else if (privkey instanceof XDHPrivateKey || privkey instanceof EdDSAPrivateKey) {
+ // Special-case BouncyCastle XDH and EdDSA
+ PrivateKeyInfo xpkinfo = PrivateKeyInfo.getInstance(privkey.getEncoded());
+ return ASN1OctetString.getInstance(xpkinfo.getPrivateKey().getOctets()).getOctets();
+ }
+ return null;
+ }
+
public static boolean equalKeyPairParameters(ECPrivateKey priv, ECPublicKey pub) {
if (priv == null || pub == null) {
return false;
@@ -465,4 +547,15 @@ public class ECUtil {
priv.getParams().getGenerator().equals(pub.getParams().getGenerator()) &&
priv.getParams().getOrder().equals(pub.getParams().getOrder());
}
+
+ public static boolean equalECParameterSpec(ECParameterSpec left, ECParameterSpec right) {
+ if (left == null || right == null) {
+ return false;
+ }
+
+ return left.getCofactor() == right.getCofactor() &&
+ left.getCurve().equals(right.getCurve()) &&
+ left.getGenerator().equals(right.getGenerator()) &&
+ left.getOrder().equals(right.getOrder());
+ }
}
diff --git a/common/src/main/java/cz/crcs/ectester/common/util/FileUtil.java b/common/src/main/java/cz/crcs/ectester/common/util/FileUtil.java
index e6e319b..da682b6 100644
--- a/common/src/main/java/cz/crcs/ectester/common/util/FileUtil.java
+++ b/common/src/main/java/cz/crcs/ectester/common/util/FileUtil.java
@@ -81,6 +81,17 @@ public class FileUtil {
return true;
}
+ public static boolean write(String resourcePath, Path outPath) throws IOException {
+ URL reqURL = FileUtil.class.getResource(resourcePath);
+ if (reqURL == null) {
+ return false;
+ }
+ URLConnection reqConn = reqURL.openConnection();
+ Files.copy(reqConn.getInputStream(), outPath, StandardCopyOption.REPLACE_EXISTING);
+ reqConn.getInputStream().close();
+ return true;
+ }
+
public static Path getLibDir() {
return getAppData().resolve("ECTesterStandalone");
}