summary refs log tree commit diff
path: root/crypto/test
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/test')
-rw-r--r--crypto/test/src/crypto/agreement/test/AllTests.cs31
-rw-r--r--crypto/test/src/crypto/agreement/test/JPakeParticipantTest.cs566
-rw-r--r--crypto/test/src/crypto/agreement/test/JPakePrimeOrderGroupTest.cs117
-rw-r--r--crypto/test/src/crypto/agreement/test/JPakeUtilitiesTest.cs306
-rw-r--r--crypto/test/src/crypto/tls/test/TlsProtocolNonBlockingTest.cs4
-rw-r--r--crypto/test/src/openpgp/examples/ByteArrayHandler.cs2
-rw-r--r--crypto/test/src/openpgp/examples/PbeFileProcessor.cs2
-rw-r--r--crypto/test/src/openpgp/test/PGPPBETest.cs10
-rw-r--r--crypto/test/src/openpgp/test/PGPRSATest.cs2
-rw-r--r--crypto/test/src/openpgp/test/PgpKeyRingTest.cs6
-rw-r--r--crypto/test/src/openpgp/test/PgpUnicodeTest.cs15
11 files changed, 1043 insertions, 18 deletions
diff --git a/crypto/test/src/crypto/agreement/test/AllTests.cs b/crypto/test/src/crypto/agreement/test/AllTests.cs
new file mode 100644
index 000000000..ea8f438e5
--- /dev/null
+++ b/crypto/test/src/crypto/agreement/test/AllTests.cs
@@ -0,0 +1,31 @@
+using System;
+
+using NUnit.Core;
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Tests
+{
+    [TestFixture]
+    public class AllTests
+    {
+        public static void Main(string[] args)
+        {
+            Suite.Run(new NullListener(), NUnit.Core.TestFilter.Empty);
+        }
+
+        [Suite]
+        public static TestSuite Suite
+        {
+            get
+            {
+                TestSuite suite = new TestSuite("JPAKE Engine Tests");
+                suite.Add(new JPakeParticipantTest());
+                suite.Add(new JPakePrimeOrderGroupTest());
+                suite.Add(new JPakeUtilitiesTest());
+                return suite;
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/agreement/test/JPakeParticipantTest.cs b/crypto/test/src/crypto/agreement/test/JPakeParticipantTest.cs
new file mode 100644
index 000000000..c84264aa5
--- /dev/null
+++ b/crypto/test/src/crypto/agreement/test/JPakeParticipantTest.cs
@@ -0,0 +1,566 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Agreement.JPake;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Tests
+{
+    [TestFixture]
+    public class JPakeParticipantTest
+        : SimpleTest
+    {
+        public override void PerformTest()
+        {
+            TestConstruction();
+            TestSuccessfulExchange();
+            TestIncorrectPassword();
+            TestStateValidation();
+            TestValidateRound1PayloadReceived();
+            TestValidateRound2PayloadReceived();
+        }
+
+        public override string Name
+        {
+            get { return "JPakeParticipant"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new JPakeParticipantTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+
+        public void TestConstruction()
+        {
+            JPakePrimeOrderGroup group = JPakePrimeOrderGroups.SUN_JCE_1024;
+            SecureRandom random = new SecureRandom();
+            IDigest digest = new Sha256Digest();
+            string participantId = "participantId";
+            char[] password = "password".ToCharArray();
+
+            // should succeed
+            new JPakeParticipant(participantId, password, group, digest, random);
+
+            // null participantId
+            try
+            {
+                new JPakeParticipant(null, password, group, digest, random);
+
+                Fail("failed to throw exception on null participantId");
+            }
+            catch (ArgumentNullException)
+            {
+                // expected
+            }
+
+            // null password
+            try
+            {
+                new JPakeParticipant(participantId, null, group, digest, random);
+
+                Fail("failed to throw exception on null password");
+            }
+            catch (ArgumentNullException)
+            {
+                // expected
+            }
+
+            // empty password
+            try
+            {
+                new JPakeParticipant(participantId, "".ToCharArray(), group, digest, random);
+
+                Fail("failed to throw exception on empty password");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            // null group
+            try
+            {
+                new JPakeParticipant(participantId, password, null, digest, random);
+
+                Fail("failed to throw exception on null group");
+            }
+            catch (ArgumentNullException)
+            {
+                // expected
+            }
+
+            // null digest
+            try
+            {
+                new JPakeParticipant(participantId, password, group, null, random);
+
+                Fail("failed to throw exception on null digest");
+            }
+            catch (ArgumentNullException)
+            {
+                // expected
+            }
+
+            // null random
+            try
+            {
+                new JPakeParticipant(participantId, password, group, digest, null);
+
+                Fail("failed to throw exception on null random");
+            }
+            catch (ArgumentNullException)
+            {
+                // expected
+            }
+        }
+
+        public void TestSuccessfulExchange()
+        {
+            JPakeParticipant alice = CreateAlice();
+            JPakeParticipant bob = CreateBob();
+
+            ExchangeAfterRound2Creation exchange = RunExchangeUntilRound2Creation(alice, bob);
+
+            alice.ValidateRound2PayloadReceived(exchange.bobRound2Payload);
+            bob.ValidateRound2PayloadReceived(exchange.aliceRound2Payload);
+
+            BigInteger aliceKeyingMaterial = alice.CalculateKeyingMaterial();
+            BigInteger bobKeyingMaterial = bob.CalculateKeyingMaterial();
+
+            JPakeRound3Payload aliceRound3Payload = alice.CreateRound3PayloadToSend(aliceKeyingMaterial);
+            JPakeRound3Payload bobRound3Payload = bob.CreateRound3PayloadToSend(bobKeyingMaterial);
+
+            alice.ValidateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
+            bob.ValidateRound3PayloadReceived(aliceRound3Payload, bobKeyingMaterial);
+
+            Assert.AreEqual(aliceKeyingMaterial, bobKeyingMaterial);
+        }
+
+        public void TestIncorrectPassword()
+        {
+            JPakeParticipant alice = CreateAlice();
+            JPakeParticipant bob = CreateBobWithWrongPassword();
+
+            ExchangeAfterRound2Creation exchange = RunExchangeUntilRound2Creation(alice, bob);
+
+            alice.ValidateRound2PayloadReceived(exchange.bobRound2Payload);
+            bob.ValidateRound2PayloadReceived(exchange.aliceRound2Payload);
+
+            BigInteger aliceKeyingMaterial = alice.CalculateKeyingMaterial();
+            BigInteger bobKeyingMaterial = bob.CalculateKeyingMaterial();
+
+            JPakeRound3Payload aliceRound3Payload = alice.CreateRound3PayloadToSend(aliceKeyingMaterial);
+            JPakeRound3Payload bobRound3Payload = bob.CreateRound3PayloadToSend(bobKeyingMaterial);
+
+            try
+            {
+                alice.ValidateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
+
+                Fail("failed to throw exception on incorrect password");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+
+            try
+            {
+                bob.ValidateRound3PayloadReceived(aliceRound3Payload, bobKeyingMaterial);
+
+                Fail("failed to throw exception on incorrect password");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+        }
+
+        public void TestStateValidation()
+        {
+            JPakeParticipant alice = CreateAlice();
+            JPakeParticipant bob = CreateBob();
+
+            // We're testing alice here. Bob is just used for help.
+
+            // START ROUND 1 CHECKS
+
+            Assert.AreEqual(JPakeParticipant.STATE_INITIALIZED, alice.State);
+
+            // create round 2 before round 1
+            try
+            {
+                alice.CreateRound2PayloadToSend();
+
+                Fail("failed to throw on round 2 creation before 1");
+            }
+            catch (InvalidOperationException)
+            {
+                // expected
+            }
+
+            JPakeRound1Payload aliceRound1Payload = alice.CreateRound1PayloadToSend();
+            Assert.AreEqual(JPakeParticipant.STATE_ROUND_1_CREATED, alice.State);
+
+            // create round 1 twice
+            try
+            {
+                alice.CreateRound1PayloadToSend();
+
+                Fail("failed to throw on round 1 creation twice");
+            }
+            catch (InvalidOperationException)
+            {
+                // expected
+            }
+
+            // create round 2 before validation round 1
+            try
+            {
+                alice.CreateRound2PayloadToSend();
+
+                Fail("failed to throw on round 2 creation before round 1 validation");
+            }
+            catch (InvalidOperationException)
+            {
+                // expected
+            }
+
+            // validate round 2 before validation round 1
+            try
+            {
+                alice.ValidateRound2PayloadReceived(null);
+
+                Fail("failed to throw on round 2 validation before round 1 validation");
+            }
+            catch (InvalidOperationException)
+            {
+                // expected
+            }
+
+            JPakeRound1Payload bobRound1Payload = bob.CreateRound1PayloadToSend();
+            alice.ValidateRound1PayloadReceived(bobRound1Payload);
+            Assert.AreEqual(JPakeParticipant.STATE_ROUND_1_VALIDATED, alice.State);
+
+            // validate round 1 payload twice
+            try
+            {
+                alice.ValidateRound1PayloadReceived(bobRound1Payload);
+
+                Fail("failed to throw on round 1 validation twice");
+            }
+            catch (InvalidOperationException)
+            {
+                // expected
+            }
+
+            bob.ValidateRound1PayloadReceived(aliceRound1Payload);
+
+            // START ROUND 2 CHECKS
+
+            JPakeRound2Payload aliceRound2Payload = alice.CreateRound2PayloadToSend();
+            Assert.AreEqual(JPakeParticipant.STATE_ROUND_2_CREATED, alice.State);
+
+            // create round 2 payload twice
+            try
+            {
+                alice.CreateRound2PayloadToSend();
+
+                Fail("failed to throw on round 2 creation twice");
+            }
+            catch (InvalidOperationException)
+            {
+                // expected
+            }
+
+            // create key before validation round 2
+            try
+            {
+                alice.CalculateKeyingMaterial();
+
+                Fail("failed to throw on calculating keying material before round 2 validation");
+            }
+            catch (InvalidOperationException)
+            {
+                // expected
+            }
+
+            // validate round 3 before validating round 2
+            try
+            {
+                alice.ValidateRound3PayloadReceived(null, null);
+
+                Fail("failed to throw on validating round 3 before 2");
+            }
+            catch (InvalidOperationException)
+            {
+                // expected
+            }
+
+            JPakeRound2Payload bobRound2Payload = bob.CreateRound2PayloadToSend();
+            alice.ValidateRound2PayloadReceived(bobRound2Payload);
+            Assert.AreEqual(JPakeParticipant.STATE_ROUND_2_VALIDATED, alice.State);
+
+            // validate round 2 payload twice
+            try
+            {
+                alice.ValidateRound2PayloadReceived(bobRound2Payload);
+
+                Fail("failed to throw on validating round 2 twice");
+            }
+            catch (InvalidOperationException)
+            {
+                // expected
+            }
+
+            bob.ValidateRound2PayloadReceived(aliceRound2Payload);
+
+            // create round 3 before calculating key
+            try
+            {
+                alice.CreateRound3PayloadToSend(BigInteger.One);
+
+                Fail("failed to throw on creating round 3 before calculating key aterial");
+            }
+            catch (InvalidOperationException)
+            {
+                // expected
+            }
+
+            // START KEY CALCULATION CHECKS
+
+            BigInteger aliceKeyingMaterial = alice.CalculateKeyingMaterial();
+            Assert.AreEqual(JPakeParticipant.STATE_KEY_CALCULATED, alice.State);
+
+            // calculate key twice
+            try
+            {
+                alice.CalculateKeyingMaterial();
+
+                Fail("failed to throw on calculating key twice");
+            }
+            catch (InvalidOperationException)
+            {
+                // expected
+            }
+
+            BigInteger bobKeyingMaterial = bob.CalculateKeyingMaterial();
+
+            // START ROUND 3 CHECKS
+
+            JPakeRound3Payload aliceRound3Payload = alice.CreateRound3PayloadToSend(aliceKeyingMaterial);
+            Assert.AreEqual(JPakeParticipant.STATE_ROUND_3_CREATED, alice.State);
+
+            // create round 3 payload twice
+            try
+            {
+                alice.CreateRound3PayloadToSend(aliceKeyingMaterial);
+
+                Fail("failed to throw on creation round 3 twice");
+            }
+            catch (InvalidOperationException)
+            {
+                // expected
+            }
+
+            JPakeRound3Payload bobRound3Payload = bob.CreateRound3PayloadToSend(bobKeyingMaterial);
+            alice.ValidateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
+            Assert.AreEqual(JPakeParticipant.STATE_ROUND_3_VALIDATED, alice.State);
+
+            // validate round 3 payload twice
+            try
+            {
+                alice.ValidateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
+
+                Fail("failed to throw on validation round 3 twice");
+            }
+            catch (InvalidOperationException)
+            {
+                // expected
+            }
+
+            bob.ValidateRound3PayloadReceived(aliceRound3Payload, bobKeyingMaterial);
+        }
+
+        public void TestValidateRound1PayloadReceived()
+        {
+            // We're testing alice here. Bob is just used for help.
+
+            JPakeRound1Payload bobRound1Payload = CreateBob().CreateRound1PayloadToSend();
+
+            // should succeed
+            CreateAlice().ValidateRound1PayloadReceived(bobRound1Payload);
+
+            // alice verifies alice's payload
+            try
+            {
+                JPakeParticipant alice = CreateAlice();
+                alice.ValidateRound1PayloadReceived(alice.CreateRound1PayloadToSend());
+
+                Fail("failed to throw on participant validating own payload");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+
+            // g^x4 == 1
+            try
+            {
+                CreateAlice().ValidateRound1PayloadReceived(new JPakeRound1Payload(
+                    bobRound1Payload.ParticipantId,
+                    bobRound1Payload.Gx1,
+                    BigInteger.One,
+                    bobRound1Payload.KnowledgeProofForX1,
+                    bobRound1Payload.KnowledgeProofForX2));
+
+                Fail("failed to throw on g^x4 == 1");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+
+            // zero knowledge proof for x3 fails
+            try
+            {
+                JPakeRound1Payload bobRound1Payload2 = CreateBob().CreateRound1PayloadToSend();
+                CreateAlice().ValidateRound1PayloadReceived(new JPakeRound1Payload(
+                    bobRound1Payload.ParticipantId,
+                    bobRound1Payload.Gx1,
+                    bobRound1Payload.Gx2,
+                    bobRound1Payload2.KnowledgeProofForX1,
+                    bobRound1Payload.KnowledgeProofForX2));
+
+                Fail("failed to throw on incorrect zero knowledge proof for x3");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+
+            // zero knowledge proof for x4 fails
+            try
+            {
+                JPakeRound1Payload bobRound1Payload2 = CreateBob().CreateRound1PayloadToSend();
+                CreateAlice().ValidateRound1PayloadReceived(new JPakeRound1Payload(
+                    bobRound1Payload.ParticipantId,
+                    bobRound1Payload.Gx1,
+                    bobRound1Payload.Gx2,
+                    bobRound1Payload.KnowledgeProofForX1,
+                    bobRound1Payload2.KnowledgeProofForX2));
+
+                Fail("failed to throw on incorrect zero knowledge proof for x4");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+        }
+
+        public void TestValidateRound2PayloadReceived()
+        {
+            // We're testing alice here. Bob is just used for help.
+
+            // should succeed
+            ExchangeAfterRound2Creation exchange1 = RunExchangeUntilRound2Creation(CreateAlice(), CreateBob());
+            exchange1.alice.ValidateRound2PayloadReceived(exchange1.bobRound2Payload);
+
+            // alice verified alice's payload
+            ExchangeAfterRound2Creation exchange2 = RunExchangeUntilRound2Creation(CreateAlice(), CreateBob());
+            try
+            {
+                exchange2.alice.ValidateRound2PayloadReceived(exchange2.aliceRound2Payload);
+
+                Fail("failed to throw on participant verifying own payload 2");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+
+            // wrong z
+            ExchangeAfterRound2Creation exchange3 = RunExchangeUntilRound2Creation(CreateAlice(), CreateBob());
+            ExchangeAfterRound2Creation exchange4 = RunExchangeUntilRound2Creation(CreateAlice(), CreateBob());
+            try
+            {
+                exchange3.alice.ValidateRound2PayloadReceived(exchange4.bobRound2Payload);
+
+                Fail("failed to throw on wrong z");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+        }
+
+        private class ExchangeAfterRound2Creation
+        {
+            public JPakeParticipant alice;
+            public JPakeRound2Payload aliceRound2Payload;
+            public JPakeRound2Payload bobRound2Payload;
+
+            public ExchangeAfterRound2Creation(
+                JPakeParticipant alice,
+                JPakeRound2Payload aliceRound2Payload,
+                JPakeRound2Payload bobRound2Payload)
+            {
+                this.alice = alice;
+                this.aliceRound2Payload = aliceRound2Payload;
+                this.bobRound2Payload = bobRound2Payload;
+            }
+        }
+
+        private ExchangeAfterRound2Creation RunExchangeUntilRound2Creation(JPakeParticipant alice, JPakeParticipant bob)
+        {
+            JPakeRound1Payload aliceRound1Payload = alice.CreateRound1PayloadToSend();
+            JPakeRound1Payload bobRound1Payload = bob.CreateRound1PayloadToSend();
+
+            alice.ValidateRound1PayloadReceived(bobRound1Payload);
+            bob.ValidateRound1PayloadReceived(aliceRound1Payload);
+
+            JPakeRound2Payload aliceRound2Payload = alice.CreateRound2PayloadToSend();
+            JPakeRound2Payload bobRound2Payload = bob.CreateRound2PayloadToSend();
+
+            return new ExchangeAfterRound2Creation(
+                alice,
+                aliceRound2Payload,
+                bobRound2Payload);
+        }
+
+        private JPakeParticipant CreateAlice()
+        {
+            return CreateParticipant("alice", "password");
+        }
+
+        private JPakeParticipant CreateBob()
+        {
+            return CreateParticipant("bob", "password");
+        }
+
+        private JPakeParticipant CreateBobWithWrongPassword()
+        {
+            return CreateParticipant("bob", "wrong");
+        }
+
+        private JPakeParticipant CreateParticipant(string participantId, string password)
+        {
+            return new JPakeParticipant(
+                participantId,
+                password.ToCharArray(),
+                JPakePrimeOrderGroups.SUN_JCE_1024);
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/agreement/test/JPakePrimeOrderGroupTest.cs b/crypto/test/src/crypto/agreement/test/JPakePrimeOrderGroupTest.cs
new file mode 100644
index 000000000..0f089f93c
--- /dev/null
+++ b/crypto/test/src/crypto/agreement/test/JPakePrimeOrderGroupTest.cs
@@ -0,0 +1,117 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Agreement.JPake;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Tests
+{
+    [TestFixture]
+    public class JPakePrimeOrderGroupTest
+        : SimpleTest
+    {
+        public override void PerformTest()
+        {
+            TestConstruction();
+        }
+
+        public override string Name
+        {
+            get { return "JPakePrimeOrderGroup"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new JPakePrimeOrderGroupTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+
+        public void TestConstruction()
+        {
+            // p-1 not evenly divisible by q
+            try
+            {
+                new JPakePrimeOrderGroup(BigInteger.ValueOf(7), BigInteger.ValueOf(5), BigInteger.ValueOf(6));
+
+                Fail("failed to throw exception on p-1 not evenly divisible by q");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            // g < 2
+            try
+            {
+                new JPakePrimeOrderGroup(BigInteger.ValueOf(11), BigInteger.ValueOf(5), BigInteger.ValueOf(1));
+
+                Fail("failed to throw exception on g < 2");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            // g > p - 1
+            try
+            {
+                new JPakePrimeOrderGroup(BigInteger.ValueOf(11), BigInteger.ValueOf(5), BigInteger.ValueOf(11));
+
+                Fail("failed to throw exception on g > p - 1");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            //g^q mod p not equal 1
+            try
+            {
+                new JPakePrimeOrderGroup(BigInteger.ValueOf(11), BigInteger.ValueOf(5), BigInteger.ValueOf(6));
+
+                Fail("failed to throw exception on g^q mod p not equal 1");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            // p not prime
+            try
+            {
+                new JPakePrimeOrderGroup(BigInteger.ValueOf(15), BigInteger.ValueOf(2), BigInteger.ValueOf(4));
+
+                Fail("failed to throw exception on p not prime");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            // q not prime
+            try
+            {
+                new JPakePrimeOrderGroup(BigInteger.ValueOf(7), BigInteger.ValueOf(6), BigInteger.ValueOf(3));
+
+                Fail("failed to throw exception on q not prime");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            // should succeed
+            new JPakePrimeOrderGroup(BigInteger.ValueOf(7), BigInteger.ValueOf(3), BigInteger.ValueOf(4));
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/agreement/test/JPakeUtilitiesTest.cs b/crypto/test/src/crypto/agreement/test/JPakeUtilitiesTest.cs
new file mode 100644
index 000000000..04a52cc06
--- /dev/null
+++ b/crypto/test/src/crypto/agreement/test/JPakeUtilitiesTest.cs
@@ -0,0 +1,306 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Agreement.JPake;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Tests
+{
+    [TestFixture]
+    public class JPakeUtilitiesTest
+        : SimpleTest
+    {
+        private static readonly BigInteger Ten = BigInteger.ValueOf(10);
+
+        public override void PerformTest()
+        {
+            TestValidateGx4();
+            TestValidateGa();
+            TestValidateParticipantIdsDiffer();
+            TestValidateParticipantsIdsEqual();
+            TestValidateMacTag();
+            TestValidateNotNull();
+            TestValidateZeroKnowledgeProof();
+        }
+
+        public override string Name
+        {
+            get { return "JPakeUtilities"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new JPakeUtilitiesTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+
+        public void TestValidateGx4()
+        {
+            JPakeUtilities.ValidateGx4(Ten);
+
+            try
+            {
+                JPakeUtilities.ValidateGx4(BigInteger.One);
+
+                Fail("exception not thrown for g^x4 equal to 1");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+        }
+
+        public void TestValidateGa()
+        {
+            JPakeUtilities.ValidateGa(Ten);
+
+            try
+            {
+                JPakeUtilities.ValidateGa(BigInteger.One);
+
+                Fail("exception not thrown for g^a equal to 1");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+        }
+
+        public void TestValidateParticipantIdsDiffer()
+        {
+            JPakeUtilities.ValidateParticipantIdsDiffer("a", "b");
+            JPakeUtilities.ValidateParticipantIdsDiffer("a", "A");
+
+            try
+            {
+                JPakeUtilities.ValidateParticipantIdsDiffer("a", "a");
+
+                Fail("validate participant ids differ not throwing exception for equal participant ids");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+        }
+
+        public void TestValidateParticipantsIdsEqual()
+        {
+            JPakeUtilities.ValidateParticipantIdsEqual("a", "a");
+
+            try
+            {
+                JPakeUtilities.ValidateParticipantIdsEqual("a", "b");
+
+                Fail("validate participant ids equal not throwing exception for different participant ids");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+        }
+
+        public void TestValidateMacTag()
+        {
+            JPakePrimeOrderGroup pg1 = JPakePrimeOrderGroups.SUN_JCE_1024;
+
+            SecureRandom random = new SecureRandom();
+            IDigest digest = new Sha256Digest();
+
+            BigInteger x1 = JPakeUtilities.GenerateX1(pg1.Q, random);
+            BigInteger x2 = JPakeUtilities.GenerateX2(pg1.Q, random);
+            BigInteger x3 = JPakeUtilities.GenerateX1(pg1.Q, random);
+            BigInteger x4 = JPakeUtilities.GenerateX2(pg1.Q, random);
+
+            BigInteger gx1 = JPakeUtilities.CalculateGx(pg1.P, pg1.G, x1);
+            BigInteger gx2 = JPakeUtilities.CalculateGx(pg1.P, pg1.G, x2);
+            BigInteger gx3 = JPakeUtilities.CalculateGx(pg1.P, pg1.G, x3);
+            BigInteger gx4 = JPakeUtilities.CalculateGx(pg1.P, pg1.G, x4);
+
+            BigInteger gB = JPakeUtilities.CalculateGA(pg1.P, gx3, gx1, gx2);
+
+            BigInteger s = JPakeUtilities.CalculateS("password".ToCharArray());
+
+            BigInteger xs = JPakeUtilities.CalculateX2s(pg1.Q, x4, s);
+
+            BigInteger B = JPakeUtilities.CalculateA(pg1.P, pg1.Q, gB, xs);
+
+            BigInteger keyingMaterial = JPakeUtilities.CalculateKeyingMaterial(pg1.P, pg1.Q, gx4, x2, s, B);
+
+            BigInteger macTag = JPakeUtilities.CalculateMacTag("participantId", "partnerParticipantId", gx1, gx2, gx3, gx4, keyingMaterial, digest);
+
+            // should succeed
+            JPakeUtilities.ValidateMacTag("partnerParticipantId", "participantId", gx3, gx4, gx1, gx2, keyingMaterial, digest, macTag);
+
+            // validating own macTag (as opposed to the other party's mactag)
+            try
+            {
+                JPakeUtilities.ValidateMacTag("participantId", "partnerParticipantId", gx1, gx2, gx3, gx4, keyingMaterial, digest, macTag);
+
+                Fail("failed to throw exception on validating own macTag (calculated partner macTag)");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+
+            // participant ids switched
+            try
+            {
+                JPakeUtilities.ValidateMacTag("participantId", "partnerParticipantId", gx3, gx4, gx1, gx2, keyingMaterial, digest, macTag);
+
+                Fail("failed to throw exception on validating own macTag (calculated partner macTag");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+        }
+
+        public void TestValidateNotNull()
+        {
+            JPakeUtilities.ValidateNotNull("a", "description");
+
+            try
+            {
+                JPakeUtilities.ValidateNotNull(null, "description");
+
+                Fail("failed to throw exception on null");
+            }
+            catch (ArgumentNullException)
+            {
+                // expected
+            }
+        }
+
+        public void TestValidateZeroKnowledgeProof()
+        {
+            JPakePrimeOrderGroup pg1 = JPakePrimeOrderGroups.SUN_JCE_1024;
+
+            SecureRandom random = new SecureRandom();
+            IDigest digest1 = new Sha256Digest();
+
+            BigInteger x1 = JPakeUtilities.GenerateX1(pg1.Q, random);
+            BigInteger gx1 = JPakeUtilities.CalculateGx(pg1.P, pg1.G, x1);
+            string participantId1 = "participant1";
+
+            BigInteger[] zkp1 = JPakeUtilities.CalculateZeroKnowledgeProof(pg1.P, pg1.Q, pg1.G, gx1, x1, participantId1, digest1, random);
+
+            // should succeed
+            JPakeUtilities.ValidateZeroKnowledgeProof(pg1.P, pg1.Q, pg1.G, gx1, zkp1, participantId1, digest1);
+
+            // wrong group
+            JPakePrimeOrderGroup pg2 = JPakePrimeOrderGroups.NIST_3072;
+            try
+            {
+                JPakeUtilities.ValidateZeroKnowledgeProof(pg2.P, pg2.Q, pg2.G, gx1, zkp1, participantId1, digest1);
+
+                Fail("failed to throw exception on wrong prime order group");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+
+            // wrong digest
+            IDigest digest2 = new Sha1Digest();
+            try
+            {
+                JPakeUtilities.ValidateZeroKnowledgeProof(pg1.P, pg1.Q, pg1.G, gx1, zkp1, participantId1, digest2);
+
+                Fail("failed to throw exception on wrong digest");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+
+            // wrong participant
+            string participantId2 = "participant2";
+            try
+            {
+                JPakeUtilities.ValidateZeroKnowledgeProof(pg1.P, pg1.Q, pg1.G, gx1, zkp1, participantId2, digest1);
+
+                Fail("failed to throw exception on wrong participant");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+
+            // wrong gx
+            BigInteger x2 = JPakeUtilities.GenerateX2(pg1.Q, random);
+            BigInteger gx2 = JPakeUtilities.CalculateGx(pg1.P, pg1.G, x2);
+            try
+            {
+                JPakeUtilities.ValidateZeroKnowledgeProof(pg1.P, pg1.Q, pg1.G, gx2, zkp1, participantId1, digest1);
+
+                Fail("failed to throw exception on wrong gx");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+
+            // wrong zkp
+            BigInteger[] zkp2 = JPakeUtilities.CalculateZeroKnowledgeProof(pg1.P, pg1.Q, pg1.G, gx2, x2, participantId1, digest1, random);
+            try
+            {
+                JPakeUtilities.ValidateZeroKnowledgeProof(pg1.P, pg1.Q, pg1.G, gx1, zkp2, participantId1, digest1);
+
+                Fail("failed to throw exception on wrong zero knowledge proof");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+
+            // gx <= 0
+            try
+            {
+                JPakeUtilities.ValidateZeroKnowledgeProof(pg1.P, pg1.Q, pg1.G, BigInteger.Zero, zkp1, participantId1, digest1);
+
+                Fail("failed to throw exception on g^x <= 0");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+
+            // gx >= p
+            try
+            {
+                JPakeUtilities.ValidateZeroKnowledgeProof(pg1.P, pg1.Q, pg1.G, pg1.P, zkp1, participantId1, digest1);
+
+                Fail("failed to throw exception on g^x >= p");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+
+            // gx mod q == 1
+            try
+            {
+                JPakeUtilities.ValidateZeroKnowledgeProof(pg1.P, pg1.Q, pg1.G, pg1.Q.Add(BigInteger.One), zkp1, participantId1, digest1);
+
+                Fail("failed to throw exception on g^x mod q == 1");
+            }
+            catch (CryptoException)
+            {
+                // expected
+            }
+        }
+    }
+}
diff --git a/crypto/test/src/crypto/tls/test/TlsProtocolNonBlockingTest.cs b/crypto/test/src/crypto/tls/test/TlsProtocolNonBlockingTest.cs
index 5fe0f32ad..477e287f1 100644
--- a/crypto/test/src/crypto/tls/test/TlsProtocolNonBlockingTest.cs
+++ b/crypto/test/src/crypto/tls/test/TlsProtocolNonBlockingTest.cs
@@ -104,7 +104,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
                 protocol.OfferInput(new byte[10]);
                 Assert.Fail("Input was accepted after close");
             }
-            catch (IOException e)
+            catch (IOException)
             {
             }
 
@@ -113,7 +113,7 @@ namespace Org.BouncyCastle.Crypto.Tls.Tests
                 protocol.OfferOutput(new byte[10], 0, 10);
                 Assert.Fail("Output was accepted after close");
             }
-            catch (IOException e)
+            catch (IOException)
             {
             }
         }
diff --git a/crypto/test/src/openpgp/examples/ByteArrayHandler.cs b/crypto/test/src/openpgp/examples/ByteArrayHandler.cs
index 676db8766..b5098ff66 100644
--- a/crypto/test/src/openpgp/examples/ByteArrayHandler.cs
+++ b/crypto/test/src/openpgp/examples/ByteArrayHandler.cs
@@ -123,7 +123,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
 			}
 
 			PgpEncryptedDataGenerator encGen = new PgpEncryptedDataGenerator(algorithm, new SecureRandom());
-            encGen.AddMethod(passPhrase);
+            encGen.AddMethod(passPhrase, HashAlgorithmTag.Sha1);
 
 			Stream encOut = encGen.Open(output, compressedData.Length);
 
diff --git a/crypto/test/src/openpgp/examples/PbeFileProcessor.cs b/crypto/test/src/openpgp/examples/PbeFileProcessor.cs
index 66b1cc4ed..961704407 100644
--- a/crypto/test/src/openpgp/examples/PbeFileProcessor.cs
+++ b/crypto/test/src/openpgp/examples/PbeFileProcessor.cs
@@ -127,7 +127,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
 
 				PgpEncryptedDataGenerator encGen = new PgpEncryptedDataGenerator(
 					SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());
-				encGen.AddMethod(passPhrase);
+                encGen.AddMethod(passPhrase, HashAlgorithmTag.Sha1);
 
 				Stream encOut = encGen.Open(outputStream, compressedData.Length);
 
diff --git a/crypto/test/src/openpgp/test/PGPPBETest.cs b/crypto/test/src/openpgp/test/PGPPBETest.cs
index 621cef684..29b786a83 100644
--- a/crypto/test/src/openpgp/test/PGPPBETest.cs
+++ b/crypto/test/src/openpgp/test/PGPPBETest.cs
@@ -168,7 +168,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(
 				SymmetricKeyAlgorithmTag.Cast5, new SecureRandom());
 
-            cPk.AddMethod(pass);
+            cPk.AddMethod(pass, HashAlgorithmTag.Sha1);
 
 			byte[] bOutData = bOut.ToArray();
 			Stream cOut = cPk.Open(new UncloseableStream(cbOut), bOutData.Length);
@@ -188,7 +188,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 			cPk = new PgpEncryptedDataGenerator(
 				SymmetricKeyAlgorithmTag.Cast5, new SecureRandom());
 
-			cPk.AddMethod(pass);
+            cPk.AddMethod(pass, HashAlgorithmTag.Sha1);
 
 			bOutData = bOut.ToArray();
 			cOut = cPk.Open(new UncloseableStream(cbOut), bOutData.Length);
@@ -233,7 +233,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             cPk = new PgpEncryptedDataGenerator(
 				SymmetricKeyAlgorithmTag.Cast5, rand);
 
-            cPk.AddMethod(pass);
+            cPk.AddMethod(pass, HashAlgorithmTag.Sha1);
 
 			cOut = cPk.Open(new UncloseableStream(cbOut), new byte[16]);
             {
@@ -256,7 +256,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             cPk = new PgpEncryptedDataGenerator(
 				SymmetricKeyAlgorithmTag.Cast5, true, rand);
 
-            cPk.AddMethod(pass);
+            cPk.AddMethod(pass, HashAlgorithmTag.Sha1);
 
             cOut = cPk.Open(new UncloseableStream(cbOut), new byte[16]);
             bOutData = bOut.ToArray();
@@ -328,7 +328,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 			cbOut = new MemoryStream();
 			cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, true, rand);
 
-			cPk.AddMethod(pass);
+            cPk.AddMethod(pass, HashAlgorithmTag.Sha1);
 
 			cOut = cPk.Open(new UncloseableStream(cbOut), new byte[16]);
 
diff --git a/crypto/test/src/openpgp/test/PGPRSATest.cs b/crypto/test/src/openpgp/test/PGPRSATest.cs
index 35f844483..82b569bbb 100644
--- a/crypto/test/src/openpgp/test/PGPRSATest.cs
+++ b/crypto/test/src/openpgp/test/PGPRSATest.cs
@@ -381,7 +381,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 
             encGen.AddMethod(pgpPubKey);
 
-            encGen.AddMethod("password".ToCharArray());
+            encGen.AddMethod("password".ToCharArray(), HashAlgorithmTag.Sha1);
 
             Stream cOut = encGen.Open(bcOut, bytes.Length);
 
diff --git a/crypto/test/src/openpgp/test/PgpKeyRingTest.cs b/crypto/test/src/openpgp/test/PgpKeyRingTest.cs
index 9896c1ef6..43aef5afa 100644
--- a/crypto/test/src/openpgp/test/PgpKeyRingTest.cs
+++ b/crypto/test/src/openpgp/test/PgpKeyRingTest.cs
@@ -1844,7 +1844,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             PgpKeyPair elgKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.ElGamalEncrypt, elgKp, DateTime.UtcNow);
 
             PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification, dsaKeyPair,
-                "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, null, null, new SecureRandom());
+                "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, false, null, null, new SecureRandom());
 
             keyRingGen.AddSubKey(elgKeyPair);
 
@@ -1904,12 +1904,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             PgpKeyPair rsaKeyPair2 = new PgpKeyPair(PublicKeyAlgorithmTag.RsaGeneral, rsaKp, DateTime.UtcNow);
 
             PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification,
-                rsaKeyPair1, "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, null, null, random);
+                rsaKeyPair1, "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, false, null, null, random);
             PgpSecretKeyRing secRing1 = keyRingGen.GenerateSecretKeyRing();
             PgpPublicKeyRing pubRing1 = keyRingGen.GeneratePublicKeyRing();
 
             keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification,
-                rsaKeyPair2, "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, null, null, random);
+                rsaKeyPair2, "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, false, null, null, random);
             PgpSecretKeyRing secRing2 = keyRingGen.GenerateSecretKeyRing();
             PgpPublicKeyRing pubRing2 = keyRingGen.GeneratePublicKeyRing();
 
diff --git a/crypto/test/src/openpgp/test/PgpUnicodeTest.cs b/crypto/test/src/openpgp/test/PgpUnicodeTest.cs
index ce1df8980..534e8a471 100644
--- a/crypto/test/src/openpgp/test/PgpUnicodeTest.cs
+++ b/crypto/test/src/openpgp/test/PgpUnicodeTest.cs
@@ -13,7 +13,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
     [TestFixture]
     public class PgpUnicodeTest
     {
-        private void DoTestKey(BigInteger keyId, string passphrase)
+        private void DoTestKey(BigInteger keyId, string passphrase, bool utf8)
         {
             PgpSecretKeyRingBundle secretKeyRing = LoadSecretKeyCollection("secring.gpg");
 
@@ -25,7 +25,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 
             try
             {
-                PgpPrivateKey privateKey = key.ExtractPrivateKey(passphrase.ToCharArray());
+                char[] pass = passphrase.ToCharArray();
+
+                PgpPrivateKey privateKey = utf8
+                    ?   key.ExtractPrivateKeyUtf8(pass)
+                    :   key.ExtractPrivateKey(pass);
 
                 Assert.IsTrue(privateKey.KeyId == keyId.LongValue);
             }
@@ -53,7 +57,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
  //             passwordFile.close();
  //             String passphrase = new String(password);            
 
-                DoTestKey(keyId, passphrase);
+                DoTestKey(keyId, passphrase, true);
 
                 // all fine!
 
@@ -75,7 +79,8 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 
                 string passphrase = "Admin123";
 
-                DoTestKey(keyId, passphrase);
+                DoTestKey(keyId, passphrase, false);
+                DoTestKey(keyId, passphrase, true);
 
                 // all fine!
             }
@@ -102,7 +107,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
                 string passphrase = reader.ReadLine();
                 passwordFile.Close();
 
-                DoTestKey(keyId, passphrase);
+                DoTestKey(keyId, passphrase, true);
 
                 // all fine!
             }