diff options
| author | quapka | 2024-06-21 16:31:37 +0200 |
|---|---|---|
| committer | quapka | 2024-06-21 16:31:37 +0200 |
| commit | ada61982cc70a2c72a6fc765dc9b4a9c01202a27 (patch) | |
| tree | d92bee42106e850d4da90ad7174ac609ca175eda /common/src/main/java | |
| parent | c051ef2ecfa92723d6dea675ac8c345be92cf165 (diff) | |
| parent | c112d3e49bbbbf33cc70d12d196e109543c19a3c (diff) | |
| download | ECTester-ada61982cc70a2c72a6fc765dc9b4a9c01202a27.tar.gz ECTester-ada61982cc70a2c72a6fc765dc9b4a9c01202a27.tar.zst ECTester-ada61982cc70a2c72a6fc765dc9b4a9c01202a27.zip | |
Merge branch 'master' into build-with-nix
Diffstat (limited to 'common/src/main/java')
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"); } |
