public virtual void ValidateRound3PayloadReceived(JPakeRound3Payload round3PayloadReceived, BigInteger keyingMaterial)
 {
     if (state >= STATE_ROUND_3_VALIDATED)
     {
         throw new InvalidOperationException("Validation already attempted for round 3 payload for " + participantId);
     }
     if (state < STATE_KEY_CALCULATED)
     {
         throw new InvalidOperationException("Keying material must be calculated prior to validating round 3 payload for " + participantId);
     }
     JPakeUtilities.ValidateParticipantIdsDiffer(participantId, round3PayloadReceived.ParticipantId);
     JPakeUtilities.ValidateParticipantIdsEqual(partnerParticipantId, round3PayloadReceived.ParticipantId);
     JPakeUtilities.ValidateMacTag(participantId, partnerParticipantId, gx1, gx2, gx3, gx4, keyingMaterial, digest, round3PayloadReceived.MacTag);
     gx1   = null;
     gx2   = null;
     gx3   = null;
     gx4   = null;
     state = STATE_ROUND_3_VALIDATED;
 }
        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);
        }