diff options
author | Jeffrey Stedfast <jeff@xamarin.com> | 2015-10-11 10:26:27 -0400 |
---|---|---|
committer | Jeffrey Stedfast <jeff@xamarin.com> | 2015-10-11 10:26:27 -0400 |
commit | b2e562d4efdc221d10b08e9cba782057225ffc0e (patch) | |
tree | e1b19aa33900ae6070f2b89b2e6b0e46bd97d2b2 /crypto/test/src | |
parent | Updated MimeKit.BouncyCastle.nuspec (diff) | |
parent | Port of recent ISO trailer updates from Java (diff) | |
download | BouncyCastle.NET-ed25519-b2e562d4efdc221d10b08e9cba782057225ffc0e.tar.xz |
Merge branch 'master' into vs2010
Diffstat (limited to 'crypto/test/src')
-rw-r--r-- | crypto/test/src/crypto/test/KeccakDigestTest.cs | 374 | ||||
-rw-r--r-- | crypto/test/src/crypto/test/RegressionTest.cs | 4 | ||||
-rw-r--r-- | crypto/test/src/crypto/test/SHA3DigestTest.cs | 468 | ||||
-rw-r--r-- | crypto/test/src/crypto/test/ShakeDigestTest.cs | 290 | ||||
-rw-r--r-- | crypto/test/src/math/ec/test/ECPointTest.cs | 51 |
5 files changed, 902 insertions, 285 deletions
diff --git a/crypto/test/src/crypto/test/KeccakDigestTest.cs b/crypto/test/src/crypto/test/KeccakDigestTest.cs new file mode 100644 index 000000000..961a5d2e3 --- /dev/null +++ b/crypto/test/src/crypto/test/KeccakDigestTest.cs @@ -0,0 +1,374 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * Keccak Digest Test + */ + [TestFixture] + public class KeccakDigestTest + : SimpleTest + { + readonly static string[] messages = { + "", + "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67", + "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f672e" + }; + + readonly static string[] digests288 = { // the default settings + "6753e3380c09e385d0339eb6b050a68f66cfd60a73476e6fd6adeb72f5edd7c6f04a5d01", // message[0] + "0bbe6afae0d7e89054085c1cc47b1689772c89a41796891e197d1ca1b76f288154933ded", // message[1] + "82558a209b960ddeb531e6dcb281885b2400ca160472462486e79f071e88a3330a8a303d", // message[2] + "94049e1ad7ef5d5b0df2b880489e7ab09ec937c3bfc1b04470e503e1ac7b1133c18f86da", // 64k a-test + "a9cb5a75b5b81b7528301e72553ed6770214fa963956e790528afe420de33c074e6f4220", // random alphabet test + "eadaf5ba2ad6a2f6f338fce0e1efdad2a61bb38f6be6068b01093977acf99e97a5d5827c" // extremely long data test + }; + + readonly static string[] digests224 = { + "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd", + "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe", + "c59d4eaeac728671c635ff645014e2afa935bebffdb5fbd207ffdeab", + "f621e11c142fbf35fa8c22841c3a812ba1e0151be4f38d80b9f1ff53", + "68b5fc8c87193155bba68a2485377e809ee4f81a85ef023b9e64add0", + "c42e4aee858e1a8ad2976896b9d23dd187f64436ee15969afdbc68c5" + }; + + readonly static string[] digests256 = { + "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15", + "578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d", + "0047a916daa1f92130d870b542e22d3108444f5a7e4429f05762fb647e6ed9ed", + "db368762253ede6d4f1db87e0b799b96e554eae005747a2ea687456ca8bcbd03", + "5f313c39963dcf792b5470d4ade9f3a356a3e4021748690a958372e2b06f82a4" + }; + + readonly static string[] digests384 = { + "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff", + "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3", + "9ad8e17325408eddb6edee6147f13856ad819bb7532668b605a24a2d958f88bd5c169e56dc4b2f89ffd325f6006d820b", + "c704cfe7a1a53208ca9526cd24251e0acdc252ecd978eee05acd16425cfb404ea81f5a9e2e5e97784d63ee6a0618a398", + "d4fe8586fd8f858dd2e4dee0bafc19b4c12b4e2a856054abc4b14927354931675cdcaf942267f204ea706c19f7beefc4", + "9b7168b4494a80a86408e6b9dc4e5a1837c85dd8ff452ed410f2832959c08c8c0d040a892eb9a755776372d4a8732315" + }; + + readonly static string[] digests512 = { + "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e", + "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609", + "ab7192d2b11f51c7dd744e7b3441febf397ca07bf812cceae122ca4ded6387889064f8db9230f173f6d1ab6e24b6e50f065b039f799f5592360a6558eb52d760", + "34341ead153aa1d1fdcf6cf624c2b4f6894b6fd16dc38bd4ec971ac0385ad54fafcb2e0ed86a1e509456f4246fdcb02c3172824cd649d9ad54c51f7fb49ea67c", + "dc44d4f4d36b07ab5fc04016cbe53548e5a7778671c58a43cb379fd00c06719b8073141fc22191ffc3db5f8b8983ae8341fa37f18c1c969664393aa5ceade64e", + "3e122edaf37398231cfaca4c7c216c9d66d5b899ec1d7ac617c40c7261906a45fc01617a021e5da3bd8d4182695b5cb785a28237cbb167590e34718e56d8aab8" + }; + + // test vectors from http://www.di-mgt.com.au/hmac_sha3_testvectors.html + readonly static byte[][] macKeys = + { + Hex.Decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), + Hex.Decode("4a656665"), + Hex.Decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + Hex.Decode("0102030405060708090a0b0c0d0e0f10111213141516171819"), + Hex.Decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaa"), + Hex.Decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaa"), + Hex.Decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") + }; + + readonly static string[] macData = + { + "4869205468657265", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + + "dddddddddddddddddddddddddddddddddddd", + "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" + + "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", + "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" + + "65204b6579202d2048617368204b6579204669727374", + "5468697320697320612074657374207573696e672061206c6172676572207468" + + "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" + + "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" + + "647320746f20626520686173686564206265666f7265206265696e6720757365" + + "642062792074686520484d414320616c676f726974686d2e", + "5468697320697320612074657374207573696e672061206c6172676572207468" + + "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" + + "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" + + "647320746f20626520686173686564206265666f7265206265696e6720757365\n" + + "642062792074686520484d414320616c676f726974686d2e" + }; + + readonly static string[] mac224 = + { + "b73d595a2ba9af815e9f2b4e53e78581ebd34a80b3bbaac4e702c4cc", + "e824fec96c074f22f99235bb942da1982664ab692ca8501053cbd414", + "770df38c99d6e2bacd68056dcfe07d4c89ae20b2686a6185e1faa449", + "305a8f2dfb94bad28861a03cbc4d590febe775c58cb4961c28428a0b", + "e7a52dfa45f95a217c100066b239aa8ad519be9b35d667268b1b57ff", + "ba13009405a929f398b348885caa5419191bb948ada32194afc84104", + "92649468be236c3c72c189909c063b13f994be05749dc91310db639e" + }; + + readonly static string[] mac256 = + { + "9663d10c73ee294054dc9faf95647cb99731d12210ff7075fb3d3395abfb9821", + "aa9aed448c7abc8b5e326ffa6a01cdedf7b4b831881468c044ba8dd4566369a1", + "95f43e50f8df80a21977d51a8db3ba572dcd71db24687e6f86f47c1139b26260", + "6331ba9b4af5804a68725b3663eb74814494b63c6093e35fb320a85d507936fd", + "b4d0cdee7ec2ba81a88b86918958312300a15622377929a054a9ce3ae1fac2b6", + "1fdc8cb4e27d07c10d897dec39c217792a6e64fa9c63a77ce42ad106ef284e02", + "fdaa10a0299aecff9bb411cf2d7748a4022e4a26be3fb5b11b33d8c2b7ef5484" + }; + + readonly static string[] mac384 = + { + "892dfdf5d51e4679bf320cd16d4c9dc6f749744608e003add7fba894acff87361efa4e5799be06b6461f43b60ae97048", + "5af5c9a77a23a6a93d80649e562ab77f4f3552e3c5caffd93bdf8b3cfc6920e3023fc26775d9df1f3c94613146ad2c9d", + "4243c29f2201992ff96441e3b91ff81d8c601d706fbc83252684a4bc51101ca9b2c06ddd03677303c502ac5331752a3c", + "b730724d3d4090cda1be799f63acbbe389fef7792fc18676fa5453aab398664650ed029c3498bbe8056f06c658e1e693", + "d62482ef601d7847439b55236e9679388ffcd53c62cd126f39be6ea63de762e26cd5974cb9a8de401b786b5555040f6f", + "4860ea191ac34994cf88957afe5a836ef36e4cc1a66d75bf77defb7576122d75f60660e4cf731c6effac06402787e2b9", + "fe9357e3cfa538eb0373a2ce8f1e26ad6590afdaf266f1300522e8896d27e73f654d0631c8fa598d4bb82af6b744f4f5" + }; + + readonly static string[] mac512 = + { + "8852c63be8cfc21541a4ee5e5a9a852fc2f7a9adec2ff3a13718ab4ed81aaea0b87b7eb397323548e261a64e7fc75198f6663a11b22cd957f7c8ec858a1c7755", + "c2962e5bbe1238007852f79d814dbbecd4682e6f097d37a363587c03bfa2eb0859d8d9c701e04cececfd3dd7bfd438f20b8b648e01bf8c11d26824b96cebbdcb", + "eb0ed9580e0ec11fc66cbb646b1be904eaff6da4556d9334f65ee4b2c85739157bae9027c51505e49d1bb81cfa55e6822db55262d5a252c088a29a5e95b84a66", + "b46193bb59f4f696bf702597616da91e2a4558a593f4b015e69141ba81e1e50ea580834c2b87f87baa25a3a03bfc9bb389847f2dc820beae69d30c4bb75369cb", + "d05888a6ebf8460423ea7bc85ea4ffda847b32df32291d2ce115fd187707325c7ce4f71880d91008084ce24a38795d20e6a28328a0f0712dc38253370da3ebb5", + "2c6b9748d35c4c8db0b4407dd2ed2381f133bdbd1dfaa69e30051eb6badfcca64299b88ae05fdbd3dd3dd7fe627e42e39e48b0fe8c7f1e85f2dbd52c2d753572", + "6adc502f14e27812402fc81a807b28bf8a53c87bea7a1df6256bf66f5de1a4cb741407ad15ab8abc136846057f881969fbb159c321c904bfb557b77afb7778c8" + }; + + readonly static KeyParameter truncKey = new KeyParameter(Hex.Decode("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c")); + readonly static byte[] truncData = Hex.Decode("546573742057697468205472756e636174696f6e"); + + readonly static byte[] trunc224 = Hex.Decode("f52bbcfd654264e7133085c5e69b72c3"); + readonly static byte[] trunc256 = Hex.Decode("745e7e687f8335280d54202ef13cecc6"); + readonly static byte[] trunc384 = Hex.Decode("fa9aea2bc1e181e47cbb8c3df243814d"); + readonly static byte[] trunc512 = Hex.Decode("04c929fead434bba190dacfa554ce3f5"); + + readonly static byte[] xtremeData = Hex.Decode("61626364656667686263646566676869636465666768696a6465666768696a6b65666768696a6b6c666768696a6b6c6d6768696a6b6c6d6e68696a6b6c6d6e6f"); + + public override string Name + { + get { return "Keccak"; } + } + + private void TestDigest(IDigest digest, string[] expected) + { + byte[] hash = new byte[digest.GetDigestSize()]; + + for (int i = 0; i != messages.Length; i++) + { + if (messages.Length != 0) + { + byte[] data = Hex.Decode(messages[i]); + + digest.BlockUpdate(data, 0, data.Length); + } + + digest.DoFinal(hash, 0); + + if (!Arrays.AreEqual(Hex.Decode(expected[i]), hash)) + { + Fail("Keccak mismatch on " + digest.AlgorithmName + " index " + i); + } + } + + byte[] k64 = new byte[1024 * 64]; + + for (int i = 0; i != k64.Length; i++) + { + k64[i] = (byte)'a'; + } + + digest.BlockUpdate(k64, 0, k64.Length); + + digest.DoFinal(hash, 0); + + if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length]), hash)) + { + Fail("Keccak mismatch on " + digest.AlgorithmName + " 64k a"); + } + + for (int i = 0; i != k64.Length; i++) + { + digest.Update((byte)'a'); + } + + digest.DoFinal(hash, 0); + + if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length]), hash)) + { + Fail("Keccak mismatch on " + digest.AlgorithmName + " 64k a single"); + } + + + for (int i = 0; i != k64.Length; i++) + { + k64[i] = (byte)('a' + (i % 26)); + } + + digest.BlockUpdate(k64, 0, k64.Length); + + digest.DoFinal(hash, 0); + + if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length + 1]), hash)) + { + Fail("Keccak mismatch on " + digest.AlgorithmName + " 64k alpha"); + } + + for (int i = 0; i != 64; i++) + { + digest.Update(k64[i * 1024]); + digest.BlockUpdate(k64, i * 1024 + 1, 1023); + } + + digest.DoFinal(hash, 0); + + if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length + 1]), hash)) + { + Fail("Keccak mismatch on " + digest.AlgorithmName + " 64k chunked alpha"); + } + + TestDigestDoFinal(digest); + + // + // extremely long data test + // + //Console.WriteLine("Starting very long"); + //for (int i = 0; i != 16384; i++) + //{ + // for (int j = 0; j != 1024; j++) + // { + // digest.BlockUpdate(xtremeData, 0, xtremeData.Length); + // } + //} + + //digest.DoFinal(hash, 0); + + //if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length + 2]), hash)) + //{ + // Fail("Keccak mismatch on " + digest.AlgorithmName + " extreme data test"); + //} + //Console.WriteLine("Done"); + } + + private void TestDigestDoFinal(IDigest digest) + { + byte[] hash = new byte[digest.GetDigestSize()]; + digest.DoFinal(hash, 0); + + for (int i = 0; i <= digest.GetDigestSize(); ++i) + { + byte[] cmp = new byte[2 * digest.GetDigestSize()]; + Array.Copy(hash, 0, cmp, i, hash.Length); + + byte[] buf = new byte[2 * digest.GetDigestSize()]; + digest.DoFinal(buf, i); + + if (!Arrays.AreEqual(cmp, buf)) + { + Fail("Keccak offset DoFinal on " + digest.AlgorithmName); + } + } + } + + private void TestMac(IDigest digest, byte[][] keys, String[] data, String[] expected, byte[] truncExpected) + { + IMac mac = new HMac(digest); + + for (int i = 0; i != keys.Length; i++) + { + mac.Init(new KeyParameter(keys[i])); + + byte[] mData = Hex.Decode(data[i]); + + mac.BlockUpdate(mData, 0, mData.Length); + + byte[] macV = new byte[mac.GetMacSize()]; + + mac.DoFinal(macV, 0); + + if (!Arrays.AreEqual(Hex.Decode(expected[i]), macV)) + { + Fail("Keccak HMAC mismatch on " + digest.AlgorithmName); + } + } + + { + mac = new HMac(digest); + + mac.Init(truncKey); + + mac.BlockUpdate(truncData, 0, truncData.Length); + + byte[] macV = new byte[mac.GetMacSize()]; + + mac.DoFinal(macV, 0); + + for (int i = 0; i != truncExpected.Length; i++) + { + if (macV[i] != truncExpected[i]) + { + Fail("mismatch on truncated HMAC for " + digest.AlgorithmName); + } + } + } + } + + public override void PerformTest() + { + TestDigest(new KeccakDigest(), digests288); + TestDigest(new KeccakDigest(224), digests224); + TestDigest(new KeccakDigest(256), digests256); + TestDigest(new KeccakDigest(384), digests384); + TestDigest(new KeccakDigest(512), digests512); + + TestMac(new KeccakDigest(224), macKeys, macData, mac224, trunc224); + TestMac(new KeccakDigest(256), macKeys, macData, mac256, trunc256); + TestMac(new KeccakDigest(384), macKeys, macData, mac384, trunc384); + TestMac(new KeccakDigest(512), macKeys, macData, mac512, trunc512); + } + + protected virtual IDigest CloneDigest(IDigest digest) + { + return new KeccakDigest((KeccakDigest)digest); + } + + public static void Main( + string[] args) + { + RunTest(new KeccakDigestTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/crypto/test/RegressionTest.cs b/crypto/test/src/crypto/test/RegressionTest.cs index 0b7a0f72d..ab6394571 100644 --- a/crypto/test/src/crypto/test/RegressionTest.cs +++ b/crypto/test/src/crypto/test/RegressionTest.cs @@ -119,7 +119,9 @@ namespace Org.BouncyCastle.Crypto.Tests new Poly1305Test(), new OcbTest(), new SM3DigestTest(), - new X931SignerTest() + new X931SignerTest(), + new KeccakDigestTest(), + new ShakeDigestTest(), }; public static void Main( diff --git a/crypto/test/src/crypto/test/SHA3DigestTest.cs b/crypto/test/src/crypto/test/SHA3DigestTest.cs index 2b8ae4a63..71f51f43b 100644 --- a/crypto/test/src/crypto/test/SHA3DigestTest.cs +++ b/crypto/test/src/crypto/test/SHA3DigestTest.cs @@ -1,11 +1,11 @@ using System; +using System.IO; +using System.Text; using NUnit.Framework; -using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Digests; -using Org.BouncyCastle.Crypto.Macs; -using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Encoders; using Org.BouncyCastle.Utilities.Test; @@ -19,346 +19,218 @@ namespace Org.BouncyCastle.Crypto.Tests public class Sha3DigestTest : SimpleTest { - readonly static string[] messages = { - "", - "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67", - "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f672e" - }; - - readonly static string[] digests288 = { // the default settings - "6753e3380c09e385d0339eb6b050a68f66cfd60a73476e6fd6adeb72f5edd7c6f04a5d01", // message[0] - "0bbe6afae0d7e89054085c1cc47b1689772c89a41796891e197d1ca1b76f288154933ded", // message[1] - "82558a209b960ddeb531e6dcb281885b2400ca160472462486e79f071e88a3330a8a303d", // message[2] - "94049e1ad7ef5d5b0df2b880489e7ab09ec937c3bfc1b04470e503e1ac7b1133c18f86da", // 64k a-test - "a9cb5a75b5b81b7528301e72553ed6770214fa963956e790528afe420de33c074e6f4220", // random alphabet test - "eadaf5ba2ad6a2f6f338fce0e1efdad2a61bb38f6be6068b01093977acf99e97a5d5827c" // extremely long data test - }; - - readonly static string[] digests224 = { - "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd", - "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe", - "c59d4eaeac728671c635ff645014e2afa935bebffdb5fbd207ffdeab", - "f621e11c142fbf35fa8c22841c3a812ba1e0151be4f38d80b9f1ff53", - "68b5fc8c87193155bba68a2485377e809ee4f81a85ef023b9e64add0", - "c42e4aee858e1a8ad2976896b9d23dd187f64436ee15969afdbc68c5" - }; - - readonly static string[] digests256 = { - "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15", - "578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d", - "0047a916daa1f92130d870b542e22d3108444f5a7e4429f05762fb647e6ed9ed", - "db368762253ede6d4f1db87e0b799b96e554eae005747a2ea687456ca8bcbd03", - "5f313c39963dcf792b5470d4ade9f3a356a3e4021748690a958372e2b06f82a4" - }; - - readonly static string[] digests384 = { - "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff", - "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3", - "9ad8e17325408eddb6edee6147f13856ad819bb7532668b605a24a2d958f88bd5c169e56dc4b2f89ffd325f6006d820b", - "c704cfe7a1a53208ca9526cd24251e0acdc252ecd978eee05acd16425cfb404ea81f5a9e2e5e97784d63ee6a0618a398", - "d4fe8586fd8f858dd2e4dee0bafc19b4c12b4e2a856054abc4b14927354931675cdcaf942267f204ea706c19f7beefc4", - "9b7168b4494a80a86408e6b9dc4e5a1837c85dd8ff452ed410f2832959c08c8c0d040a892eb9a755776372d4a8732315" - }; - - readonly static string[] digests512 = { - "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e", - "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609", - "ab7192d2b11f51c7dd744e7b3441febf397ca07bf812cceae122ca4ded6387889064f8db9230f173f6d1ab6e24b6e50f065b039f799f5592360a6558eb52d760", - "34341ead153aa1d1fdcf6cf624c2b4f6894b6fd16dc38bd4ec971ac0385ad54fafcb2e0ed86a1e509456f4246fdcb02c3172824cd649d9ad54c51f7fb49ea67c", - "dc44d4f4d36b07ab5fc04016cbe53548e5a7778671c58a43cb379fd00c06719b8073141fc22191ffc3db5f8b8983ae8341fa37f18c1c969664393aa5ceade64e", - "3e122edaf37398231cfaca4c7c216c9d66d5b899ec1d7ac617c40c7261906a45fc01617a021e5da3bd8d4182695b5cb785a28237cbb167590e34718e56d8aab8" - }; - - // test vectors from http://www.di-mgt.com.au/hmac_sha3_testvectors.html - readonly static byte[][] macKeys = + internal class MySha3Digest : Sha3Digest { - Hex.Decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), - Hex.Decode("4a656665"), - Hex.Decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), - Hex.Decode("0102030405060708090a0b0c0d0e0f10111213141516171819"), - Hex.Decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "aaaaaa"), - Hex.Decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "aaaaaa"), - Hex.Decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") - }; - - readonly static string[] macData = - { - "4869205468657265", - "7768617420646f2079612077616e7420666f72206e6f7468696e673f", - "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + - "dddddddddddddddddddddddddddddddddddd", - "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" + - "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", - "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" + - "65204b6579202d2048617368204b6579204669727374", - "5468697320697320612074657374207573696e672061206c6172676572207468" + - "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" + - "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" + - "647320746f20626520686173686564206265666f7265206265696e6720757365" + - "642062792074686520484d414320616c676f726974686d2e", - "5468697320697320612074657374207573696e672061206c6172676572207468" + - "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" + - "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" + - "647320746f20626520686173686564206265666f7265206265696e6720757365\n" + - "642062792074686520484d414320616c676f726974686d2e" - }; - - readonly static string[] mac224 = - { - "b73d595a2ba9af815e9f2b4e53e78581ebd34a80b3bbaac4e702c4cc", - "e824fec96c074f22f99235bb942da1982664ab692ca8501053cbd414", - "770df38c99d6e2bacd68056dcfe07d4c89ae20b2686a6185e1faa449", - "305a8f2dfb94bad28861a03cbc4d590febe775c58cb4961c28428a0b", - "e7a52dfa45f95a217c100066b239aa8ad519be9b35d667268b1b57ff", - "ba13009405a929f398b348885caa5419191bb948ada32194afc84104", - "92649468be236c3c72c189909c063b13f994be05749dc91310db639e" - }; - - readonly static string[] mac256 = - { - "9663d10c73ee294054dc9faf95647cb99731d12210ff7075fb3d3395abfb9821", - "aa9aed448c7abc8b5e326ffa6a01cdedf7b4b831881468c044ba8dd4566369a1", - "95f43e50f8df80a21977d51a8db3ba572dcd71db24687e6f86f47c1139b26260", - "6331ba9b4af5804a68725b3663eb74814494b63c6093e35fb320a85d507936fd", - "b4d0cdee7ec2ba81a88b86918958312300a15622377929a054a9ce3ae1fac2b6", - "1fdc8cb4e27d07c10d897dec39c217792a6e64fa9c63a77ce42ad106ef284e02", - "fdaa10a0299aecff9bb411cf2d7748a4022e4a26be3fb5b11b33d8c2b7ef5484" - }; - - readonly static string[] mac384 = - { - "892dfdf5d51e4679bf320cd16d4c9dc6f749744608e003add7fba894acff87361efa4e5799be06b6461f43b60ae97048", - "5af5c9a77a23a6a93d80649e562ab77f4f3552e3c5caffd93bdf8b3cfc6920e3023fc26775d9df1f3c94613146ad2c9d", - "4243c29f2201992ff96441e3b91ff81d8c601d706fbc83252684a4bc51101ca9b2c06ddd03677303c502ac5331752a3c", - "b730724d3d4090cda1be799f63acbbe389fef7792fc18676fa5453aab398664650ed029c3498bbe8056f06c658e1e693", - "d62482ef601d7847439b55236e9679388ffcd53c62cd126f39be6ea63de762e26cd5974cb9a8de401b786b5555040f6f", - "4860ea191ac34994cf88957afe5a836ef36e4cc1a66d75bf77defb7576122d75f60660e4cf731c6effac06402787e2b9", - "fe9357e3cfa538eb0373a2ce8f1e26ad6590afdaf266f1300522e8896d27e73f654d0631c8fa598d4bb82af6b744f4f5" - }; - - readonly static string[] mac512 = - { - "8852c63be8cfc21541a4ee5e5a9a852fc2f7a9adec2ff3a13718ab4ed81aaea0b87b7eb397323548e261a64e7fc75198f6663a11b22cd957f7c8ec858a1c7755", - "c2962e5bbe1238007852f79d814dbbecd4682e6f097d37a363587c03bfa2eb0859d8d9c701e04cececfd3dd7bfd438f20b8b648e01bf8c11d26824b96cebbdcb", - "eb0ed9580e0ec11fc66cbb646b1be904eaff6da4556d9334f65ee4b2c85739157bae9027c51505e49d1bb81cfa55e6822db55262d5a252c088a29a5e95b84a66", - "b46193bb59f4f696bf702597616da91e2a4558a593f4b015e69141ba81e1e50ea580834c2b87f87baa25a3a03bfc9bb389847f2dc820beae69d30c4bb75369cb", - "d05888a6ebf8460423ea7bc85ea4ffda847b32df32291d2ce115fd187707325c7ce4f71880d91008084ce24a38795d20e6a28328a0f0712dc38253370da3ebb5", - "2c6b9748d35c4c8db0b4407dd2ed2381f133bdbd1dfaa69e30051eb6badfcca64299b88ae05fdbd3dd3dd7fe627e42e39e48b0fe8c7f1e85f2dbd52c2d753572", - "6adc502f14e27812402fc81a807b28bf8a53c87bea7a1df6256bf66f5de1a4cb741407ad15ab8abc136846057f881969fbb159c321c904bfb557b77afb7778c8" - }; - - readonly static KeyParameter truncKey = new KeyParameter(Hex.Decode("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c")); - readonly static byte[] truncData = Hex.Decode("546573742057697468205472756e636174696f6e"); - - readonly static byte[] trunc224 = Hex.Decode("f52bbcfd654264e7133085c5e69b72c3"); - readonly static byte[] trunc256 = Hex.Decode("745e7e687f8335280d54202ef13cecc6"); - readonly static byte[] trunc384 = Hex.Decode("fa9aea2bc1e181e47cbb8c3df243814d"); - readonly static byte[] trunc512 = Hex.Decode("04c929fead434bba190dacfa554ce3f5"); + internal MySha3Digest(int bitLength) + : base(bitLength) + { + } - readonly static byte[] xtremeData = Hex.Decode("61626364656667686263646566676869636465666768696a6465666768696a6b65666768696a6b6c666768696a6b6c6d6768696a6b6c6d6e68696a6b6c6d6e6f"); + internal int MyDoFinal(byte[] output, int outOff, byte partialByte, int partialBits) + { + return DoFinal(output, outOff, partialByte, partialBits); + } + } public override string Name { - get { return "SHA3"; } + get { return "SHA-3"; } } - private void TestDigest(IDigest digest, string[] expected) + public override void PerformTest() { - byte[] hash = new byte[digest.GetDigestSize()]; + TestVectors(); + } - for (int i = 0; i != messages.Length; i++) + public void TestVectors() + { + using (StreamReader r = new StreamReader(SimpleTest.GetTestDataAsStream("crypto.SHA3TestVectors.txt"))) { - if (messages.Length != 0) - { - byte[] data = Hex.Decode(messages[i]); - - digest.BlockUpdate(data, 0, data.Length); - } - - digest.DoFinal(hash, 0); - - if (!Arrays.AreEqual(Hex.Decode(expected[i]), hash)) + String line; + while (null != (line = ReadLine(r))) { - Fail("sha3 mismatch on " + digest.AlgorithmName + " index " + i); + if (line.Length != 0) + { + TestVector v = ReadTestVector(r, line); + RunTestVector(v); + } } } + } - byte[] k64 = new byte[1024 * 64]; - - for (int i = 0; i != k64.Length; i++) + private MySha3Digest CreateDigest(string algorithm) + { + if (algorithm.StartsWith("SHA3-")) { - k64[i] = (byte)'a'; + int bits = ParseDecimal(algorithm.Substring("SHA3-".Length)); + return new MySha3Digest(bits); } + throw new ArgumentException("Unknown algorithm: " + algorithm, "algorithm"); + } - digest.BlockUpdate(k64, 0, k64.Length); - - digest.DoFinal(hash, 0); + private byte[] DecodeBinary(string block) + { + int bits = block.Length; + int fullBytes = bits / 8; + int totalBytes = (bits + 7) / 8; + byte[] result = new byte[totalBytes]; - if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length]), hash)) + for (int i = 0; i < fullBytes; ++i) { - Fail("sha3 mismatch on " + digest.AlgorithmName + " 64k a"); + string byteStr = Reverse(block.Substring(i * 8, 8)); + result[i] = (byte)ParseBinary(byteStr); } - for (int i = 0; i != k64.Length; i++) + if (totalBytes > fullBytes) { - digest.Update((byte)'a'); + string byteStr = Reverse(block.Substring(fullBytes * 8)); + result[fullBytes] = (byte)ParseBinary(byteStr); } - digest.DoFinal(hash, 0); + return result; + } - if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length]), hash)) - { - Fail("sha3 mismatch on " + digest.AlgorithmName + " 64k a single"); - } + private int ParseBinary(string s) + { + return new BigInteger(s, 2).IntValue; + } + private int ParseDecimal(string s) + { + return Int32.Parse(s); + } - for (int i = 0; i != k64.Length; i++) + private string ReadBlock(StreamReader r) + { + StringBuilder b = new StringBuilder(); + string line; + while ((line = ReadBlockLine(r)) != null) { - k64[i] = (byte)('a' + (i % 26)); + b.Append(line); } + return b.ToString(); + } - digest.BlockUpdate(k64, 0, k64.Length); - - digest.DoFinal(hash, 0); - - if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length + 1]), hash)) + private string ReadBlockLine(StreamReader r) + { + string line = ReadLine(r); + if (line == null || line.Length == 0) { - Fail("sha3 mismatch on " + digest.AlgorithmName + " 64k alpha"); + return null; } + return line.Replace(" ", ""); + } - for (int i = 0; i != 64; i++) - { - digest.Update(k64[i * 1024]); - digest.BlockUpdate(k64, i * 1024 + 1, 1023); - } + private TestVector ReadTestVector(StreamReader r, string header) + { + string[] parts = SplitAround(header, TestVector.SAMPLE_OF); - digest.DoFinal(hash, 0); + string algorithm = parts[0]; + int bits = ParseDecimal(StripFromChar(parts[1], '-')); - if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length + 1]), hash)) + SkipUntil(r, TestVector.MSG_HEADER); + string messageBlock = ReadBlock(r); + if (messageBlock.Length != bits) { - Fail("sha3 mismatch on " + digest.AlgorithmName + " 64k chunked alpha"); + throw new InvalidOperationException("Test vector length mismatch"); } + byte[] message = DecodeBinary(messageBlock); + + SkipUntil(r, TestVector.HASH_HEADER); + byte[] hash = Hex.Decode(ReadBlock(r)); - TestDigestDoFinal(digest); - - // - // extremely long data test - // - //Console.WriteLine("Starting very long"); - //for (int i = 0; i != 16384; i++) - //{ - // for (int j = 0; j != 1024; j++) - // { - // digest.BlockUpdate(xtremeData, 0, xtremeData.Length); - // } - //} - - //digest.DoFinal(hash, 0); - - //if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length + 2]), hash)) - //{ - // Fail("sha3 mismatch on " + digest.AlgorithmName + " extreme data test"); - //} - //Console.WriteLine("Done"); + return new TestVector(algorithm, bits, message, hash); } - private void TestDigestDoFinal(IDigest digest) + private string ReadLine(StreamReader r) { - byte[] hash = new byte[digest.GetDigestSize()]; - digest.DoFinal(hash, 0); + string line = r.ReadLine(); + return line == null ? null : StripFromChar(line, '#').Trim(); + } - for (int i = 0; i <= digest.GetDigestSize(); ++i) + private string RequireLine(StreamReader r) + { + string line = ReadLine(r); + if (line == null) { - byte[] cmp = new byte[2 * digest.GetDigestSize()]; - Array.Copy(hash, 0, cmp, i, hash.Length); - - byte[] buf = new byte[2 * digest.GetDigestSize()]; - digest.DoFinal(buf, i); - - if (!Arrays.AreEqual(cmp, buf)) - { - Fail("sha3 offset DoFinal on " + digest.AlgorithmName); - } + throw new EndOfStreamException(); } + return line; } - private void TestMac(IDigest digest, byte[][] keys, String[] data, String[] expected, byte[] truncExpected) + private string Reverse(string s) { - IMac mac = new HMac(digest); - - for (int i = 0; i != keys.Length; i++) - { - mac.Init(new KeyParameter(keys[i])); - - byte[] mData = Hex.Decode(data[i]); + char[] cs = s.ToCharArray(); + Array.Reverse(cs); + return new string(cs); + } - mac.BlockUpdate(mData, 0, mData.Length); + private void RunTestVector(TestVector v) + { + int bits = v.Bits; + int partialBits = bits % 8; - byte[] macV = new byte[mac.GetMacSize()]; + //Console.WriteLine(v.Algorithm + " " + bits + "-bit"); + //Console.WriteLine(Hex.ToHexString(v.Message).ToUpper()); + //Console.WriteLine(Hex.ToHexString(v.Hash).ToUpper()); - mac.DoFinal(macV, 0); + MySha3Digest d = CreateDigest(v.Algorithm); + byte[] output = new byte[d.GetDigestSize()]; - if (!Arrays.AreEqual(Hex.Decode(expected[i]), macV)) - { - Fail("sha3 HMAC mismatch on " + digest.AlgorithmName); - } + byte[] m = v.Message; + if (partialBits == 0) + { + d.BlockUpdate(m, 0, m.Length); + d.DoFinal(output, 0); } - + else { - mac = new HMac(digest); - - mac.Init(truncKey); - - mac.BlockUpdate(truncData, 0, truncData.Length); - - byte[] macV = new byte[mac.GetMacSize()]; + d.BlockUpdate(m, 0, m.Length - 1); + d.MyDoFinal(output, 0, m[m.Length - 1], partialBits); + } - mac.DoFinal(macV, 0); + if (!Arrays.AreEqual(v.Hash, output)) + { + Fail(v.Algorithm + " " + v.Bits + "-bit test vector hash mismatch"); + //Console.Error.WriteLine(v.Algorithm + " " + v.Bits + "-bit test vector hash mismatch"); + //Console.Error.WriteLine(Hex.ToHexString(output).ToUpper()); + } + } - for (int i = 0; i != truncExpected.Length; i++) - { - if (macV[i] != truncExpected[i]) - { - Fail("mismatch on truncated HMAC for " + digest.AlgorithmName); - } - } + private void SkipUntil(StreamReader r, string header) + { + string line; + do + { + line = RequireLine(r); + } + while (line.Length == 0); + if (!line.Equals(header)) + { + throw new IOException("Expected: " + header); } } - public override void PerformTest() + private string[] SplitAround(string s, string separator) { - TestDigest(new Sha3Digest(), digests288); - TestDigest(new Sha3Digest(224), digests224); - TestDigest(new Sha3Digest(256), digests256); - TestDigest(new Sha3Digest(384), digests384); - TestDigest(new Sha3Digest(512), digests512); - - TestMac(new Sha3Digest(224), macKeys, macData, mac224, trunc224); - TestMac(new Sha3Digest(256), macKeys, macData, mac256, trunc256); - TestMac(new Sha3Digest(384), macKeys, macData, mac384, trunc384); - TestMac(new Sha3Digest(512), macKeys, macData, mac512, trunc512); + int i = s.IndexOf(separator); + if (i < 0) + throw new InvalidOperationException(); + return new string[] { s.Substring(0, i), s.Substring(i + separator.Length) }; } - protected virtual IDigest CloneDigest(IDigest digest) + private string StripFromChar(string s, char c) { - return new Sha3Digest((Sha3Digest)digest); + int i = s.IndexOf(c); + if (i >= 0) + { + s = s.Substring(0, i); + } + return s; } public static void Main( - string[] args) + string[] args) { RunTest(new Sha3DigestTest()); } @@ -370,5 +242,45 @@ namespace Org.BouncyCastle.Crypto.Tests Assert.AreEqual(Name + ": Okay", resultText); } + + internal class TestVector + { + internal static string SAMPLE_OF = " sample of "; + internal static string MSG_HEADER = "Msg as bit string"; + internal static string HASH_HEADER = "Hash val is"; + + private readonly string algorithm; + private readonly int bits; + private readonly byte[] message; + private readonly byte[] hash; + + internal TestVector(string algorithm, int bits, byte[] message, byte[] hash) + { + this.algorithm = algorithm; + this.bits = bits; + this.message = message; + this.hash = hash; + } + + public string Algorithm + { + get { return algorithm; } + } + + public int Bits + { + get { return bits; } + } + + public byte[] Message + { + get { return message; } + } + + public byte[] Hash + { + get { return hash; } + } + } } } diff --git a/crypto/test/src/crypto/test/ShakeDigestTest.cs b/crypto/test/src/crypto/test/ShakeDigestTest.cs new file mode 100644 index 000000000..ef4696739 --- /dev/null +++ b/crypto/test/src/crypto/test/ShakeDigestTest.cs @@ -0,0 +1,290 @@ +using System; +using System.IO; +using System.Text; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + /** + * SHAKE Digest Test + */ + [TestFixture] + public class ShakeDigestTest + : SimpleTest + { + internal class MyShakeDigest : ShakeDigest + { + internal MyShakeDigest(int bitLength) + : base(bitLength) + { + } + + internal int MyDoFinal(byte[] output, int outOff, int outLen, byte partialByte, int partialBits) + { + return DoFinal(output, outOff, outLen, partialByte, partialBits); + } + } + + public override string Name + { + get { return "SHAKE"; } + } + + public override void PerformTest() + { + TestVectors(); + } + + public void TestVectors() + { + using (StreamReader r = new StreamReader(SimpleTest.GetTestDataAsStream("crypto.SHAKETestVectors.txt"))) + { + String line; + while (null != (line = ReadLine(r))) + { + if (line.Length != 0) + { + TestVector v = ReadTestVector(r, line); + RunTestVector(v); + } + } + } + } + + private MyShakeDigest CreateDigest(string algorithm) + { + if (algorithm.StartsWith("SHAKE-")) + { + int bits = ParseDecimal(algorithm.Substring("SHAKE-".Length)); + return new MyShakeDigest(bits); + } + throw new ArgumentException("Unknown algorithm: " + algorithm, "algorithm"); + } + + private byte[] DecodeBinary(string block) + { + int bits = block.Length; + int fullBytes = bits / 8; + int totalBytes = (bits + 7) / 8; + byte[] result = new byte[totalBytes]; + + for (int i = 0; i < fullBytes; ++i) + { + string byteStr = Reverse(block.Substring(i * 8, 8)); + result[i] = (byte)ParseBinary(byteStr); + } + + if (totalBytes > fullBytes) + { + string byteStr = Reverse(block.Substring(fullBytes * 8)); + result[fullBytes] = (byte)ParseBinary(byteStr); + } + + return result; + } + + private int ParseBinary(string s) + { + return new BigInteger(s, 2).IntValue; + } + + private int ParseDecimal(string s) + { + return Int32.Parse(s); + } + + private string ReadBlock(StreamReader r) + { + StringBuilder b = new StringBuilder(); + string line; + while ((line = ReadBlockLine(r)) != null) + { + b.Append(line); + } + return b.ToString(); + } + + private string ReadBlockLine(StreamReader r) + { + string line = ReadLine(r); + if (line == null || line.Length == 0) + { + return null; + } + return line.Replace(" ", ""); + } + + private TestVector ReadTestVector(StreamReader r, string header) + { + string[] parts = SplitAround(header, TestVector.SAMPLE_OF); + + string algorithm = parts[0]; + int bits = ParseDecimal(StripFromChar(parts[1], '-')); + + SkipUntil(r, TestVector.MSG_HEADER); + string messageBlock = ReadBlock(r); + if (messageBlock.Length != bits) + { + throw new InvalidOperationException("Test vector length mismatch"); + } + byte[] message = DecodeBinary(messageBlock); + + SkipUntil(r, TestVector.OUTPUT_HEADER); + byte[] output = Hex.Decode(ReadBlock(r)); + + return new TestVector(algorithm, bits, message, output); + } + + private string ReadLine(StreamReader r) + { + string line = r.ReadLine(); + return line == null ? null : StripFromChar(line, '#').Trim(); + } + + private string RequireLine(StreamReader r) + { + string line = ReadLine(r); + if (line == null) + { + throw new EndOfStreamException(); + } + return line; + } + + private string Reverse(string s) + { + char[] cs = s.ToCharArray(); + Array.Reverse(cs); + return new string(cs); + } + + private void RunTestVector(TestVector v) + { + int bits = v.Bits; + int partialBits = bits % 8; + + byte[] expected = v.Output; + + //Console.WriteLine(v.Algorithm + " " + bits + "-bit"); + //Console.WriteLine(Hex.ToHexString(v.Message).ToUpper()); + //Console.WriteLine(Hex.ToHexString(expected).ToUpper()); + + int outLen = expected.Length; + + MyShakeDigest d = CreateDigest(v.Algorithm); + byte[] output = new byte[outLen]; + + byte[] m = v.Message; + if (partialBits == 0) + { + d.BlockUpdate(m, 0, m.Length); + d.DoFinal(output, 0, outLen); + } + else + { + d.BlockUpdate(m, 0, m.Length - 1); + d.MyDoFinal(output, 0, outLen, m[m.Length - 1], partialBits); + } + + if (!Arrays.AreEqual(expected, output)) + { + Fail(v.Algorithm + " " + v.Bits + "-bit test vector hash mismatch"); + //Console.Error.WriteLine(v.Algorithm + " " + v.Bits + "-bit test vector hash mismatch"); + //Console.Error.WriteLine(Hex.ToHexString(output).ToUpper()); + } + } + + private void SkipUntil(StreamReader r, string header) + { + string line; + do + { + line = RequireLine(r); + } + while (line.Length == 0); + if (!line.Equals(header)) + { + throw new IOException("Expected: " + header); + } + } + + private string[] SplitAround(string s, string separator) + { + int i = s.IndexOf(separator); + if (i < 0) + throw new InvalidOperationException(); + return new string[] { s.Substring(0, i), s.Substring(i + separator.Length) }; + } + + private string StripFromChar(string s, char c) + { + int i = s.IndexOf(c); + if (i >= 0) + { + s = s.Substring(0, i); + } + return s; + } + + public static void Main( + string[] args) + { + RunTest(new ShakeDigestTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + internal class TestVector + { + internal static string SAMPLE_OF = " sample of "; + internal static string MSG_HEADER = "Msg as bit string"; + internal static string OUTPUT_HEADER = "Output val is"; + + private readonly string algorithm; + private readonly int bits; + private readonly byte[] message; + private readonly byte[] output; + + internal TestVector(string algorithm, int bits, byte[] message, byte[] output) + { + this.algorithm = algorithm; + this.bits = bits; + this.message = message; + this.output = output; + } + + public string Algorithm + { + get { return algorithm; } + } + + public int Bits + { + get { return bits; } + } + + public byte[] Message + { + get { return message; } + } + + public byte[] Output + { + get { return output; } + } + } + } +} diff --git a/crypto/test/src/math/ec/test/ECPointTest.cs b/crypto/test/src/math/ec/test/ECPointTest.cs index 2a62b7740..3c10170f7 100644 --- a/crypto/test/src/math/ec/test/ECPointTest.cs +++ b/crypto/test/src/math/ec/test/ECPointTest.cs @@ -487,23 +487,62 @@ namespace Org.BouncyCastle.Math.EC.Tests foreach (string name in uniqNames) { - X9ECParameters x9ECParameters = ECNamedCurveTable.GetByName(name); - if (x9ECParameters != null) + X9ECParameters x9A = ECNamedCurveTable.GetByName(name); + X9ECParameters x9B = CustomNamedCurves.GetByName(name); + + if (x9A != null && x9B != null) + { + Assert.AreEqual(x9A.Curve.Field, x9B.Curve.Field); + Assert.AreEqual(x9A.Curve.A.ToBigInteger(), x9B.Curve.A.ToBigInteger()); + Assert.AreEqual(x9A.Curve.B.ToBigInteger(), x9B.Curve.B.ToBigInteger()); + AssertOptionalValuesAgree(x9A.Curve.Cofactor, x9B.Curve.Cofactor); + AssertOptionalValuesAgree(x9A.Curve.Order, x9B.Curve.Order); + + AssertPointsEqual("Custom curve base-point inconsistency", x9A.G, x9B.G); + + Assert.AreEqual(x9A.H, x9B.H); + Assert.AreEqual(x9A.N, x9B.N); + AssertOptionalValuesAgree(x9A.GetSeed(), x9B.GetSeed()); + + BigInteger k = new BigInteger(x9A.N.BitLength, secRand); + ECPoint pA = x9A.G.Multiply(k); + ECPoint pB = x9B.G.Multiply(k); + AssertPointsEqual("Custom curve multiplication inconsistency", pA, pB); + } + + if (x9A != null) { - ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(x9ECParameters); + ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(x9A); } - x9ECParameters = CustomNamedCurves.GetByName(name); - if (x9ECParameters != null) + if (x9B != null) { - ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(x9ECParameters); + ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(x9B); } } } private void AssertPointsEqual(string message, ECPoint a, ECPoint b) { + // NOTE: We intentionally test points for equality in both directions Assert.AreEqual(a, b, message); + Assert.AreEqual(b, a, message); + } + + private void AssertOptionalValuesAgree(object a, object b) + { + if (a != null && b != null) + { + Assert.AreEqual(a, b); + } + } + + private void AssertOptionalValuesAgree(byte[] a, byte[] b) + { + if (a != null && b != null) + { + Assert.IsTrue(Arrays.AreEqual(a, b)); + } } } } |