From bd1f720cafbcbf30891a286718ee91c44e1c8a4e Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 17 Apr 2018 10:41:26 +0700 Subject: Add X25519 and X448 from RFC 7748 - includes optimized ladders for base points --- crypto/test/src/math/ec/rfc7748/test/X25519Test.cs | 184 +++++++++++++++++++++ crypto/test/src/math/ec/rfc7748/test/X448Test.cs | 183 ++++++++++++++++++++ 2 files changed, 367 insertions(+) create mode 100644 crypto/test/src/math/ec/rfc7748/test/X25519Test.cs create mode 100644 crypto/test/src/math/ec/rfc7748/test/X448Test.cs (limited to 'crypto/test/src/math/ec') diff --git a/crypto/test/src/math/ec/rfc7748/test/X25519Test.cs b/crypto/test/src/math/ec/rfc7748/test/X25519Test.cs new file mode 100644 index 000000000..89c325fd5 --- /dev/null +++ b/crypto/test/src/math/ec/rfc7748/test/X25519Test.cs @@ -0,0 +1,184 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Rfc7748.Tests +{ + [TestFixture] + public class X25519Test + { + private static readonly SecureRandom Random = new SecureRandom(); + + [SetUp] + public void SetUp() + { + X25519.Precompute(); + } + + [Test] + public void TestConsistency() + { + byte[] u = new byte[32]; u[0] = 9; + byte[] k = new byte[32]; + byte[] rF = new byte[32]; + byte[] rV = new byte[32]; + + for (int i = 1; i <= 100; ++i) + { + Random.NextBytes(k); + X25519.ScalarMultBase(k, 0, rF, 0); + X25519.ScalarMult(k, 0, u, 0, rV, 0); + Assert.IsTrue(Arrays.AreEqual(rF, rV), "Consistency #" + i); + } + } + + [Test] + public void TestECDH() + { + byte[] kA = new byte[32]; + byte[] kB = new byte[32]; + byte[] qA = new byte[32]; + byte[] qB = new byte[32]; + byte[] sA = new byte[32]; + byte[] sB = new byte[32]; + + for (int i = 1; i <= 100; ++i) + { + // Each party generates an ephemeral private key, ... + Random.NextBytes(kA); + Random.NextBytes(kB); + + // ... publishes their public key, ... + X25519.ScalarMultBase(kA, 0, qA, 0); + X25519.ScalarMultBase(kB, 0, qB, 0); + + // ... computes the shared secret, ... + X25519.ScalarMult(kA, 0, qB, 0, sA, 0); + X25519.ScalarMult(kB, 0, qA, 0, sB, 0); + + // ... which is the same for both parties. + //Assert.IsTrue(Arrays.AreEqual(sA, sB), "ECDH #" + i); + if (!Arrays.AreEqual(sA, sB)) + { + Console.WriteLine(" " + i); + } + } + } + + [Test] + public void TestECDHVector1() + { + CheckECDHVector( + "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a", + "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a", + "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb", + "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f", + "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742", + "ECDH Vector #1"); + } + + [Test] + public void TestX25519Iterated() + { + CheckIterated(1000); + } + + //[Test, Explicit] + //public void TestX25519IteratedFull() + //{ + // CheckIterated(1000000); + //} + + [Test] + public void TestX25519Vector1() + { + CheckX25519Vector( + "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", + "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c", + "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552", + "Vector #1"); + } + + [Test] + public void TestX25519Vector2() + { + CheckX25519Vector( + "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d", + "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493", + "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957", + "Vector #2"); + } + + private static void CheckECDHVector(string sA, string sAPub, string sB, string sBPub, string sK, string text) + { + byte[] a = Hex.Decode(sA); + byte[] b = Hex.Decode(sB); + + byte[] aPub = new byte[32]; + X25519.ScalarMultBase(a, 0, aPub, 0); + CheckValue(aPub, text, sAPub); + + byte[] bPub = new byte[32]; + X25519.ScalarMultBase(b, 0, bPub, 0); + CheckValue(bPub, text, sBPub); + + byte[] aK = new byte[32]; + X25519.ScalarMult(a, 0, bPub, 0, aK, 0); + CheckValue(aK, text, sK); + + byte[] bK = new byte[32]; + X25519.ScalarMult(b, 0, aPub, 0, bK, 0); + CheckValue(bK, text, sK); + } + + private static void CheckIterated(int count) + { + byte[] k = new byte[32]; k[0] = 9; + byte[] u = new byte[32]; u[0] = 9; + byte[] r = new byte[32]; + + int iterations = 0; + while (iterations < count) + { + X25519.ScalarMult(k, 0, u, 0, r, 0); + + Array.Copy(k, 0, u, 0, 32); + Array.Copy(r, 0, k, 0, 32); + + switch (++iterations) + { + case 1: + CheckValue(k, "Iterated @1", "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079"); + break; + case 1000: + CheckValue(k, "Iterated @1000", "684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51"); + break; + case 1000000: + CheckValue(k, "Iterated @1000000", "7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424"); + break; + default: + break; + } + } + } + + private static void CheckValue(byte[] n, string text, string se) + { + byte[] e = Hex.Decode(se); + Assert.IsTrue(Arrays.AreEqual(e, n), text); + } + + private static void CheckX25519Vector(string sk, string su, string se, string text) + { + byte[] k = Hex.Decode(sk); + byte[] u = Hex.Decode(su); + byte[] r = new byte[32]; + X25519.ScalarMult(k, 0, u, 0, r, 0); + CheckValue(r, text, se); + } + } +} diff --git a/crypto/test/src/math/ec/rfc7748/test/X448Test.cs b/crypto/test/src/math/ec/rfc7748/test/X448Test.cs new file mode 100644 index 000000000..b095eade0 --- /dev/null +++ b/crypto/test/src/math/ec/rfc7748/test/X448Test.cs @@ -0,0 +1,183 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; + +namespace Org.BouncyCastle.Math.EC.Rfc7748.Tests +{ + [TestFixture] + public class X448Test + { + private static readonly SecureRandom Random = new SecureRandom(); + + [SetUp] + public void SetUp() + { + X448.Precompute(); + } + + [Test] + public void TestConsistency() + { + byte[] u = new byte[56]; u[0] = 5; + byte[] k = new byte[56]; + byte[] rF = new byte[56]; + byte[] rV = new byte[56]; + + for (int i = 1; i <= 100; ++i) + { + Random.NextBytes(k); + X448.ScalarMultBase(k, 0, rF, 0); + X448.ScalarMult(k, 0, u, 0, rV, 0); + Assert.IsTrue(Arrays.AreEqual(rF, rV), "Consistency #" + i); + } + } + + [Test] + public void TestECDH() + { + byte[] kA = new byte[56]; + byte[] kB = new byte[56]; + byte[] qA = new byte[56]; + byte[] qB = new byte[56]; + byte[] sA = new byte[56]; + byte[] sB = new byte[56]; + + for (int i = 1; i <= 100; ++i) + { + // Each party generates an ephemeral private key, ... + Random.NextBytes(kA); + Random.NextBytes(kB); + + // ... publishes their public key, ... + X448.ScalarMultBase(kA, 0, qA, 0); + X448.ScalarMultBase(kB, 0, qB, 0); + + // ... computes the shared secret, ... + X448.ScalarMult(kA, 0, qB, 0, sA, 0); + X448.ScalarMult(kB, 0, qA, 0, sB, 0); + + // ... which is the same for both parties. + Assert.IsTrue(Arrays.AreEqual(sA, sB), "ECDH #" + i); + } + } + + [Test] + public void TestECDHVector1() + { + CheckECDHVector( + "9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b", + "9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0", + "1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d", + "3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609", + "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d", + "ECDH Vector #1"); + } + + [Test] + public void TestX448Iterated() + { + CheckIterated(1000); + } + + //[Test, Explicit] + //public void TestX448IteratedFull() + //{ + // CheckIterated(1000000); + //} + + [Test] + public void TestX448Vector1() + { + CheckX448Vector( + "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3", + "06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086", + "ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f", + "Vector #1"); + } + + [Test] + public void TestX448Vector2() + { + CheckX448Vector( + "203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f", + "0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db", + "884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d", + "Vector #2"); + } + + private static void CheckECDHVector(string sA, string sAPub, string sB, string sBPub, string sK, string text) + { + byte[] a = Hex.Decode(sA); + byte[] b = Hex.Decode(sB); + + byte[] aPub = new byte[56]; + X448.ScalarMultBase(a, 0, aPub, 0); + CheckValue(aPub, text, sAPub); + + byte[] bPub = new byte[56]; + X448.ScalarMultBase(b, 0, bPub, 0); + CheckValue(bPub, text, sBPub); + + byte[] aK = new byte[56]; + X448.ScalarMult(a, 0, bPub, 0, aK, 0); + CheckValue(aK, text, sK); + + byte[] bK = new byte[56]; + X448.ScalarMult(b, 0, aPub, 0, bK, 0); + CheckValue(bK, text, sK); + } + + private static void CheckIterated(int count) + { + byte[] k = new byte[56]; k[0] = 5; + byte[] u = new byte[56]; u[0] = 5; + byte[] r = new byte[56]; + + int iterations = 0; + while (iterations < count) + { + X448.ScalarMult(k, 0, u, 0, r, 0); + + Array.Copy(k, 0, u, 0, 56); + Array.Copy(r, 0, k, 0, 56); + + switch (++iterations) + { + case 1: + CheckValue(k, "Iterated @1", + "3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113"); + break; + case 1000: + CheckValue(k, "Iterated @1000", + "aa3b4749d55b9daf1e5b00288826c467274ce3ebbdd5c17b975e09d4af6c67cf10d087202db88286e2b79fceea3ec353ef54faa26e219f38"); + break; + case 1000000: + CheckValue(k, "Iterated @1000000", + "077f453681caca3693198420bbe515cae0002472519b3e67661a7e89cab94695c8f4bcd66e61b9b9c946da8d524de3d69bd9d9d66b997e37"); + break; + default: + break; + } + } + } + + private static void CheckValue(byte[] n, String text, String se) + { + byte[] e = Hex.Decode(se); + Assert.IsTrue(Arrays.AreEqual(e, n), text); + } + + private static void CheckX448Vector(String sk, String su, String se, String text) + { + byte[] k = Hex.Decode(sk); + byte[] u = Hex.Decode(su); + byte[] r = new byte[56]; + X448.ScalarMult(k, 0, u, 0, r, 0); + CheckValue(r, text, se); + } + } +} -- cgit 1.4.1