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));
        }
 public virtual void ValidateRound1PayloadReceived(JPakeRound1Payload round1PayloadReceived)
 {
     if (state >= STATE_ROUND_1_VALIDATED)
     {
         throw new InvalidOperationException("Validation already attempted for round 1 payload for " + participantId);
     }
     partnerParticipantId = round1PayloadReceived.ParticipantId;
     gx3 = round1PayloadReceived.Gx1;
     gx4 = round1PayloadReceived.Gx2;
     BigInteger[] knowledgeProofForX  = round1PayloadReceived.KnowledgeProofForX1;
     BigInteger[] knowledgeProofForX2 = round1PayloadReceived.KnowledgeProofForX2;
     JPakeUtilities.ValidateParticipantIdsDiffer(participantId, round1PayloadReceived.ParticipantId);
     JPakeUtilities.ValidateGx4(gx4);
     JPakeUtilities.ValidateZeroKnowledgeProof(p, q, g, gx3, knowledgeProofForX, round1PayloadReceived.ParticipantId, digest);
     JPakeUtilities.ValidateZeroKnowledgeProof(p, q, g, gx4, knowledgeProofForX2, round1PayloadReceived.ParticipantId, digest);
     state = STATE_ROUND_1_VALIDATED;
 }
        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 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);
        }