aboutsummaryrefslogtreecommitdiff
path: root/Tools/Hazel-Networking/Hazel.UnitTests/Crypto
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/Hazel-Networking/Hazel.UnitTests/Crypto')
-rw-r--r--Tools/Hazel-Networking/Hazel.UnitTests/Crypto/AesGcmTest.cs255
-rw-r--r--Tools/Hazel-Networking/Hazel.UnitTests/Crypto/Sha256Tests.cs70
-rw-r--r--Tools/Hazel-Networking/Hazel.UnitTests/Crypto/X25519Tests.cs297
3 files changed, 622 insertions, 0 deletions
diff --git a/Tools/Hazel-Networking/Hazel.UnitTests/Crypto/AesGcmTest.cs b/Tools/Hazel-Networking/Hazel.UnitTests/Crypto/AesGcmTest.cs
new file mode 100644
index 0000000..9620973
--- /dev/null
+++ b/Tools/Hazel-Networking/Hazel.UnitTests/Crypto/AesGcmTest.cs
@@ -0,0 +1,255 @@
+using Hazel.Crypto;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Text;
+
+namespace Hazel.UnitTests.Crypto
+{
+ [TestClass]
+ public class AesGcmTest
+ {
+ [TestMethod]
+ public void Example1()
+ {
+ byte[] key = Utils.HexToBytes("FEFFE992 8665731C 6D6A8F94 67308308");
+ byte[] nonce = Utils.HexToBytes("CAFEBABE FACEDBAD DECAF888");
+ byte[] associatedData = Utils.HexToBytes("");
+
+ using (Aes128Gcm aes = new Aes128Gcm(key))
+ {
+ byte[] plaintext = Utils.HexToBytes("");
+ byte[] ciphertextBytes = new byte[plaintext.Length + Aes128Gcm.CiphertextOverhead];
+ aes.Seal(ciphertextBytes, nonce, plaintext, associatedData);
+
+ CollectionAssert.AreEqual(Utils.HexToBytes("3247184B 3C4F69A4 4DBCD228 87BBB418"), ciphertextBytes);
+ }
+
+ using (Aes128Gcm aes = new Aes128Gcm(key))
+ {
+ byte[] ciphertext = Utils.HexToBytes("3247184B 3C4F69A4 4DBCD228 87BBB418");
+ byte[] plaintext = new byte[ciphertext.Length - Aes128Gcm.CiphertextOverhead];
+ bool result = aes.Open(plaintext, nonce, ciphertext, associatedData);
+ Assert.IsTrue(result);
+ CollectionAssert.AreEqual(Utils.HexToBytes(""), plaintext);
+ }
+ }
+
+ [TestMethod]
+ public void Example2()
+ {
+ byte[] key = Utils.HexToBytes("FEFFE992 8665731C 6D6A8F94 67308308");
+ byte[] nonce = Utils.HexToBytes("CAFEBABE FACEDBAD DECAF888");
+ byte[] associatedData = Utils.HexToBytes("");
+
+ using (Aes128Gcm aes = new Aes128Gcm(key))
+ {
+ byte[] plaintext = Utils.HexToBytes(@"
+ D9313225 F88406E5 A55909C5 AFF5269A
+ 86A7A953 1534F7DA 2E4C303D 8A318A72
+ 1C3C0C95 95680953 2FCF0E24 49A6B525
+ B16AEDF5 AA0DE657 BA637B39 1AAFD255
+ ");
+ byte[] ciphertextBytes = new byte[plaintext.Length + Aes128Gcm.CiphertextOverhead];
+ aes.Seal(ciphertextBytes, nonce, plaintext, associatedData);
+
+ CollectionAssert.AreEqual(Utils.HexToBytes(@"
+ 42831EC2 21777424 4B7221B7 84D0D49C
+ E3AA212F 2C02A4E0 35C17E23 29ACA12E
+ 21D514B2 5466931C 7D8F6A5A AC84AA05
+ 1BA30B39 6A0AAC97 3D58E091 473F5985
+
+ 4D5C2AF3 27CD64A6 2CF35ABD 2BA6FAB4
+ "), ciphertextBytes);
+ }
+
+ using (Aes128Gcm aes = new Aes128Gcm(key))
+ {
+ byte[] ciphertext = Utils.HexToBytes(@"
+ 42831EC2 21777424 4B7221B7 84D0D49C
+ E3AA212F 2C02A4E0 35C17E23 29ACA12E
+ 21D514B2 5466931C 7D8F6A5A AC84AA05
+ 1BA30B39 6A0AAC97 3D58E091 473F5985
+
+ 4D5C2AF3 27CD64A6 2CF35ABD 2BA6FAB4
+ ");
+ byte[] plaintext = new byte[ciphertext.Length - Aes128Gcm.CiphertextOverhead];
+ bool result = aes.Open(plaintext, nonce, ciphertext, associatedData);
+ Assert.IsTrue(result);
+
+ CollectionAssert.AreEqual(Utils.HexToBytes(@"
+ D9313225 F88406E5 A55909C5 AFF5269A
+ 86A7A953 1534F7DA 2E4C303D 8A318A72
+ 1C3C0C95 95680953 2FCF0E24 49A6B525
+ B16AEDF5 AA0DE657 BA637B39 1AAFD255
+ "), plaintext);
+ }
+ }
+
+ [TestMethod]
+ public void Example3()
+ {
+ byte[] key = Utils.HexToBytes("FEFFE992 8665731C 6D6A8F94 67308308");
+ byte[] nonce = Utils.HexToBytes("CAFEBABE FACEDBAD DECAF888");
+ byte[] associatedData = Utils.HexToBytes(@"
+ 3AD77BB4 0D7A3660 A89ECAF3 2466EF97
+ F5D3D585 03B9699D E785895A 96FDBAAF
+ 43B1CD7F 598ECE23 881B00E3 ED030688
+ 7B0C785E 27E8AD3F 82232071 04725DD4
+ ");
+
+ using (Aes128Gcm aes = new Aes128Gcm(key))
+ {
+ byte[] plaintext = Utils.HexToBytes("");
+ byte[] ciphertextBytes = new byte[plaintext.Length + Aes128Gcm.CiphertextOverhead];
+ aes.Seal(ciphertextBytes, nonce, plaintext, associatedData);
+
+ CollectionAssert.AreEqual(Utils.HexToBytes(@"
+ 5F91D771 23EF5EB9 99791384 9B8DC1E9
+ "), ciphertextBytes);
+ }
+
+ using (Aes128Gcm aes = new Aes128Gcm(key))
+ {
+ byte[] ciphertext = Utils.HexToBytes(@"
+ 5F91D771 23EF5EB9 99791384 9B8DC1E9
+ ");
+ byte[] plaintext = new byte[ciphertext.Length - Aes128Gcm.CiphertextOverhead];
+ bool result = aes.Open(plaintext, nonce, ciphertext, associatedData);
+ Assert.IsTrue(result);
+
+ CollectionAssert.AreEqual(Utils.HexToBytes(""), plaintext);
+ }
+ }
+
+ [TestMethod]
+ public void Example4()
+ {
+ byte[] key = Utils.HexToBytes("FEFFE992 8665731C 6D6A8F94 67308308");
+ byte[] nonce = Utils.HexToBytes("CAFEBABE FACEDBAD DECAF888");
+ byte[] associatedData = Utils.HexToBytes(@"
+ 3AD77BB4 0D7A3660 A89ECAF3 2466EF97
+ F5D3D585 03B9699D E785895A 96FDBAAF
+ 43B1CD7F 598ECE23 881B00E3 ED030688
+ 7B0C785E 27E8AD3F 82232071 04725DD4
+ ");
+
+ using (Aes128Gcm aes = new Aes128Gcm(key))
+ {
+ byte[] plaintext = Utils.HexToBytes(@"
+ D9313225 F88406E5 A55909C5 AFF5269A
+ 86A7A953 1534F7DA 2E4C303D 8A318A72
+ 1C3C0C95 95680953 2FCF0E24 49A6B525
+ B16AEDF5 AA0DE657 BA637B39 1AAFD255
+ ");
+ byte[] ciphertextBytes = new byte[plaintext.Length + Aes128Gcm.CiphertextOverhead];
+ aes.Seal(ciphertextBytes, nonce, plaintext, associatedData);
+
+ CollectionAssert.AreEqual(Utils.HexToBytes(@"
+ 42831EC2 21777424 4B7221B7 84D0D49C
+ E3AA212F 2C02A4E0 35C17E23 29ACA12E
+ 21D514B2 5466931C 7D8F6A5A AC84AA05
+ 1BA30B39 6A0AAC97 3D58E091 473F5985
+
+ 64C02329 04AF398A 5B67C10B 53A5024D
+ "), ciphertextBytes);
+ }
+
+ using (Aes128Gcm aes = new Aes128Gcm(key))
+ {
+ byte[] ciphertext = Utils.HexToBytes(@"
+ 42831EC2 21777424 4B7221B7 84D0D49C
+ E3AA212F 2C02A4E0 35C17E23 29ACA12E
+ 21D514B2 5466931C 7D8F6A5A AC84AA05
+ 1BA30B39 6A0AAC97 3D58E091 473F5985
+
+ 64C02329 04AF398A 5B67C10B 53A5024D
+ ");
+ byte[] plaintext = new byte[ciphertext.Length - Aes128Gcm.CiphertextOverhead];
+ bool result = aes.Open(plaintext, nonce, ciphertext, associatedData);
+ Assert.IsTrue(result);
+
+ CollectionAssert.AreEqual(Utils.HexToBytes(@"
+ D9313225 F88406E5 A55909C5 AFF5269A
+ 86A7A953 1534F7DA 2E4C303D 8A318A72
+ 1C3C0C95 95680953 2FCF0E24 49A6B525
+ B16AEDF5 AA0DE657 BA637B39 1AAFD255
+ "), plaintext);
+ }
+ }
+
+ [TestMethod]
+ public void TestReuseToDecrypt()
+ {
+ byte[] key = Utils.HexToBytes("FEFFE992 8665731C 6D6A8F94 67308308");
+ byte[] nonce = Utils.HexToBytes("CAFEBABE FACEDBAD DECAF888");
+ byte[] associatedData = Utils.HexToBytes(@"
+ 3AD77BB4 0D7A3660 A89ECAF3 2466EF97
+ F5D3D585 03B9699D E785895A 96FDBAAF
+ 43B1CD7F 598ECE23 881B00E3 ED030688
+ 7B0C785E 27E8AD3F 82232071 04725DD4
+ ");
+
+ using (Aes128Gcm aes = new Aes128Gcm(key))
+ {
+ byte[] plaintext = Utils.HexToBytes("");
+ byte[] ciphertextBytes = new byte[plaintext.Length + Aes128Gcm.CiphertextOverhead];
+ aes.Seal(ciphertextBytes, nonce, plaintext, associatedData);
+
+ CollectionAssert.AreEqual(Utils.HexToBytes(@"
+ 5F91D771 23EF5EB9 99791384 9B8DC1E9
+ "), ciphertextBytes);
+
+ byte[] ciphertext = Utils.HexToBytes(@"
+ 5F91D771 23EF5EB9 99791384 9B8DC1E9
+ ");
+ plaintext = new byte[ciphertext.Length - Aes128Gcm.CiphertextOverhead];
+ bool result = aes.Open(plaintext, nonce, ciphertext, associatedData);
+ Assert.IsTrue(result);
+
+ CollectionAssert.AreEqual(Utils.HexToBytes(""), plaintext);
+ }
+ }
+
+ [TestMethod]
+ public void TestPlaintextSmallerThanBlock()
+ {
+ byte[] key = Utils.HexToBytes("FEFFE992 8665731C 6D6A8F94 67308308");
+ byte[] nonce = Utils.HexToBytes("CAFEBABE FACEDBAD DECAF888");
+ byte[] originalPlaintext = Encoding.UTF8.GetBytes("Lorem ipsum");
+ Assert.IsTrue(originalPlaintext.Length < 16);
+
+ using (Aes128Gcm aes = new Aes128Gcm(key))
+ {
+ byte[] ciphertext = new byte[originalPlaintext.Length + Aes128Gcm.CiphertextOverhead];
+ aes.Seal(ciphertext, nonce, originalPlaintext, ByteSpan.Empty);
+
+ byte[] plaintext = new byte[originalPlaintext.Length];
+ bool result = aes.Open(plaintext, nonce, ciphertext, ByteSpan.Empty);
+ Assert.IsTrue(result);
+
+ CollectionAssert.AreEqual(originalPlaintext, plaintext);
+ }
+ }
+
+ [TestMethod]
+ public void TestPlaintextLargerThanBlockMultiple()
+ {
+ byte[] key = Utils.HexToBytes("FEFFE992 8665731C 6D6A8F94 67308308");
+ byte[] nonce = Utils.HexToBytes("CAFEBABE FACEDBAD DECAF888");
+ byte[] originalPlaintext = Encoding.UTF8.GetBytes("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
+ Assert.IsTrue(originalPlaintext.Length > 16);
+ Assert.IsTrue((originalPlaintext.Length % 16) != 0);
+
+ using (Aes128Gcm aes = new Aes128Gcm(key))
+ {
+ byte[] ciphertext = new byte[originalPlaintext.Length + Aes128Gcm.CiphertextOverhead];
+ aes.Seal(ciphertext, nonce, originalPlaintext, ByteSpan.Empty);
+
+ byte[] plaintext = new byte[originalPlaintext.Length];
+ bool result = aes.Open(plaintext, nonce, ciphertext, ByteSpan.Empty);
+ Assert.IsTrue(result);
+
+ CollectionAssert.AreEqual(originalPlaintext, plaintext);
+ }
+ }
+ }
+}
diff --git a/Tools/Hazel-Networking/Hazel.UnitTests/Crypto/Sha256Tests.cs b/Tools/Hazel-Networking/Hazel.UnitTests/Crypto/Sha256Tests.cs
new file mode 100644
index 0000000..5309988
--- /dev/null
+++ b/Tools/Hazel-Networking/Hazel.UnitTests/Crypto/Sha256Tests.cs
@@ -0,0 +1,70 @@
+using Hazel.Crypto;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Text;
+
+namespace Hazel.UnitTests.Crypto
+{
+ [TestClass]
+ public class Sha256Tests
+ {
+ [TestMethod]
+ public void TestOneBlockMessage()
+ {
+ ByteSpan message = Encoding.ASCII.GetBytes(
+ "abc"
+ );
+ byte[] expectedDigest = Utils.HexToBytes(
+ "ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad"
+ );
+ byte[] actualDigest = new byte[Sha256Stream.DigestSize];
+
+ using (Sha256Stream sha256 = new Sha256Stream())
+ {
+ sha256.AddData(message);
+ sha256.CopyOrCalculateFinalHash(actualDigest);
+ }
+
+ CollectionAssert.AreEqual(expectedDigest, actualDigest);
+ }
+
+ [TestMethod]
+ public void TestMultiBlockMessage()
+ {
+ ByteSpan message = Encoding.ASCII.GetBytes(
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ );
+ byte[] expectedDigest = Utils.HexToBytes(
+ "248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1"
+ );
+ byte[] actualDigest = new byte[Sha256Stream.DigestSize];
+
+ using (Sha256Stream sha256 = new Sha256Stream())
+ {
+ sha256.AddData(message);
+ sha256.CopyOrCalculateFinalHash(actualDigest);
+ }
+
+ CollectionAssert.AreEqual(expectedDigest, actualDigest);
+ }
+
+ [TestMethod]
+ public void TestLongMessage()
+ {
+ ByteSpan message = Encoding.ASCII.GetBytes(
+ new string('a', 1000000)
+ );
+ byte[] expectedDigest = Utils.HexToBytes(
+ "cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0"
+ );
+ byte[] actualDigest = new byte[Sha256Stream.DigestSize];
+
+ using (Sha256Stream sha256 = new Sha256Stream())
+ {
+ sha256.AddData(message);
+ sha256.CopyOrCalculateFinalHash(actualDigest);
+ }
+
+ CollectionAssert.AreEqual(expectedDigest, actualDigest);
+ }
+ }
+}
diff --git a/Tools/Hazel-Networking/Hazel.UnitTests/Crypto/X25519Tests.cs b/Tools/Hazel-Networking/Hazel.UnitTests/Crypto/X25519Tests.cs
new file mode 100644
index 0000000..8d9a583
--- /dev/null
+++ b/Tools/Hazel-Networking/Hazel.UnitTests/Crypto/X25519Tests.cs
@@ -0,0 +1,297 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+using Hazel.Crypto;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Security.Cryptography;
+
+namespace Hazel.UnitTests.Crypto
+{
+ [TestClass]
+ public class X25519Tests
+ {
+ private static readonly byte[][] LowOrderPoints = new byte[][]
+ {
+ new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ new byte[]{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ new byte[]{0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00},
+ new byte[]{0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57},
+ new byte[]{0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f},
+ new byte[]{0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f},
+ new byte[]{0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f},
+ };
+
+ [TestMethod]
+ public void TestLowOrderPoints()
+ {
+ using (RandomNumberGenerator random = RandomNumberGenerator.Create())
+ {
+ byte[] scalar = new byte[X25519.KeySize];
+ random.GetBytes(scalar);
+
+ for (int ii = 0, nn = LowOrderPoints.Length; ii != nn; ++ii)
+ {
+ ByteSpan output = new byte[X25519.KeySize];
+ bool result = X25519.Func(output, scalar, LowOrderPoints[ii]);
+ Assert.IsFalse(result, $"Multiplication by low order point {ii} succeeded: should have failed");
+ }
+ }
+ }
+
+ [TestMethod]
+ public void TestVectors()
+ {
+ for (int ii = 0, nn = TestVectorData.Length; ii != nn; ++ii)
+ {
+ byte[] actual = new byte[32];
+ bool result = X25519.Func(actual, TestVectorData[ii].In, TestVectorData[ii].Base);
+ Assert.IsTrue(result);
+ CollectionAssert.AreEqual(TestVectorData[ii].Expect, actual, $"Test vector {ii} mismatch");
+ }
+ }
+
+ [TestMethod]
+ public void TestAgreement()
+ {
+ using (RandomNumberGenerator random = RandomNumberGenerator.Create())
+ {
+ byte[] clientPrivateKey = new byte[X25519.KeySize];
+ random.GetBytes(clientPrivateKey);
+
+ byte[] clientPublicKey = new byte[X25519.KeySize];
+ X25519.Func(clientPublicKey, clientPrivateKey);
+
+ byte[] serverPrivateKey = new byte[X25519.KeySize];
+ random.GetBytes(serverPrivateKey);
+
+ byte[] serverPublickey = new byte[X25519.KeySize];
+ X25519.Func(serverPublickey, serverPrivateKey);
+
+ // client key aggreement
+ byte[] clientSharedSecret = new byte[X25519.KeySize];
+ Assert.IsTrue(X25519.Func(clientSharedSecret, clientPrivateKey, serverPublickey));
+
+ // server key agreement
+ byte[] serverSharedSecret = new byte[X25519.KeySize];
+ Assert.IsTrue(X25519.Func(serverSharedSecret, serverPrivateKey, clientPublicKey));
+
+ CollectionAssert.AreEqual(clientSharedSecret, serverSharedSecret);
+ }
+ }
+
+ private struct TestVector
+ {
+ public byte[] In;
+ public byte[] Base;
+ public byte[] Expect;
+ }
+
+ private static readonly TestVector[] TestVectorData =
+ {
+ new TestVector {
+ In = new byte[]{0x66, 0x8f, 0xb9, 0xf7, 0x6a, 0xd9, 0x71, 0xc8, 0x1a, 0xc9, 0x0, 0x7, 0x1a, 0x15, 0x60, 0xbc, 0xe2, 0xca, 0x0, 0xca, 0xc7, 0xe6, 0x7a, 0xf9, 0x93, 0x48, 0x91, 0x37, 0x61, 0x43, 0x40, 0x14},
+ Base = new byte[]{0xdb, 0x5f, 0x32, 0xb7, 0xf8, 0x41, 0xe7, 0xa1, 0xa0, 0x9, 0x68, 0xef, 0xfd, 0xed, 0x12, 0x73, 0x5f, 0xc4, 0x7a, 0x3e, 0xb1, 0x3b, 0x57, 0x9a, 0xac, 0xad, 0xea, 0xe8, 0x9, 0x39, 0xa7, 0xdd},
+ Expect = new byte[]{0x9, 0xd, 0x85, 0xe5, 0x99, 0xea, 0x8e, 0x2b, 0xee, 0xb6, 0x13, 0x4, 0xd3, 0x7b, 0xe1, 0xe, 0xc5, 0xc9, 0x5, 0xf9, 0x92, 0x7d, 0x32, 0xf4, 0x2a, 0x9a, 0xa, 0xfb, 0x3e, 0xb, 0x40, 0x74},
+ },
+ new TestVector {
+ In = new byte[]{ 0x63, 0x66, 0x95, 0xe3, 0x4f, 0x75, 0xb9, 0xa2, 0x79, 0xc8, 0x70, 0x6f, 0xad, 0x12, 0x89, 0xf2, 0xc0, 0xb1, 0xe2, 0x2e, 0x16, 0xf8, 0xb8, 0x86, 0x17, 0x29, 0xc1, 0xa, 0x58, 0x29, 0x58, 0xaf},
+ Base = new byte[]{ 0x9, 0xd, 0x7, 0x1, 0xf8, 0xfd, 0xe2, 0x8f, 0x70, 0x4, 0x3b, 0x83, 0xf2, 0x34, 0x62, 0x25, 0x41, 0x9b, 0x18, 0xa7, 0xf2, 0x7e, 0x9e, 0x3d, 0x2b, 0xfd, 0x4, 0xe1, 0xf, 0x3d, 0x21, 0x3e},
+ Expect = new byte[]{ 0xbf, 0x26, 0xec, 0x7e, 0xc4, 0x13, 0x6, 0x17, 0x33, 0xd4, 0x40, 0x70, 0xea, 0x67, 0xca, 0xb0, 0x2a, 0x85, 0xdc, 0x1b, 0xe8, 0xcf, 0xe1, 0xff, 0x73, 0xd5, 0x41, 0xcc, 0x8, 0x32, 0x55, 0x6},
+ },
+ new TestVector {
+ In = new byte[]{ 0x73, 0x41, 0x81, 0xcd, 0x1a, 0x94, 0x6, 0x52, 0x2a, 0x56, 0xfe, 0x25, 0xe4, 0x3e, 0xcb, 0xf0, 0x29, 0x5d, 0xb5, 0xdd, 0xd0, 0x60, 0x9b, 0x3c, 0x2b, 0x4e, 0x79, 0xc0, 0x6f, 0x8b, 0xd4, 0x6d},
+ Base = new byte[]{ 0xf8, 0xa8, 0x42, 0x1c, 0x7d, 0x21, 0xa9, 0x2d, 0xb3, 0xed, 0xe9, 0x79, 0xe1, 0xfa, 0x6a, 0xcb, 0x6, 0x2b, 0x56, 0xb1, 0x88, 0x5c, 0x71, 0xc5, 0x11, 0x53, 0xcc, 0xb8, 0x80, 0xac, 0x73, 0x15},
+ Expect = new byte[]{ 0x11, 0x76, 0xd0, 0x16, 0x81, 0xf2, 0xcf, 0x92, 0x9d, 0xa2, 0xc7, 0xa3, 0xdf, 0x66, 0xb5, 0xd7, 0x72, 0x9f, 0xd4, 0x22, 0x22, 0x6f, 0xd6, 0x37, 0x42, 0x16, 0xbf, 0x7e, 0x2, 0xfd, 0xf, 0x62},
+ },
+ new TestVector {
+ In = new byte[]{ 0x1f, 0x70, 0x39, 0x1f, 0x6b, 0xa8, 0x58, 0x12, 0x94, 0x13, 0xbd, 0x80, 0x1b, 0x12, 0xac, 0xbf, 0x66, 0x23, 0x62, 0x82, 0x5c, 0xa2, 0x50, 0x9c, 0x81, 0x87, 0x59, 0xa, 0x2b, 0xe, 0x61, 0x72},
+ Base = new byte[]{ 0xd3, 0xea, 0xd0, 0x7a, 0x0, 0x8, 0xf4, 0x45, 0x2, 0xd5, 0x80, 0x8b, 0xff, 0xc8, 0x97, 0x9f, 0x25, 0xa8, 0x59, 0xd5, 0xad, 0xf4, 0x31, 0x2e, 0xa4, 0x87, 0x48, 0x9c, 0x30, 0xe0, 0x1b, 0x3b},
+ Expect = new byte[]{ 0xf8, 0x48, 0x2f, 0x2e, 0x9e, 0x58, 0xbb, 0x6, 0x7e, 0x86, 0xb2, 0x87, 0x24, 0xb3, 0xc0, 0xa3, 0xbb, 0xb5, 0x7, 0x3e, 0x4c, 0x6a, 0xcd, 0x93, 0xdf, 0x54, 0x5e, 0xff, 0xdb, 0xba, 0x50, 0x5f},
+ },
+ new TestVector {
+ In = new byte[]{ 0x3a, 0x7a, 0xe6, 0xcf, 0x8b, 0x88, 0x9d, 0x2b, 0x7a, 0x60, 0xa4, 0x70, 0xad, 0x6a, 0xd9, 0x99, 0x20, 0x6b, 0xf5, 0x7d, 0x90, 0x30, 0xdd, 0xf7, 0xf8, 0x68, 0xc, 0x8b, 0x1a, 0x64, 0x5d, 0xaa},
+ Base = new byte[]{ 0x4d, 0x25, 0x4c, 0x80, 0x83, 0xd8, 0x7f, 0x1a, 0x9b, 0x3e, 0xa7, 0x31, 0xef, 0xcf, 0xf8, 0xa6, 0xf2, 0x31, 0x2d, 0x6f, 0xed, 0x68, 0xe, 0xf8, 0x29, 0x18, 0x51, 0x61, 0xc8, 0xfc, 0x50, 0x60},
+ Expect = new byte[]{ 0x47, 0xb3, 0x56, 0xd5, 0x81, 0x8d, 0xe8, 0xef, 0xac, 0x77, 0x4b, 0x71, 0x4c, 0x42, 0xc4, 0x4b, 0xe6, 0x85, 0x23, 0xdd, 0x57, 0xdb, 0xd7, 0x39, 0x62, 0xd5, 0xa5, 0x26, 0x31, 0x87, 0x62, 0x37},
+ },
+ new TestVector {
+ In = new byte[]{ 0x20, 0x31, 0x61, 0xc3, 0x15, 0x9a, 0x87, 0x6a, 0x2b, 0xea, 0xec, 0x29, 0xd2, 0x42, 0x7f, 0xb0, 0xc7, 0xc3, 0xd, 0x38, 0x2c, 0xd0, 0x13, 0xd2, 0x7c, 0xc3, 0xd3, 0x93, 0xdb, 0xd, 0xaf, 0x6f},
+ Base = new byte[]{ 0x6a, 0xb9, 0x5d, 0x1a, 0xbe, 0x68, 0xc0, 0x9b, 0x0, 0x5c, 0x3d, 0xb9, 0x4, 0x2c, 0xc9, 0x1a, 0xc8, 0x49, 0xf7, 0xe9, 0x4a, 0x2a, 0x4a, 0x9b, 0x89, 0x36, 0x78, 0x97, 0xb, 0x7b, 0x95, 0xbf},
+ Expect = new byte[]{ 0x11, 0xed, 0xae, 0xdc, 0x95, 0xff, 0x78, 0xf5, 0x63, 0xa1, 0xc8, 0xf1, 0x55, 0x91, 0xc0, 0x71, 0xde, 0xa0, 0x92, 0xb4, 0xd7, 0xec, 0xaa, 0xc8, 0xe0, 0x38, 0x7b, 0x5a, 0x16, 0xc, 0x4e, 0x5d},
+ },
+ new TestVector {
+ In = new byte[]{ 0x13, 0xd6, 0x54, 0x91, 0xfe, 0x75, 0xf2, 0x3, 0xa0, 0x8, 0xb4, 0x41, 0x5a, 0xbc, 0x60, 0xd5, 0x32, 0xe6, 0x95, 0xdb, 0xd2, 0xf1, 0xe8, 0x3, 0xac, 0xcb, 0x34, 0xb2, 0xb7, 0x2c, 0x3d, 0x70},
+ Base = new byte[]{ 0x2e, 0x78, 0x4e, 0x4, 0xca, 0x0, 0x73, 0x33, 0x62, 0x56, 0xa8, 0x39, 0x25, 0x5e, 0xd2, 0xf7, 0xd4, 0x79, 0x6a, 0x64, 0xcd, 0xc3, 0x7f, 0x1e, 0xb0, 0xe5, 0xc4, 0xc8, 0xd1, 0xd1, 0xe0, 0xf5},
+ Expect = new byte[]{ 0x56, 0x3e, 0x8c, 0x9a, 0xda, 0xa7, 0xd7, 0x31, 0x1, 0xb0, 0xf2, 0xea, 0xd3, 0xca, 0xe1, 0xea, 0x5d, 0x8f, 0xcd, 0x5c, 0xd3, 0x60, 0x80, 0xbb, 0x8e, 0x6e, 0xc0, 0x3d, 0x61, 0x45, 0x9, 0x17},
+ },
+ new TestVector {
+ In = new byte[]{ 0x68, 0x6f, 0x7d, 0xa9, 0x3b, 0xf2, 0x68, 0xe5, 0x88, 0x6, 0x98, 0x31, 0xf0, 0x47, 0x16, 0x3f, 0x33, 0x58, 0x99, 0x89, 0xd0, 0x82, 0x6e, 0x98, 0x8, 0xfb, 0x67, 0x8e, 0xd5, 0x7e, 0x67, 0x49},
+ Base = new byte[]{ 0x8b, 0x54, 0x9b, 0x2d, 0xf6, 0x42, 0xd3, 0xb2, 0x5f, 0xe8, 0x38, 0xf, 0x8c, 0xc4, 0x37, 0x5f, 0x99, 0xb7, 0xbb, 0x4d, 0x27, 0x5f, 0x77, 0x9f, 0x3b, 0x7c, 0x81, 0xb8, 0xa2, 0xbb, 0xc1, 0x29},
+ Expect = new byte[]{ 0x1, 0x47, 0x69, 0x65, 0x42, 0x6b, 0x61, 0x71, 0x74, 0x9a, 0x8a, 0xdd, 0x92, 0x35, 0x2, 0x5c, 0xe5, 0xf5, 0x57, 0xfe, 0x40, 0x9, 0xf7, 0x39, 0x30, 0x44, 0xeb, 0xbb, 0x8a, 0xe9, 0x52, 0x79},
+ },
+ new TestVector {
+ In = new byte[]{ 0x82, 0xd6, 0x1c, 0xce, 0xdc, 0x80, 0x6a, 0x60, 0x60, 0xa3, 0x34, 0x9a, 0x5e, 0x87, 0xcb, 0xc7, 0xac, 0x11, 0x5e, 0x4f, 0x87, 0x77, 0x62, 0x50, 0xae, 0x25, 0x60, 0x98, 0xa7, 0xc4, 0x49, 0x59},
+ Base = new byte[]{ 0x8b, 0x6b, 0x9d, 0x8, 0xf6, 0x1f, 0xc9, 0x1f, 0xe8, 0xb3, 0x29, 0x53, 0xc4, 0x23, 0x40, 0xf0, 0x7, 0xb5, 0x71, 0xdc, 0xb0, 0xa5, 0x6d, 0x10, 0x72, 0x4e, 0xce, 0xf9, 0x95, 0xc, 0xfb, 0x25},
+ Expect = new byte[]{ 0x9c, 0x49, 0x94, 0x1f, 0x9c, 0x4f, 0x18, 0x71, 0xfa, 0x40, 0x91, 0xfe, 0xd7, 0x16, 0xd3, 0x49, 0x99, 0xc9, 0x52, 0x34, 0xed, 0xf2, 0xfd, 0xfb, 0xa6, 0xd1, 0x4a, 0x5a, 0xfe, 0x9e, 0x5, 0x58},
+ },
+ new TestVector {
+ In = new byte[]{ 0x7d, 0xc7, 0x64, 0x4, 0x83, 0x13, 0x97, 0xd5, 0x88, 0x4f, 0xdf, 0x6f, 0x97, 0xe1, 0x74, 0x4c, 0x9e, 0xb1, 0x18, 0xa3, 0x1a, 0x7b, 0x23, 0xf8, 0xd7, 0x9f, 0x48, 0xce, 0x9c, 0xad, 0x15, 0x4b},
+ Base = new byte[]{ 0x1a, 0xcd, 0x29, 0x27, 0x84, 0xf4, 0x79, 0x19, 0xd4, 0x55, 0xf8, 0x87, 0x44, 0x83, 0x58, 0x61, 0xb, 0xb9, 0x45, 0x96, 0x70, 0xeb, 0x99, 0xde, 0xe4, 0x60, 0x5, 0xf6, 0x89, 0xca, 0x5f, 0xb6},
+ Expect = new byte[]{ 0x0, 0xf4, 0x3c, 0x2, 0x2e, 0x94, 0xea, 0x38, 0x19, 0xb0, 0x36, 0xae, 0x2b, 0x36, 0xb2, 0xa7, 0x61, 0x36, 0xaf, 0x62, 0x8a, 0x75, 0x1f, 0xe5, 0xd0, 0x1e, 0x3, 0xd, 0x44, 0x25, 0x88, 0x59},
+ },
+ new TestVector {
+ In = new byte[]{ 0xfb, 0xc4, 0x51, 0x1d, 0x23, 0xa6, 0x82, 0xae, 0x4e, 0xfd, 0x8, 0xc8, 0x17, 0x9c, 0x1c, 0x6, 0x7f, 0x9c, 0x8b, 0xe7, 0x9b, 0xbc, 0x4e, 0xff, 0x5c, 0xe2, 0x96, 0xc6, 0xbc, 0x1f, 0xf4, 0x45},
+ Base = new byte[]{ 0x55, 0xca, 0xff, 0x21, 0x81, 0xf2, 0x13, 0x6b, 0xe, 0xd0, 0xe1, 0xe2, 0x99, 0x44, 0x48, 0xe1, 0x6c, 0xc9, 0x70, 0x64, 0x6a, 0x98, 0x3d, 0x14, 0xd, 0xc4, 0xea, 0xb3, 0xd9, 0x4c, 0x28, 0x4e},
+ Expect = new byte[]{ 0xae, 0x39, 0xd8, 0x16, 0x53, 0x23, 0x45, 0x79, 0x4d, 0x26, 0x91, 0xe0, 0x80, 0x1c, 0xaa, 0x52, 0x5f, 0xc3, 0x63, 0x4d, 0x40, 0x2c, 0xe9, 0x58, 0xb, 0x33, 0x38, 0xb4, 0x6f, 0x8b, 0xb9, 0x72},
+ },
+ new TestVector {
+ In = new byte[]{ 0x4e, 0x6, 0xc, 0xe1, 0xc, 0xeb, 0xf0, 0x95, 0x9, 0x87, 0x16, 0xc8, 0x66, 0x19, 0xeb, 0x9f, 0x7d, 0xf6, 0x65, 0x24, 0x69, 0x8b, 0xa7, 0x98, 0x8c, 0x3b, 0x90, 0x95, 0xd9, 0xf5, 0x1, 0x34},
+ Base = new byte[]{ 0x57, 0x73, 0x3f, 0x2d, 0x86, 0x96, 0x90, 0xd0, 0xd2, 0xed, 0xae, 0xc9, 0x52, 0x3d, 0xaa, 0x2d, 0xa9, 0x54, 0x45, 0xf4, 0x4f, 0x57, 0x83, 0xc1, 0xfa, 0xec, 0x6c, 0x3a, 0x98, 0x28, 0x18, 0xf3},
+ Expect = new byte[]{ 0xa6, 0x1e, 0x74, 0x55, 0x2c, 0xce, 0x75, 0xf5, 0xe9, 0x72, 0xe4, 0x24, 0xf2, 0xcc, 0xb0, 0x9c, 0x83, 0xbc, 0x1b, 0x67, 0x1, 0x47, 0x48, 0xf0, 0x2c, 0x37, 0x1a, 0x20, 0x9e, 0xf2, 0xfb, 0x2c},
+ },
+ new TestVector {
+ In = new byte[]{ 0x5c, 0x49, 0x2c, 0xba, 0x2c, 0xc8, 0x92, 0x48, 0x8a, 0x9c, 0xeb, 0x91, 0x86, 0xc2, 0xaa, 0xc2, 0x2f, 0x1, 0x5b, 0xf3, 0xef, 0x8d, 0x3e, 0xcc, 0x9c, 0x41, 0x76, 0x97, 0x62, 0x61, 0xaa, 0xb1},
+ Base = new byte[]{ 0x67, 0x97, 0xc2, 0xe7, 0xdc, 0x92, 0xcc, 0xbe, 0x7c, 0x5, 0x6b, 0xec, 0x35, 0xa, 0xb6, 0xd3, 0xbd, 0x2a, 0x2c, 0x6b, 0xc5, 0xa8, 0x7, 0xbb, 0xca, 0xe1, 0xf6, 0xc2, 0xaf, 0x80, 0x36, 0x44},
+ Expect = new byte[]{ 0xfc, 0xf3, 0x7, 0xdf, 0xbc, 0x19, 0x2, 0xb, 0x28, 0xa6, 0x61, 0x8c, 0x6c, 0x62, 0x2f, 0x31, 0x7e, 0x45, 0x96, 0x7d, 0xac, 0xf4, 0xae, 0x4a, 0xa, 0x69, 0x9a, 0x10, 0x76, 0x9f, 0xde, 0x14},
+ },
+ new TestVector {
+ In = new byte[]{ 0xea, 0x33, 0x34, 0x92, 0x96, 0x5, 0x5a, 0x4e, 0x8b, 0x19, 0x2e, 0x3c, 0x23, 0xc5, 0xf4, 0xc8, 0x44, 0x28, 0x2a, 0x3b, 0xfc, 0x19, 0xec, 0xc9, 0xdc, 0x64, 0x6a, 0x42, 0xc3, 0x8d, 0xc2, 0x48},
+ Base = new byte[]{ 0x2c, 0x75, 0xd8, 0x51, 0x42, 0xec, 0xad, 0x3e, 0x69, 0x44, 0x70, 0x4, 0x54, 0xc, 0x1c, 0x23, 0x54, 0x8f, 0xc8, 0xf4, 0x86, 0x25, 0x1b, 0x8a, 0x19, 0x46, 0x3f, 0x3d, 0xf6, 0xf8, 0xac, 0x61},
+ Expect = new byte[]{ 0x5d, 0xca, 0xb6, 0x89, 0x73, 0xf9, 0x5b, 0xd3, 0xae, 0x4b, 0x34, 0xfa, 0xb9, 0x49, 0xfb, 0x7f, 0xb1, 0x5a, 0xf1, 0xd8, 0xca, 0xe2, 0x8c, 0xd6, 0x99, 0xf9, 0xc1, 0xaa, 0x33, 0x37, 0x34, 0x2f},
+ },
+ new TestVector {
+ In = new byte[]{ 0x4f, 0x29, 0x79, 0xb1, 0xec, 0x86, 0x19, 0xe4, 0x5c, 0xa, 0xb, 0x2b, 0x52, 0x9, 0x34, 0x54, 0x1a, 0xb9, 0x44, 0x7, 0xb6, 0x4d, 0x19, 0xa, 0x76, 0xf3, 0x23, 0x14, 0xef, 0xe1, 0x84, 0xe7},
+ Base = new byte[]{ 0xf7, 0xca, 0xe1, 0x8d, 0x8d, 0x36, 0xa7, 0xf5, 0x61, 0x17, 0xb8, 0xb7, 0xe, 0x25, 0x52, 0x27, 0x7f, 0xfc, 0x99, 0xdf, 0x87, 0x56, 0xb5, 0xe1, 0x38, 0xbf, 0x63, 0x68, 0xbc, 0x87, 0xf7, 0x4c},
+ Expect = new byte[]{ 0xe4, 0xe6, 0x34, 0xeb, 0xb4, 0xfb, 0x66, 0x4f, 0xe8, 0xb2, 0xcf, 0xa1, 0x61, 0x5f, 0x0, 0xe6, 0x46, 0x6f, 0xff, 0x73, 0x2c, 0xe1, 0xf8, 0xa0, 0xc8, 0xd2, 0x72, 0x74, 0x31, 0xd1, 0x6f, 0x14},
+ },
+ new TestVector {
+ In = new byte[]{ 0xf5, 0xd8, 0xa9, 0x27, 0x90, 0x1d, 0x4f, 0xa4, 0x24, 0x90, 0x86, 0xb7, 0xff, 0xec, 0x24, 0xf5, 0x29, 0x7d, 0x80, 0x11, 0x8e, 0x4a, 0xc9, 0xd3, 0xfc, 0x9a, 0x82, 0x37, 0x95, 0x1e, 0x3b, 0x7f},
+ Base = new byte[]{ 0x3c, 0x23, 0x5e, 0xdc, 0x2, 0xf9, 0x11, 0x56, 0x41, 0xdb, 0xf5, 0x16, 0xd5, 0xde, 0x8a, 0x73, 0x5d, 0x6e, 0x53, 0xe2, 0x2a, 0xa2, 0xac, 0x14, 0x36, 0x56, 0x4, 0x5f, 0xf2, 0xe9, 0x52, 0x49},
+ Expect = new byte[]{ 0xab, 0x95, 0x15, 0xab, 0x14, 0xaf, 0x9d, 0x27, 0xe, 0x1d, 0xae, 0xc, 0x56, 0x80, 0xcb, 0xc8, 0x88, 0xb, 0xd8, 0xa8, 0xe7, 0xeb, 0x67, 0xb4, 0xda, 0x42, 0xa6, 0x61, 0x96, 0x1e, 0xfc, 0xb},
+ },
+ };
+ }
+
+ [TestClass]
+ public class X25519FieldTests
+ {
+ private readonly byte[] A = {0x21, 0xDD, 0xB0, 0x43, 0xCF, 0xB2, 0xB3, 0xFE, 0xC4, 0xCC, 0xA3, 0x8B, 0xBA, 0x3D, 0xE1, 0x92, 0xDF, 0xEA, 0x85, 0xCE, 0x2B, 0x4A, 0xD8, 0x44, 0x95, 0xAA, 0xB1, 0x3A, 0x5B, 0x62, 0x87, 0x8E};
+ private readonly byte[] B = {0x22, 0x8B, 0x2F, 0x48, 0x4B, 0x86, 0xAC, 0x9C, 0xA4, 0x7B, 0x64, 0xC4, 0x62, 0x76, 0x34, 0x7C, 0x67, 0xBD, 0x59, 0x6F, 0x8D, 0x18, 0x41, 0x4D, 0x96, 0x31, 0xA5, 0x5B, 0x3B, 0xA5, 0x7E, 0xC7};
+
+ [TestMethod]
+ public void Zero()
+ {
+ byte[] actual = new byte[X25519.KeySize];
+ X25519.FieldElement fe = X25519.FieldElement.Zero();
+ fe.CopyTo(actual);
+
+ byte[] expected = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ CollectionAssert.AreEqual(expected, actual);
+ }
+
+ [TestMethod]
+ public void One()
+ {
+ byte[] actual = new byte[X25519.KeySize];
+ X25519.FieldElement fe = X25519.FieldElement.One();
+ fe.CopyTo(actual);
+
+ byte[] expected = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ CollectionAssert.AreEqual(expected, actual);
+ }
+
+ [TestMethod]
+ public void Add()
+ {
+ X25519.FieldElement a = X25519.FieldElement.FromBytes(A);
+ X25519.FieldElement b = X25519.FieldElement.FromBytes(B);
+
+ byte[] actual = new byte[X25519.KeySize];
+ X25519.FieldElement c = new X25519.FieldElement();
+ X25519.FieldElement.Add(ref c, ref a, ref b);
+ c.CopyTo(actual);
+
+ byte[] expected = {0x43, 0x68, 0xE0, 0x8B, 0x1A, 0x39, 0x60, 0x9B, 0x69, 0x48, 0x08, 0x50, 0x1D, 0xB4, 0x15, 0x0F, 0x47, 0xA8, 0xDF, 0x3D, 0xB9, 0x62, 0x19, 0x92, 0x2B, 0xDC, 0x56, 0x96, 0x96, 0x07, 0x06, 0x56};
+ CollectionAssert.AreEqual(expected, actual);
+ }
+
+ [TestMethod]
+ public void Sub()
+ {
+ X25519.FieldElement a = X25519.FieldElement.FromBytes(A);
+ X25519.FieldElement b = X25519.FieldElement.FromBytes(B);
+
+ byte[] actual = new byte[X25519.KeySize];
+ X25519.FieldElement c = new X25519.FieldElement();
+ X25519.FieldElement.Sub(ref c, ref a, ref b);
+ c.CopyTo(actual);
+
+ byte[] expected = {0xEC, 0x51, 0x81, 0xFB, 0x83, 0x2C, 0x07, 0x62, 0x20, 0x51, 0x3F, 0xC7, 0x57, 0xC7, 0xAC, 0x16, 0x78, 0x2D, 0x2C, 0x5F, 0x9E, 0x31, 0x97, 0xF7, 0xFE, 0x78, 0x0C, 0xDF, 0x1F, 0xBD, 0x08, 0x47};
+ CollectionAssert.AreEqual(expected, actual);
+ }
+
+ [TestMethod]
+ public void Multiply()
+ {
+ X25519.FieldElement a = X25519.FieldElement.FromBytes(A);
+ X25519.FieldElement b = X25519.FieldElement.FromBytes(B);
+
+ byte[] actual = new byte[X25519.KeySize];
+ X25519.FieldElement c = new X25519.FieldElement();
+ X25519.FieldElement.Multiply(ref c, ref a, ref b);
+ c.CopyTo(actual);
+
+ byte[] expected = {0x1E, 0xBE, 0xBD, 0xE0, 0xEC, 0xB1, 0x3C, 0xDB, 0x50, 0x6E, 0xD6, 0x50, 0x02, 0x1A, 0x59, 0x99, 0xC1, 0xC0, 0xFC, 0xE0, 0xBF, 0xDB, 0x64, 0xB0, 0x3E, 0xB3, 0x2D, 0x43, 0x8B, 0x66, 0x43, 0x3C};
+ CollectionAssert.AreEqual(expected, actual);
+ }
+
+ [TestMethod]
+ public void Square()
+ {
+ X25519.FieldElement a = X25519.FieldElement.FromBytes(A);
+
+ byte[] actual = new byte[X25519.KeySize];
+ X25519.FieldElement c = new X25519.FieldElement();
+ X25519.FieldElement.Square(ref c, ref a);
+ c.CopyTo(actual);
+
+ byte[] expected = {0xAE, 0xB2, 0x22, 0xD4, 0x72, 0xF7, 0xF4, 0x09, 0xBB, 0x9A, 0xA9, 0x99, 0xEB, 0x7F, 0xC4, 0xE1, 0x4C, 0x0A, 0x53, 0xEB, 0x3C, 0xFF, 0x5C, 0xE2, 0xF6, 0x92, 0x46, 0x53, 0x29, 0xE1, 0x5D, 0x7A};
+ CollectionAssert.AreEqual(expected, actual);
+
+
+ a = X25519.FieldElement.FromBytes(A);
+ X25519.FieldElement.Square(ref a, ref a);
+ a.CopyTo(actual);
+
+ CollectionAssert.AreEqual(expected, actual);
+ }
+
+ [TestMethod]
+ public void Multiply121666()
+ {
+ X25519.FieldElement a = X25519.FieldElement.FromBytes(A);
+
+ byte[] actual = new byte[X25519.KeySize];
+ X25519.FieldElement c = new X25519.FieldElement();
+ X25519.FieldElement.Multiply121666(ref c, ref a);
+ c.CopyTo(actual);
+
+ byte[] expected = {0x65, 0x3E, 0xE9, 0x9D, 0x08, 0xAC, 0x1A, 0x17, 0x61, 0x4F, 0x2C, 0xED, 0x30, 0x0B, 0x9B, 0xCB, 0x2B, 0x63, 0x53, 0xB9, 0x7D, 0x67, 0x62, 0x11, 0x39, 0xF1, 0x50, 0xC9, 0x6C, 0xA1, 0x66, 0x72};
+ CollectionAssert.AreEqual(expected, actual);
+ }
+
+ [TestMethod]
+ public void Invert()
+ {
+ X25519.FieldElement a = X25519.FieldElement.FromBytes(A);
+
+ byte[] actual = new byte[X25519.KeySize];
+ X25519.FieldElement c = new X25519.FieldElement();
+ X25519.FieldElement.Invert(ref c, ref a);
+ c.CopyTo(actual);
+
+ byte[] expected = {0x8E, 0x66, 0x2F, 0x60, 0xFC, 0xCD, 0x3A, 0x11, 0x36, 0xF5, 0xD9, 0xE6, 0x94, 0x28, 0x04, 0x2A, 0x6B, 0x5D, 0xC4, 0x72, 0x82, 0x30, 0xF3, 0x09, 0xC0, 0x24, 0xDE, 0xCD, 0x60, 0x3F, 0x5D, 0x17};
+ CollectionAssert.AreEqual(expected, actual);
+ }
+ }
+}