diff options
Diffstat (limited to 'libraries/spongycastle/core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEParticipantTest.java')
-rw-r--r-- | libraries/spongycastle/core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEParticipantTest.java | 561 |
1 files changed, 561 insertions, 0 deletions
diff --git a/libraries/spongycastle/core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEParticipantTest.java b/libraries/spongycastle/core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEParticipantTest.java new file mode 100644 index 000000000..223057fc1 --- /dev/null +++ b/libraries/spongycastle/core/src/test/java/org/spongycastle/crypto/agreement/test/JPAKEParticipantTest.java @@ -0,0 +1,561 @@ +package org.spongycastle.crypto.agreement.test; + +import java.math.BigInteger; +import java.security.SecureRandom; + +import junit.framework.TestCase; +import org.spongycastle.crypto.CryptoException; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.agreement.jpake.JPAKEParticipant; +import org.spongycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup; +import org.spongycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroups; +import org.spongycastle.crypto.agreement.jpake.JPAKERound1Payload; +import org.spongycastle.crypto.agreement.jpake.JPAKERound2Payload; +import org.spongycastle.crypto.agreement.jpake.JPAKERound3Payload; +import org.spongycastle.crypto.agreement.jpake.JPAKEUtil; +import org.spongycastle.crypto.digests.SHA256Digest; + +public class JPAKEParticipantTest + extends TestCase +{ + + public void testConstruction() + throws CryptoException + { + JPAKEPrimeOrderGroup group = JPAKEPrimeOrderGroups.SUN_JCE_1024; + SecureRandom random = new SecureRandom(); + Digest 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(); + } + catch (NullPointerException e) + { + // pass + } + + // null password + try + { + new JPAKEParticipant(participantId, null, group, digest, random); + fail(); + } + catch (NullPointerException e) + { + // pass + } + + // empty password + try + { + new JPAKEParticipant(participantId, "".toCharArray(), group, digest, random); + fail(); + } + catch (IllegalArgumentException e) + { + // pass + } + + // null group + try + { + new JPAKEParticipant(participantId, password, null, digest, random); + fail(); + } + catch (NullPointerException e) + { + // pass + } + + // null digest + try + { + new JPAKEParticipant(participantId, password, group, null, random); + fail(); + } + catch (NullPointerException e) + { + // pass + } + + // null random + try + { + new JPAKEParticipant(participantId, password, group, digest, null); + fail(); + } + catch (NullPointerException e) + { + // pass + } + } + + public void testSuccessfulExchange() + throws CryptoException + { + + 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); + + assertEquals(aliceKeyingMaterial, bobKeyingMaterial); + + } + + public void testIncorrectPassword() + throws CryptoException + { + + 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(); + } + catch (CryptoException e) + { + // pass + } + + try + { + bob.validateRound3PayloadReceived(aliceRound3Payload, bobKeyingMaterial); + fail(); + } + catch (CryptoException e) + { + // pass + } + + } + + /** + * Tests that {@link JPAKEParticipant} throws appropriate {@link IllegalStateException}s + * when the methods are called in the wrong order. + */ + public void testStateValidation() + throws CryptoException + { + + JPAKEParticipant alice = createAlice(); + JPAKEParticipant bob = createBob(); + + // We're testing alice here. Bob is just used for help. + + // START ROUND 1 CHECKS + + assertEquals(JPAKEParticipant.STATE_INITIALIZED, alice.getState()); + + // create round 2 before round 1 + try + { + alice.createRound2PayloadToSend(); + fail(); + } + catch (IllegalStateException e) + { + // pass + } + + JPAKERound1Payload aliceRound1Payload = alice.createRound1PayloadToSend(); + + assertEquals(JPAKEParticipant.STATE_ROUND_1_CREATED, alice.getState()); + + // create round 1 payload twice + try + { + alice.createRound1PayloadToSend(); + fail(); + } + catch (IllegalStateException e) + { + // pass + } + + // create round 2 before validating round 1 + try + { + alice.createRound2PayloadToSend(); + fail(); + } + catch (IllegalStateException e) + { + // pass + } + + // validate round 2 before validating round 1 + try + { + alice.validateRound2PayloadReceived(null); + fail(); + } + catch (IllegalStateException e) + { + // pass + } + + JPAKERound1Payload bobRound1Payload = bob.createRound1PayloadToSend(); + + alice.validateRound1PayloadReceived(bobRound1Payload); + + assertEquals(JPAKEParticipant.STATE_ROUND_1_VALIDATED, alice.getState()); + + // validate round 1 payload twice + try + { + alice.validateRound1PayloadReceived(bobRound1Payload); + fail(); + } + catch (IllegalStateException e) + { + // pass + } + + bob.validateRound1PayloadReceived(aliceRound1Payload); + + // START ROUND 2 CHECKS + + JPAKERound2Payload aliceRound2Payload = alice.createRound2PayloadToSend(); + + assertEquals(JPAKEParticipant.STATE_ROUND_2_CREATED, alice.getState()); + + // create round 2 payload twice + try + { + alice.createRound2PayloadToSend(); + fail(); + } + catch (IllegalStateException e) + { + // pass + } + + // create key before validating round 2 + try + { + alice.calculateKeyingMaterial(); + fail(); + } + catch (IllegalStateException e) + { + // pass + } + + // validate round 3 before validating round 2 + try + { + alice.validateRound3PayloadReceived(null, null); + fail(); + } + catch (IllegalStateException e) + { + // pass + } + + JPAKERound2Payload bobRound2Payload = bob.createRound2PayloadToSend(); + + alice.validateRound2PayloadReceived(bobRound2Payload); + + assertEquals(JPAKEParticipant.STATE_ROUND_2_VALIDATED, alice.getState()); + + // validate round 2 payload twice + try + { + alice.validateRound2PayloadReceived(bobRound2Payload); + fail(); + } + catch (IllegalStateException e) + { + // pass + } + + bob.validateRound2PayloadReceived(aliceRound2Payload); + + // create round 3 before calculating key + try + { + alice.createRound3PayloadToSend(BigInteger.ONE); + fail(); + } + catch (IllegalStateException e) + { + // pass + } + + // START KEY CALCULATION CHECKS + + BigInteger aliceKeyingMaterial = alice.calculateKeyingMaterial(); + + assertEquals(JPAKEParticipant.STATE_KEY_CALCULATED, alice.getState()); + + // calculate key twice + try + { + alice.calculateKeyingMaterial(); + fail(); + } + catch (IllegalStateException e) + { + // pass + } + + BigInteger bobKeyingMaterial = bob.calculateKeyingMaterial(); + + // START ROUND 3 CHECKS + + JPAKERound3Payload aliceRound3Payload = alice.createRound3PayloadToSend(aliceKeyingMaterial); + + assertEquals(JPAKEParticipant.STATE_ROUND_3_CREATED, alice.getState()); + + // create round 3 payload twice + try + { + alice.createRound3PayloadToSend(aliceKeyingMaterial); + fail(); + } + catch (IllegalStateException e) + { + // pass + } + + JPAKERound3Payload bobRound3Payload = bob.createRound3PayloadToSend(bobKeyingMaterial); + + alice.validateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial); + + assertEquals(JPAKEParticipant.STATE_ROUND_3_VALIDATED, alice.getState()); + + // validate round 3 payload twice + try + { + alice.validateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial); + fail(); + } + catch (IllegalStateException e) + { + // pass + } + + bob.validateRound3PayloadReceived(aliceRound3Payload, bobKeyingMaterial); + + + } + + /** + * Tests that {@link JPAKEParticipant#validateRound1PayloadReceived(JPAKERound1Payload)} + * calls the appropriate validate methods in {@link JPAKEUtil}. + * Note that {@link JPAKEUtilTest} tests the individual validate methods + * called by {@link JPAKEParticipant} more extensively. + */ + public void testValidateRound1PayloadReceived() + throws CryptoException + { + + // 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(); + } + catch (CryptoException e) + { + // pass + } + + // g^x4 == 1 + try + { + createAlice().validateRound1PayloadReceived(new JPAKERound1Payload( + bobRound1Payload.getParticipantId(), + bobRound1Payload.getGx1(), + BigInteger.ONE, + bobRound1Payload.getKnowledgeProofForX1(), + bobRound1Payload.getKnowledgeProofForX2())); + fail(); + } + catch (CryptoException e) + { + // pass + } + + // zero knowledge proof for x3 fails + try + { + JPAKERound1Payload bobRound1Payload2 = createBob().createRound1PayloadToSend(); + createAlice().validateRound1PayloadReceived(new JPAKERound1Payload( + bobRound1Payload.getParticipantId(), + bobRound1Payload.getGx1(), + bobRound1Payload.getGx2(), + bobRound1Payload2.getKnowledgeProofForX1(), + bobRound1Payload.getKnowledgeProofForX2())); + fail(); + } + catch (CryptoException e) + { + // pass + } + + // zero knowledge proof for x4 fails + try + { + JPAKERound1Payload bobRound1Payload2 = createBob().createRound1PayloadToSend(); + createAlice().validateRound1PayloadReceived(new JPAKERound1Payload( + bobRound1Payload.getParticipantId(), + bobRound1Payload.getGx1(), + bobRound1Payload.getGx2(), + bobRound1Payload.getKnowledgeProofForX1(), + bobRound1Payload2.getKnowledgeProofForX2())); + fail(); + } + catch (CryptoException e) + { + // pass + } + + } + + /** + * Tests that {@link JPAKEParticipant#validateRound2PayloadReceived(JPAKERound2Payload)} + * calls the appropriate validate methods in {@link JPAKEUtil}. + * Note that {@link JPAKEUtilTest} tests the individual validate methods + * called by {@link JPAKEParticipant} more extensively. + */ + public void testValidateRound2PayloadReceived() + throws CryptoException + { + + // We're testing alice here. Bob is just used for help. + + // should succeed + ExchangeAfterRound2Creation exchange1 = runExchangeUntilRound2Creation(createAlice(), createBob()); + exchange1.alice.validateRound2PayloadReceived(exchange1.bobRound2Payload); + + // alice verifies alice's payload + ExchangeAfterRound2Creation exchange2 = runExchangeUntilRound2Creation(createAlice(), createBob()); + try + { + exchange2.alice.validateRound2PayloadReceived(exchange2.aliceRound2Payload); + fail(); + } + catch (CryptoException e) + { + // pass + } + + // wrong z + ExchangeAfterRound2Creation exchange3 = runExchangeUntilRound2Creation(createAlice(), createBob()); + ExchangeAfterRound2Creation exchange4 = runExchangeUntilRound2Creation(createAlice(), createBob()); + try + { + exchange3.alice.validateRound2PayloadReceived(exchange4.bobRound2Payload); + fail(); + } + catch (CryptoException e) + { + // pass + } + + } + + private static 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) + throws CryptoException + { + 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); + } + +} |