summary refs log tree commit diff
path: root/crypto/test/src
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2016-02-03 23:14:10 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2016-02-03 23:14:10 +0700
commit26c0d3e4de498a9b7c8b6712bb765d693fb93de3 (patch)
treebfa0c30f149dc3e089eda4ab3ad35142394ded86 /crypto/test/src
parentImplement RFC 7685 in TLS (diff)
downloadBouncyCastle.NET-ed25519-26c0d3e4de498a9b7c8b6712bb765d693fb93de3.tar.xz
Port bcrypt from Java API
- Requested in BMA-143
Diffstat (limited to 'crypto/test/src')
-rw-r--r--crypto/test/src/crypto/test/BCryptTest.cs161
-rw-r--r--crypto/test/src/crypto/test/OpenBsdBCryptTest.cs147
-rw-r--r--crypto/test/src/crypto/test/RegressionTest.cs11
3 files changed, 313 insertions, 6 deletions
diff --git a/crypto/test/src/crypto/test/BCryptTest.cs b/crypto/test/src/crypto/test/BCryptTest.cs
new file mode 100644
index 000000000..2d9771d17
--- /dev/null
+++ b/crypto/test/src/crypto/test/BCryptTest.cs
@@ -0,0 +1,161 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /*
+     * bcrypt test vectors
+     */
+    [TestFixture]
+    public class BCryptTest
+        :   SimpleTest
+    {
+        // Raw test vectors based on crypt style test vectors
+        // Cross checked with JBCrypt
+        private static readonly object[][] TestVectorData = {
+            new object[]{"", "144b3d691a7b4ecf39cf735c7fa7a79c", 6, "557e94f34bf286e8719a26be94ac1e16d95ef9f819dee092"},
+            new object[]{"00", "144b3d691a7b4ecf39cf735c7fa7a79c", 6, "557e94f34bf286e8719a26be94ac1e16d95ef9f819dee092"},
+            new object[]{"00", "26c63033c04f8bcba2fe24b574db6274", 8, "56701b26164d8f1bc15225f46234ac8ac79bf5bc16bf48ba"},
+            new object[]{"00", "9b7c9d2ada0fd07091c915d1517701d6", 10, "7b2e03106a43c9753821db688b5cc7590b18fdf9ba544632"},
+            new object[]{"6100", "a3612d8c9a37dac2f99d94da03bd4521", 6, "e6d53831f82060dc08a2e8489ce850ce48fbf976978738f3"},
+            new object[]{"6100", "7a17b15dfe1c4be10ec6a3ab47818386", 8, "a9f3469a61cbff0a0f1a1445dfe023587f38b2c9c40570e1"},
+            new object[]{"6100", "9bef4d04e1f8f92f3de57323f8179190", 10, "5169fd39606d630524285147734b4c981def0ee512c3ace1"},
+            new object[]{"61626300", "2a1f1dc70a3d147956a46febe3016017", 6, "d9a275b493bcbe1024b0ff80d330253cfdca34687d8f69e5"},
+            new object[]{"61626300", "4ead845a142c9bc79918c8797f470ef5", 8, "8d4131a723bfbbac8a67f2e035cae08cc33b69f37331ea91"},
+            new object[]{"61626300", "631c554493327c32f9c26d9be7d18e4c", 10, "8cd0b863c3ff0860e31a2b42427974e0283b3af7142969a6"},
+            new object[]{"6162636465666768696a6b6c6d6e6f707172737475767778797a00", "02d1176d74158ee29cffdac6150cf123", 6, "4d38b523ce9dc6f2f6ff9fb3c2cd71dfe7f96eb4a3baf19f"},
+            new object[]{"6162636465666768696a6b6c6d6e6f707172737475767778797a00", "715b96caed2ac92c354ed16c1e19e38a", 8, "98bf9ffc1f5be485f959e8b1d526392fbd4ed2d5719f506b"},
+            new object[]{"6162636465666768696a6b6c6d6e6f707172737475767778797a00", "85727e838f9049397fbec90566ede0df", 10, "cebba53f67bd28af5a44c6707383c231ac4ef244a6f5fb2b"},
+            new object[]{"7e21402324255e262a28292020202020207e21402324255e262a2829504e4246524400", "8512ae0d0fac4ec9a5978f79b6171028", 6, "26f517fe5345ad575ba7dfb8144f01bfdb15f3d47c1e146a"},
+            new object[]{"7e21402324255e262a28292020202020207e21402324255e262a2829504e4246524400", "1ace2de8807df18c79fced54678f388f", 8, "d51d7cdf839b91a25758b80141e42c9f896ae80fd6cd561f"},
+            new object[]{"7e21402324255e262a28292020202020207e21402324255e262a2829504e4246524400", "36285a6267751b14ba2dc989f6d43126", 10, "db4fab24c1ff41c1e2c966f8b3d6381c76e86f52da9e15a9"},
+            new object[]{"c2a300", "144b3d691a7b4ecf39cf735c7fa7a79c", 6, "5a6c4fedb23980a7da9217e0442565ac6145b687c7313339"},
+        };
+
+        public override string Name
+        {
+            get { return "BCrypt"; }
+        }
+
+        public override void PerformTest()
+        {
+            DoTestParameters();
+            DoTestShortKeys();
+            DoTestVectors();
+        }
+
+        private void DoTestShortKeys()
+        {
+            byte[] salt = new byte[16];
+
+            // Check BCrypt with empty key pads to zero byte key
+            byte[] hashEmpty = BCrypt.Generate(new byte[0], salt, 4);
+            byte[] hashZero1 = BCrypt.Generate(new byte[1], salt, 4);
+
+            if (!Arrays.AreEqual(hashEmpty, hashZero1))
+            {
+                Fail("Hash for empty password should equal zeroed key", Hex.ToHexString(hashEmpty),
+                    Hex.ToHexString(hashZero1));
+            }
+
+            // Check zeroed byte key of min Blowfish length is equivalent
+            byte[] hashZero4 = BCrypt.Generate(new byte[4], salt, 4);
+            if (!Arrays.AreEqual(hashEmpty, hashZero4))
+            {
+                Fail("Hash for empty password should equal zeroed key[4]", Hex.ToHexString(hashEmpty),
+                    Hex.ToHexString(hashZero4));
+            }
+
+            // Check BCrypt isn't padding too small (32 bit) keys
+            byte[] hashA = BCrypt.Generate(new byte[]{(byte)'a'}, salt, 4);
+            byte[] hashA0 = BCrypt.Generate(new byte[]{(byte)'a', (byte)0}, salt, 4);
+            if (Arrays.AreEqual(hashA, hashA0))
+            {
+                Fail("Small keys should not be 0 padded.");
+            }
+        }
+
+        public void DoTestParameters()
+        {
+            CheckOK("Empty key", new byte[0], new byte[16], 4);
+            CheckOK("Minimal values", new byte[1], new byte[16], 4);
+            //CheckOK("Max cost", new byte[1], new byte[16], 31);
+            CheckOK("Max passcode", new byte[72], new byte[16], 4);
+            CheckIllegal("Null password", null, new byte[16], 4);
+            CheckIllegal("Null salt", new byte[1], null, 4);
+            CheckIllegal("Salt too small", new byte[1], new byte[15], 4);
+            CheckIllegal("Salt too big", new byte[1], new byte[17], 4);
+            CheckIllegal("Cost too low", new byte[16], new byte[16], 3);
+            CheckIllegal("Cost too high", new byte[16], new byte[16], 32);
+            CheckIllegal("Passcode too long", new byte[73], new byte[16], 32);
+        }
+
+        private void CheckOK(string msg, byte[] pass, byte[] salt, int cost)
+        {
+            try
+            {
+                BCrypt.Generate(pass, salt, cost);
+            }
+            catch (ArgumentException e)
+            {
+                Console.Error.WriteLine(e.StackTrace);
+                Fail(msg);
+            }
+        }
+
+        private void CheckIllegal(String msg, byte[] pass, byte[] salt, int cost)
+        {
+            try
+            {
+                BCrypt.Generate(pass, salt, cost);
+                Fail(msg);
+            }
+            catch (ArgumentException)
+            {
+                // Expected
+            }
+        }
+
+        public void DoTestVectors()
+        {
+            foreach (object[] v in TestVectorData)
+            {
+                byte[] password = Hex.Decode((string)v[0]);
+                byte[] salt = Hex.Decode((string)v[1]);
+                int cost = (int)v[2];
+                byte[] expected = Hex.Decode((string)v[3]);
+
+                DoTest(password, salt, cost, expected);
+            }
+
+        }
+
+        private void DoTest(byte[] password, byte[] salt, int cost, byte[] expected)
+        {
+            byte[] hash = BCrypt.Generate(password, salt, cost);
+            if (!Arrays.AreEqual(hash, expected))
+            {
+                Fail("Hash for " + Hex.ToHexString(password), Hex.ToHexString(expected), Hex.ToHexString(hash));
+            }
+        }
+
+        public static void Main(string[] args)
+		{
+            RunTest(new BCryptTest());
+		}
+
+        [Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+		}
+    }
+}
diff --git a/crypto/test/src/crypto/test/OpenBsdBCryptTest.cs b/crypto/test/src/crypto/test/OpenBsdBCryptTest.cs
new file mode 100644
index 000000000..8501588ee
--- /dev/null
+++ b/crypto/test/src/crypto/test/OpenBsdBCryptTest.cs
@@ -0,0 +1,147 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    [TestFixture]
+    public class OpenBsdBCryptTest
+        :   SimpleTest
+    {
+        private static readonly string[][] BCryptTest1 = // vectors from http://cvsweb.openwall.com/cgi/cvsweb.cgi/Owl/packages/glibc/crypt_blowfish/wrapper.c?rev=HEAD
+        {
+            new string[]{"$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW", "U*U"},
+            new string[]{"$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK", "U*U*"},
+            new string[]{"$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a", "U*U*U"},
+            new string[]{"$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy", ""},
+            new string[]{"$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui",
+                "0123456789abcdefghijklmnopqrstuvwxyz"
+                + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+                + "chars after 72 are ignored"},
+        };
+
+        private static readonly string[] BCryptTest2 = { // from: http://openwall.info/wiki/john/sample-hashes
+            "$2a$05$bvIG6Nmid91Mu9RcmmWZfO5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe", "password"
+        };
+
+        private static readonly string[] BCryptTest2b = { // from: http://stackoverflow.com/questions/11654684/verifying-a-bcrypt-hash
+            "$2a$10$.TtQJ4Jr6isd4Hp.mVfZeuh6Gws4rOQ/vdBczhDx.19NFK0Y84Dle", "ππππππππ"
+        };
+
+        private static readonly string[][] BCryptTest3 = // from: https://bitbucket.org/vadim/bcrypt.net/src/464c41416dc9/BCrypt.Net.Test/TestBCrypt.cs - plain - salt - expected
+        {
+            new string[]{"", "$2a$06$DCq7YPn5Rq63x1Lad4cll.", "$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s."},
+            new string[]{"", "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.", "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye"},
+            new string[]{"", "$2a$10$k1wbIrmNyFAPwPVPSVa/ze", "$2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW"},
+            new string[]{"", "$2a$12$k42ZFHFWqBp3vWli.nIn8u", "$2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO"},
+            new string[]{"a", "$2a$06$m0CrhHm10qJ3lXRY.5zDGO", "$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe"},
+            new string[]{"a", "$2a$08$cfcvVd2aQ8CMvoMpP2EBfe", "$2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V."},
+            new string[]{"a", "$2a$10$k87L/MF28Q673VKh8/cPi.", "$2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u"},
+            new string[]{"a", "$2a$12$8NJH3LsPrANStV6XtBakCe", "$2a$12$8NJH3LsPrANStV6XtBakCez0cKHXVxmvxIlcz785vxAIZrihHZpeS"},
+            new string[]{"abc", "$2a$06$If6bvum7DFjUnE9p2uDeDu", "$2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i"},
+            new string[]{"abc", "$2a$08$Ro0CUfOqk6cXEKf3dyaM7O", "$2a$08$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm"},
+            new string[]{"abc", "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.", "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi"},
+            new string[]{"abc", "$2a$12$EXRkfkdmXn2gzds2SSitu.", "$2a$12$EXRkfkdmXn2gzds2SSitu.MW9.gAVqa9eLS1//RYtYCmB1eLHg.9q"},
+            new string[]{"abcdefghijklmnopqrstuvwxyz", "$2a$06$.rCVZVOThsIa97pEDOxvGu", "$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC"},
+            new string[]{"abcdefghijklmnopqrstuvwxyz", "$2a$08$aTsUwsyowQuzRrDqFflhge", "$2a$08$aTsUwsyowQuzRrDqFflhgekJ8d9/7Z3GV3UcgvzQW3J5zMyrTvlz."},
+            new string[]{"abcdefghijklmnopqrstuvwxyz", "$2a$10$fVH8e28OQRj9tqiDXs1e1u", "$2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq"},
+            new string[]{"abcdefghijklmnopqrstuvwxyz", "$2a$12$D4G5f18o7aMMfwasBL7Gpu", "$2a$12$D4G5f18o7aMMfwasBL7GpuQWuP3pkrZrOAnqP.bmezbMng.QwJ/pG"},
+            new string[]{"~!@#$%^&*()      ~!@#$%^&*()PNBFRD", "$2a$06$fPIsBO8qRqkjj273rfaOI.", "$2a$06$fPIsBO8qRqkjj273rfaOI.HtSV9jLDpTbZn782DC6/t7qT67P6FfO"},
+            new string[]{"~!@#$%^&*()      ~!@#$%^&*()PNBFRD", "$2a$08$Eq2r4G/76Wv39MzSX262hu", "$2a$08$Eq2r4G/76Wv39MzSX262huzPz612MZiYHVUJe/OcOql2jo4.9UxTW"},
+            new string[]{"~!@#$%^&*()      ~!@#$%^&*()PNBFRD", "$2a$10$LgfYWkbzEvQ4JakH7rOvHe", "$2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS"},
+            new string[]{"~!@#$%^&*()      ~!@#$%^&*()PNBFRD", "$2a$12$WApznUOJfkEGSmYRfnkrPO", "$2a$12$WApznUOJfkEGSmYRfnkrPOr466oFDCaj4b6HY3EXGvfxm43seyhgC"},
+        };
+
+        private static readonly string[][] BCryptTest4 = { // from: https://github.com/ChrisMcKee/cryptsharp/blob/master/Tests/vectors/BCrypt.txt
+            new string[]{"n6HyjrYTo/r4lgjvM7L<`iM", "$2a$07$XPrYfnqc5ankSHnRfmPVu.A0trKq3VdczdbJjKaWIksKF.GfFCxv."},
+            new string[]{"~s0quB/K8zRtRT:QtZr`s|^O", "$2a$07$5zzz8omiaStXwOetWwlmuePPRwUt0jhNBPYGGgAMcUDvqsGVqv9Cy"},
+            new string[]{"r>8y3uE}6<7nI34?Q2rR0JEw", "$2a$07$k5AH9bO9aplPYdZMZ155qOcY1FewMXcupWewW6fViUtsVQ2Umg6LS"},
+            new string[]{">l_7}xxH3|Cr{dCR[HTUN@k~", "$2a$05$24xz81ZZsMUMm940bbWMCeHsO.s6A3MG0JZzm4y3.Ti6P96bz6RN6"},
+            new string[]{"D`lCFYTe9_8IW6nEB:oPjEk/S", "$2a$05$bA1xkp4NqFvDmtQJtDO9CugW0INxQLpMZha8AaHmBj9Zg9HlfQtBa"},
+            new string[]{"UBGYU6|a|RpA:bp[;}p.ZY4f1", "$2a$08$gu4KBnkla.bEqHiwaJ8.z.0ixfzE1Q0/iPfmpfRmUA.NUhUdZboxa"},
+            new string[]{"O9X[kP6{63F3rXKtN>n?zh2_", "$2a$04$yRZW9xEsqN9DL19jveqFyO1bljZ0r5KNCYqQzMqYpDB7XHWqDWNGC"},
+            new string[]{":Sa:BknepsG}\\5dOj>kh0KAk", "$2a$04$KhDTFUlakUsPNuLQSgyr7.xQZxkTSIvo0nFw0XyjvrH6n5kZkYDLG"},// extra escape sequence added
+            new string[]{"2_9J6k:{z?SSjCzL/GT/5CMgc", "$2a$05$eN1jCXDxN9HmuIARJlwH4ewsEyYbAmq7Cw99gEHqGRXtWyrRNLScy"},
+
+            new string[]{"2KNy`Kodau14?s8XVru<IIw0eDw|.64MM^Wtv;3sfZt~3`2QN6/U]0^1HtETqWHt<lMfD-LX::zo7AcNLQ.Q.@.g5kX`j7hRi", "$2a$04$xUNE1aUuNlpNwSOuz1VpjuBgW95ImLccIquQxyGLeinucvokg2Ale"},
+            new string[]{"0yWE>E;h/kdCRd@T]fQiv`Vz]KC0zaIAIeyY4zcooQ0^DfP{hHsw9?atO}CxbkbnK-LxUe;|FiBEluVqO@ysHhXQDdXPt0p", "$2a$07$pNHi/IxrSUohtsD5/eIv4O324ZPGfJE7mUAaNpIPkpyxjW9kqIk76"},
+            new string[]{"ilWj~2mLBa1Pq`sxrW8fNNq:XF0@KP5RLW9u?[E_wwkROmCSWudYoS5I2HGI-1-?Pd0zVxTIeNbF;nLDUGtce{8dHmx90:;N<8", "$2a$07$ePVgkQl8QKSG2Xv6o0bnOe4SZp4ejag5CP44tjxfmY17F5VzRgwF6"},
+            new string[]{"dj~OsXmQGj6FXnPGgwg9]G@75~L@G[|e<hgh2vaNqIyYZPh@M;I1DTgZS/~Q:i[6d]oei:hBw4}{}y7k9K^4SoN}wb8mrg[", "$2a$04$BZT7YoAYAgtNkD0/BOl.jOi0dDni7WtmB8.wAebHeHkOs.TpRgml."},
+            new string[]{"7;PjW]RYJoZXf.r2M^Mm1jVIe0wJ=Kdd2iUBuu1v3HGI1-S[TB6yg{0~:nbpeA08dysS5d}@Oxbrpj[~i-60mpq1WZqQmSVpnR", "$2a$07$fa9NDzoPKiSWC67cP/tj2OqE0PqvGwzRoJiCKj.czyqKyvpdtVpKe"},
+            new string[]{"8nv;PAN~-FQ]Emh@.TKG=^.t8R0EQC0T?x9|9g4xzxYmSbBO1qDx8kv-ehh0IBv>3KWhz.Z~jUF0tt8[5U@8;5:=[v6pf.IEJ", "$2a$08$eXo9KDc1BZyybBgMurpcD.GA1/ch3XhgBnIH10Xvjc2ogZaGg3t/m"},
+        };
+
+        public override string Name
+        {
+            get { return "OpenBsdBCrypt"; }
+        }
+
+        public override void PerformTest()
+        {
+            string encoded, password;
+
+            for (int i = 0; i < BCryptTest1.Length; i++)
+            {
+                string[] testString = BCryptTest1[i];
+                encoded = testString[0];
+                password = testString[1];
+                if (!OpenBsdBCrypt.CheckPassword(encoded, password.ToCharArray()))
+                {
+                    Fail("test1 mismatch: " + "[" + i + "] " + password);
+                }
+            }
+
+            encoded = BCryptTest2[0];
+            password = BCryptTest2[1];
+            if (!OpenBsdBCrypt.CheckPassword(encoded, password.ToCharArray()))
+            {
+                Fail("bcryptTest2 mismatch: " + password);
+            }
+
+            encoded = BCryptTest2b[0];
+            password = BCryptTest2b[1];
+            if (!OpenBsdBCrypt.CheckPassword(encoded, password.ToCharArray()))
+            {
+                Fail("bcryptTest2b mismatch: " + password);
+            }
+
+            for (int i = 0; i < BCryptTest3.Length; i++)
+            {
+                string[] testString = BCryptTest3[i];
+                encoded = testString[2];
+                password = testString[0];
+                if (!OpenBsdBCrypt.CheckPassword(encoded, password.ToCharArray()))
+                {
+                    Fail("test3 mismatch: " + "[" + i + "] " + password);
+                }
+            }
+
+            for (int i = 0; i < BCryptTest4.Length; i++)
+            {
+                string[] testString = BCryptTest4[i];
+                encoded = testString[1];
+                password = testString[0];
+                if (!OpenBsdBCrypt.CheckPassword(encoded, password.ToCharArray()))
+                {
+                    Fail("test4 mismatch: " + "[" + i + "] " + password);
+                }
+            }
+        }
+
+        public static void Main(string[] args)
+        {
+            RunTest(new OpenBsdBCryptTest());
+        }
+
+        [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 ea9fd84f2..3611e4e63 100644
--- a/crypto/test/src/crypto/test/RegressionTest.cs
+++ b/crypto/test/src/crypto/test/RegressionTest.cs
@@ -122,19 +122,18 @@ namespace Org.BouncyCastle.Crypto.Tests
             new NonMemoableDigestTest(),
             new StreamCipherResetTest(),
             new SM3DigestTest(),
+            new BCryptTest(),
+            new OpenBsdBCryptTest(),
             new X931SignerTest(),
             new KeccakDigestTest(),
             new ShakeDigestTest(),
         };
 
-        public static void Main(
-            string[] args)
+        public static void Main(string[] args)
         {
-            for (int i = 0; i != tests.Length; i++)
+            foreach (ITest test in tests)
             {
-                ITestResult result = tests[i].Perform();
-
-                Console.WriteLine(result);
+                SimpleTest.RunTest(test);
             }
         }
     }