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 virtual void ValidateRound2PayloadReceived(JPakeRound2Payload round2PayloadReceived)
    {
        if (state >= STATE_ROUND_2_VALIDATED)
        {
            throw new InvalidOperationException("Validation already attempted for round 2 payload for " + participantId);
        }
        if (state < STATE_ROUND_1_VALIDATED)
        {
            throw new InvalidOperationException("Round 1 payload must be validated prior to validation round 2 payload for " + participantId);
        }
        BigInteger ga = JPakeUtilities.CalculateGA(p, gx3, gx1, gx2);

        b = round2PayloadReceived.A;
        BigInteger[] knowledgeProofForX2s = round2PayloadReceived.KnowledgeProofForX2s;
        JPakeUtilities.ValidateParticipantIdsDiffer(participantId, round2PayloadReceived.ParticipantId);
        JPakeUtilities.ValidateParticipantIdsEqual(partnerParticipantId, round2PayloadReceived.ParticipantId);
        JPakeUtilities.ValidateGa(ga);
        JPakeUtilities.ValidateZeroKnowledgeProof(p, q, ga, b, knowledgeProofForX2s, round2PayloadReceived.ParticipantId, digest);
        state = STATE_ROUND_2_VALIDATED;
    }
        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
            }
        }