public JPakePrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g, bool skipChecks) { JPakeUtilities.ValidateNotNull(p, "p"); JPakeUtilities.ValidateNotNull(q, "q"); JPakeUtilities.ValidateNotNull(g, "g"); if (!skipChecks) { if (!p.Subtract(JPakeUtilities.One).Mod(q).Equals(JPakeUtilities.Zero)) { throw new ArgumentException("p-1 must be evenly divisible by q"); } if (g.CompareTo(BigInteger.Two) == -1 || g.CompareTo(p.Subtract(JPakeUtilities.One)) == 1) { throw new ArgumentException("g must be in [2, p-1]"); } if (!g.ModPow(q, p).Equals(JPakeUtilities.One)) { throw new ArgumentException("g^q mod p must equal 1"); } if (!p.IsProbablePrime(20)) { throw new ArgumentException("p must be prime"); } if (!q.IsProbablePrime(20)) { throw new ArgumentException("q must be prime"); } } this.p = p; this.q = q; this.g = g; }
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 JPakeRound2Payload(string participantId, BigInteger a, BigInteger[] knowledgeProofForX2s) { JPakeUtilities.ValidateNotNull(participantId, "participantId"); JPakeUtilities.ValidateNotNull(a, "a"); JPakeUtilities.ValidateNotNull(knowledgeProofForX2s, "knowledgeProofForX2s"); this.participantId = participantId; this.a = a; this.knowledgeProofForX2s = new BigInteger[knowledgeProofForX2s.Length]; knowledgeProofForX2s.CopyTo(this.knowledgeProofForX2s, 0); }
public JPakeRound1Payload(string participantId, BigInteger gx1, BigInteger gx2, BigInteger[] knowledgeProofForX1, BigInteger[] knowledgeProofForX2) { JPakeUtilities.ValidateNotNull(participantId, "participantId"); JPakeUtilities.ValidateNotNull(gx1, "gx1"); JPakeUtilities.ValidateNotNull(gx2, "gx2"); JPakeUtilities.ValidateNotNull(knowledgeProofForX1, "knowledgeProofForX1"); JPakeUtilities.ValidateNotNull(knowledgeProofForX2, "knowledgeProofForX2"); this.participantId = participantId; this.gx1 = gx1; this.gx2 = gx2; this.knowledgeProofForX1 = new BigInteger[knowledgeProofForX1.Length]; Array.Copy(knowledgeProofForX1, this.knowledgeProofForX1, knowledgeProofForX1.Length); this.knowledgeProofForX2 = new BigInteger[knowledgeProofForX2.Length]; Array.Copy(knowledgeProofForX2, this.knowledgeProofForX2, knowledgeProofForX2.Length); }
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 virtual JPakeRound1Payload CreateRound1PayloadToSend() { if (state >= STATE_ROUND_1_CREATED) { throw new InvalidOperationException("Round 1 payload already created for " + participantId); } x1 = JPakeUtilities.GenerateX1(q, random); x2 = JPakeUtilities.GenerateX2(q, random); gx1 = JPakeUtilities.CalculateGx(p, g, x1); gx2 = JPakeUtilities.CalculateGx(p, g, x2); BigInteger[] knowledgeProofForX = JPakeUtilities.CalculateZeroKnowledgeProof(p, q, g, gx1, x1, participantId, digest, random); BigInteger[] knowledgeProofForX2 = JPakeUtilities.CalculateZeroKnowledgeProof(p, q, g, gx2, x2, participantId, digest, random); state = STATE_ROUND_1_CREATED; return(new JPakeRound1Payload(participantId, gx1, gx2, knowledgeProofForX, knowledgeProofForX2)); }
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 TestValidateNotNull() { JPakeUtilities.ValidateNotNull("a", "description"); try { JPakeUtilities.ValidateNotNull(null, "description"); Fail("failed to throw exception on null"); } catch (ArgumentNullException) { // expected } }
public virtual JPakeRound3Payload CreateRound3PayloadToSend(BigInteger keyingMaterial) { if (state >= STATE_ROUND_3_CREATED) { throw new InvalidOperationException("Round 3 payload already created for " + participantId); } if (state < STATE_KEY_CALCULATED) { throw new InvalidOperationException("Keying material must be calculated prior to creating round 3 payload for " + participantId); } BigInteger magTag = JPakeUtilities.CalculateMacTag(participantId, partnerParticipantId, gx1, gx2, gx3, gx4, keyingMaterial, digest); state = STATE_ROUND_3_CREATED; return(new JPakeRound3Payload(participantId, magTag)); }
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 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 JPakeRound2Payload CreateRound2PayloadToSend() { if (state >= STATE_ROUND_2_CREATED) { throw new InvalidOperationException("Round 2 payload already created for " + participantId); } if (state < STATE_ROUND_1_VALIDATED) { throw new InvalidOperationException("Round 1 payload must be validated prior to creating round 2 payload for " + participantId); } BigInteger gA = JPakeUtilities.CalculateGA(p, gx1, gx3, gx4); BigInteger s = JPakeUtilities.CalculateS(password); BigInteger bigInteger = JPakeUtilities.CalculateX2s(q, x2, s); BigInteger bigInteger2 = JPakeUtilities.CalculateA(p, q, gA, bigInteger); BigInteger[] knowledgeProofForX2s = JPakeUtilities.CalculateZeroKnowledgeProof(p, q, gA, bigInteger2, bigInteger, participantId, digest, random); state = STATE_ROUND_2_CREATED; return(new JPakeRound2Payload(participantId, bigInteger2, knowledgeProofForX2s)); }
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 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 JPakeParticipant(string participantId, char[] password, JPakePrimeOrderGroup group, IDigest digest, SecureRandom random) { JPakeUtilities.ValidateNotNull(participantId, "participantId"); JPakeUtilities.ValidateNotNull(password, "password"); JPakeUtilities.ValidateNotNull(group, "p"); JPakeUtilities.ValidateNotNull(digest, "digest"); JPakeUtilities.ValidateNotNull(random, "random"); if (password.Length == 0) { throw new ArgumentException("Password must not be empty."); } this.participantId = participantId; this.password = new char[password.Length]; Array.Copy(password, this.password, password.Length); p = group.P; q = group.Q; g = group.G; this.digest = digest; this.random = random; state = STATE_INITIALIZED; }
public virtual BigInteger CalculateKeyingMaterial() { if (state >= STATE_KEY_CALCULATED) { throw new InvalidOperationException("Key already calculated for " + participantId); } if (state < STATE_ROUND_2_VALIDATED) { throw new InvalidOperationException("Round 2 payload must be validated prior to creating key for " + participantId); } BigInteger s = JPakeUtilities.CalculateS(password); Array.Clear(password, 0, password.Length); password = null; BigInteger result = JPakeUtilities.CalculateKeyingMaterial(p, q, gx4, x2, s, b); x1 = null; x2 = null; b = null; state = STATE_KEY_CALCULATED; return(result); }
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 } }