From 5ff7adcebfd2cd6124a22a179763219a7f235264 Mon Sep 17 00:00:00 2001 From: str4d <str4d@mail.i2p> Date: Wed, 16 Mar 2016 08:35:23 +0000 Subject: [PATCH] Test BQP implementation --- briar-tests/build.gradle | 4 + .../KeyAgreementProtocolTest.java | 394 ++++++++++++++++++ 2 files changed, 398 insertions(+) create mode 100644 briar-tests/src/org/briarproject/keyagreement/KeyAgreementProtocolTest.java diff --git a/briar-tests/build.gradle b/briar-tests/build.gradle index c5ae112372..b3c2af66e1 100644 --- a/briar-tests/build.gradle +++ b/briar-tests/build.gradle @@ -15,6 +15,8 @@ dependencies { compile project(':briar-desktop') compile "junit:junit:4.12" compile "org.jmock:jmock:2.8.1" + compile "org.jmock:jmock-junit4:2.8.1" + compile "org.jmock:jmock-legacy:2.8.1" compile "org.hamcrest:hamcrest-library:1.3" compile "org.hamcrest:hamcrest-core:1.3" } @@ -23,6 +25,8 @@ dependencyVerification { verify = [ 'junit:junit:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a', 'org.jmock:jmock:75d4bdaf636879f0215830c5e6ab99407069a625eaffde5d57b32d887b75dc14', + 'org.jmock:jmock-junit4:81e3fff46ed56738a6f3f5147525d1d85cda591ce5df007cc193e735cee31113', + 'org.jmock:jmock-legacy:19c76059eb254775ba884fc8039bc5c7d1700dc68cc55ad3be5b405a2a8a1819', 'org.hamcrest:hamcrest-library:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c', 'org.hamcrest:hamcrest-core:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9', ] diff --git a/briar-tests/src/org/briarproject/keyagreement/KeyAgreementProtocolTest.java b/briar-tests/src/org/briarproject/keyagreement/KeyAgreementProtocolTest.java new file mode 100644 index 0000000000..e404c547f4 --- /dev/null +++ b/briar-tests/src/org/briarproject/keyagreement/KeyAgreementProtocolTest.java @@ -0,0 +1,394 @@ +package org.briarproject.keyagreement; + +import org.briarproject.BriarTestCase; +import org.briarproject.TestUtils; +import org.briarproject.api.crypto.CryptoComponent; +import org.briarproject.api.crypto.KeyPair; +import org.briarproject.api.crypto.PublicKey; +import org.briarproject.api.crypto.SecretKey; +import org.briarproject.api.keyagreement.Payload; +import org.briarproject.api.keyagreement.PayloadEncoder; +import org.briarproject.util.StringUtils; +import org.jmock.Expectations; +import org.jmock.auto.Mock; +import org.jmock.integration.junit4.JUnitRuleMockery; +import org.jmock.lib.legacy.ClassImposteriser; +import org.junit.Rule; +import org.junit.Test; + +import static org.briarproject.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +public class KeyAgreementProtocolTest extends BriarTestCase { + + @Rule + public JUnitRuleMockery context = new JUnitRuleMockery() {{ + // So we can mock concrete classes like KeyAgreementTransport + setImposteriser(ClassImposteriser.INSTANCE); + }}; + + private static final byte[] ALICE_PUBKEY = TestUtils.getRandomBytes(32); + private static final byte[] ALICE_COMMIT = + TestUtils.getRandomBytes(COMMIT_LENGTH); + private static final byte[] ALICE_PAYLOAD = + TestUtils.getRandomBytes(COMMIT_LENGTH + 8); + + private static final byte[] BOB_PUBKEY = TestUtils.getRandomBytes(32); + private static final byte[] BOB_COMMIT = + TestUtils.getRandomBytes(COMMIT_LENGTH); + private static final byte[] BOB_PAYLOAD = + TestUtils.getRandomBytes(COMMIT_LENGTH + 19); + + private static final byte[] ALICE_CONFIRM = + TestUtils.getRandomBytes(SecretKey.LENGTH); + private static final byte[] BOB_CONFIRM = + TestUtils.getRandomBytes(SecretKey.LENGTH); + + private static final byte[] BAD_PUBKEY = TestUtils.getRandomBytes(32); + private static final byte[] BAD_COMMIT = + TestUtils.getRandomBytes(COMMIT_LENGTH); + private static final byte[] BAD_CONFIRM = + TestUtils.getRandomBytes(SecretKey.LENGTH); + + @Mock + KeyAgreementProtocol.Callbacks callbacks; + @Mock + CryptoComponent crypto; + @Mock + PayloadEncoder payloadEncoder; + @Mock + KeyAgreementTransport transport; + @Mock + PublicKey ourPubKey; + + @Test + public void testAliceProtocol() throws Exception { + // set up + final Payload theirPayload = new Payload(BOB_COMMIT, null); + final Payload ourPayload = new Payload(ALICE_COMMIT, null); + final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); + final SecretKey sharedSecret = TestUtils.createSecretKey(); + final SecretKey masterSecret = TestUtils.createSecretKey(); + + KeyAgreementProtocol protocol = + new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, + transport, theirPayload, ourPayload, ourKeyPair, true); + + // expectations + context.checking(new Expectations() {{ + // Helpers + allowing(payloadEncoder).encode(ourPayload); + will(returnValue(ALICE_PAYLOAD)); + allowing(payloadEncoder).encode(theirPayload); + will(returnValue(BOB_PAYLOAD)); + allowing(ourPubKey).getEncoded(); + will(returnValue(ALICE_PUBKEY)); + + // Alice sends her public key + oneOf(transport).sendKey(ALICE_PUBKEY); + + // Alice receives Bob's public key + oneOf(callbacks).connectionWaiting(); + oneOf(transport).receiveKey(); + will(returnValue(BOB_PUBKEY)); + oneOf(callbacks).initialPacketReceived(); + + // Alice verifies Bob's public key + oneOf(crypto).deriveKeyCommitment(BOB_PUBKEY); + will(returnValue(BOB_COMMIT)); + + // Alice computes shared secret + oneOf(crypto).deriveSharedSecret(BOB_PUBKEY, ourKeyPair, true); + will(returnValue(sharedSecret)); + + // Alice sends her confirmation record + oneOf(crypto).deriveConfirmationRecord(sharedSecret, BOB_PAYLOAD, + ALICE_PAYLOAD, BOB_PUBKEY, ourKeyPair, true, true); + will(returnValue(ALICE_CONFIRM)); + oneOf(transport).sendConfirm(ALICE_CONFIRM); + + // Alice receives Bob's confirmation record + oneOf(transport).receiveConfirm(); + will(returnValue(BOB_CONFIRM)); + + // Alice verifies Bob's confirmation record + oneOf(crypto).deriveConfirmationRecord(sharedSecret, BOB_PAYLOAD, + ALICE_PAYLOAD, BOB_PUBKEY, ourKeyPair, true, false); + will(returnValue(BOB_CONFIRM)); + + // Alice computes master secret + oneOf(crypto).deriveMasterSecret(sharedSecret); + will(returnValue(masterSecret)); + }}); + + // execute + assertThat(masterSecret, is(equalTo(protocol.perform()))); + } + + @Test + public void testBobProtocol() throws Exception { + // set up + final Payload theirPayload = new Payload(ALICE_COMMIT, null); + final Payload ourPayload = new Payload(BOB_COMMIT, null); + final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); + final SecretKey sharedSecret = TestUtils.createSecretKey(); + final SecretKey masterSecret = TestUtils.createSecretKey(); + + KeyAgreementProtocol protocol = + new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, + transport, theirPayload, ourPayload, ourKeyPair, false); + + // expectations + context.checking(new Expectations() {{ + // Helpers + allowing(payloadEncoder).encode(ourPayload); + will(returnValue(BOB_PAYLOAD)); + allowing(payloadEncoder).encode(theirPayload); + will(returnValue(ALICE_PAYLOAD)); + allowing(ourPubKey).getEncoded(); + will(returnValue(BOB_PUBKEY)); + + // Bob receives Alice's public key + oneOf(transport).receiveKey(); + will(returnValue(ALICE_PUBKEY)); + oneOf(callbacks).initialPacketReceived(); + + // Bob verifies Alice's public key + oneOf(crypto).deriveKeyCommitment(ALICE_PUBKEY); + will(returnValue(ALICE_COMMIT)); + + // Bob sends his public key + oneOf(transport).sendKey(BOB_PUBKEY); + + // Bob computes shared secret + oneOf(crypto).deriveSharedSecret(ALICE_PUBKEY, ourKeyPair, false); + will(returnValue(sharedSecret)); + + // Bob receives Alices's confirmation record + oneOf(transport).receiveConfirm(); + will(returnValue(ALICE_CONFIRM)); + + // Bob verifies Alice's confirmation record + oneOf(crypto).deriveConfirmationRecord(sharedSecret, ALICE_PAYLOAD, + BOB_PAYLOAD, ALICE_PUBKEY, ourKeyPair, false, true); + will(returnValue(ALICE_CONFIRM)); + + // Bob sends his confirmation record + oneOf(crypto).deriveConfirmationRecord(sharedSecret, ALICE_PAYLOAD, + BOB_PAYLOAD, ALICE_PUBKEY, ourKeyPair, false, false); + will(returnValue(BOB_CONFIRM)); + oneOf(transport).sendConfirm(BOB_CONFIRM); + + // Bob computes master secret + oneOf(crypto).deriveMasterSecret(sharedSecret); + will(returnValue(masterSecret)); + }}); + + // execute + assertThat(masterSecret, is(equalTo(protocol.perform()))); + } + + @Test(expected = AbortException.class) + public void testAliceProtocolAbortOnBadKey() throws Exception { + // set up + final Payload theirPayload = new Payload(BOB_COMMIT, null); + final Payload ourPayload = new Payload(ALICE_COMMIT, null); + final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); + + KeyAgreementProtocol protocol = + new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, + transport, theirPayload, ourPayload, ourKeyPair, true); + + // expectations + context.checking(new Expectations() {{ + // Helpers + allowing(ourPubKey).getEncoded(); + will(returnValue(ALICE_PUBKEY)); + + // Alice sends her public key + oneOf(transport).sendKey(ALICE_PUBKEY); + + // Alice receives a bad public key + oneOf(callbacks).connectionWaiting(); + oneOf(transport).receiveKey(); + will(returnValue(BAD_PUBKEY)); + oneOf(callbacks).initialPacketReceived(); + + // Alice verifies Bob's public key + oneOf(crypto).deriveKeyCommitment(BAD_PUBKEY); + will(returnValue(BAD_COMMIT)); + + // Alice aborts + oneOf(transport).sendAbort(false); + + // Alice never computes shared secret + never(crypto).deriveSharedSecret(BAD_PUBKEY, ourKeyPair, true); + }}); + + // execute + protocol.perform(); + } + + @Test(expected = AbortException.class) + public void testBobProtocolAbortOnBadKey() throws Exception { + // set up + final Payload theirPayload = new Payload(ALICE_COMMIT, null); + final Payload ourPayload = new Payload(BOB_COMMIT, null); + final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); + + KeyAgreementProtocol protocol = + new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, + transport, theirPayload, ourPayload, ourKeyPair, false); + + // expectations + context.checking(new Expectations() {{ + // Helpers + allowing(ourPubKey).getEncoded(); + will(returnValue(BOB_PUBKEY)); + + // Bob receives a bad public key + oneOf(transport).receiveKey(); + will(returnValue(BAD_PUBKEY)); + oneOf(callbacks).initialPacketReceived(); + + // Bob verifies Alice's public key + oneOf(crypto).deriveKeyCommitment(BAD_PUBKEY); + will(returnValue(BAD_COMMIT)); + + // Bob aborts + oneOf(transport).sendAbort(false); + + // Bob never sends his public key + never(transport).sendKey(BOB_PUBKEY); + }}); + + // execute + protocol.perform(); + } + + @Test(expected = AbortException.class) + public void testAliceProtocolAbortOnBadConfirm() throws Exception { + // set up + final Payload theirPayload = new Payload(BOB_COMMIT, null); + final Payload ourPayload = new Payload(ALICE_COMMIT, null); + final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); + final SecretKey sharedSecret = TestUtils.createSecretKey(); + + KeyAgreementProtocol protocol = + new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, + transport, theirPayload, ourPayload, ourKeyPair, true); + + // expectations + context.checking(new Expectations() {{ + // Helpers + allowing(payloadEncoder).encode(ourPayload); + will(returnValue(ALICE_PAYLOAD)); + allowing(payloadEncoder).encode(theirPayload); + will(returnValue(BOB_PAYLOAD)); + allowing(ourPubKey).getEncoded(); + will(returnValue(ALICE_PUBKEY)); + + // Alice sends her public key + oneOf(transport).sendKey(ALICE_PUBKEY); + + // Alice receives Bob's public key + oneOf(callbacks).connectionWaiting(); + oneOf(transport).receiveKey(); + will(returnValue(BOB_PUBKEY)); + oneOf(callbacks).initialPacketReceived(); + + // Alice verifies Bob's public key + oneOf(crypto).deriveKeyCommitment(BOB_PUBKEY); + will(returnValue(BOB_COMMIT)); + + // Alice computes shared secret + oneOf(crypto).deriveSharedSecret(BOB_PUBKEY, ourKeyPair, true); + will(returnValue(sharedSecret)); + + // Alice sends her confirmation record + oneOf(crypto).deriveConfirmationRecord(sharedSecret, BOB_PAYLOAD, + ALICE_PAYLOAD, BOB_PUBKEY, ourKeyPair, true, true); + will(returnValue(ALICE_CONFIRM)); + oneOf(transport).sendConfirm(ALICE_CONFIRM); + + // Alice receives a bad confirmation record + oneOf(transport).receiveConfirm(); + will(returnValue(BAD_CONFIRM)); + + // Alice verifies Bob's confirmation record + oneOf(crypto).deriveConfirmationRecord(sharedSecret, BOB_PAYLOAD, + ALICE_PAYLOAD, BOB_PUBKEY, ourKeyPair, true, false); + will(returnValue(BOB_CONFIRM)); + + // Alice aborts + oneOf(transport).sendAbort(false); + + // Alice never computes master secret + never(crypto).deriveMasterSecret(sharedSecret); + }}); + + // execute + protocol.perform(); + } + + @Test(expected = AbortException.class) + public void testBobProtocolAbortOnBadConfirm() throws Exception { + // set up + final Payload theirPayload = new Payload(ALICE_COMMIT, null); + final Payload ourPayload = new Payload(BOB_COMMIT, null); + final KeyPair ourKeyPair = new KeyPair(ourPubKey, null); + final SecretKey sharedSecret = TestUtils.createSecretKey(); + + KeyAgreementProtocol protocol = + new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, + transport, theirPayload, ourPayload, ourKeyPair, false); + + // expectations + context.checking(new Expectations() {{ + // Helpers + allowing(payloadEncoder).encode(ourPayload); + will(returnValue(BOB_PAYLOAD)); + allowing(payloadEncoder).encode(theirPayload); + will(returnValue(ALICE_PAYLOAD)); + allowing(ourPubKey).getEncoded(); + will(returnValue(BOB_PUBKEY)); + + // Bob receives Alice's public key + oneOf(transport).receiveKey(); + will(returnValue(ALICE_PUBKEY)); + oneOf(callbacks).initialPacketReceived(); + + // Bob verifies Alice's public key + oneOf(crypto).deriveKeyCommitment(ALICE_PUBKEY); + will(returnValue(ALICE_COMMIT)); + + // Bob sends his public key + oneOf(transport).sendKey(BOB_PUBKEY); + + // Bob computes shared secret + oneOf(crypto).deriveSharedSecret(ALICE_PUBKEY, ourKeyPair, false); + will(returnValue(sharedSecret)); + + // Bob receives a bad confirmation record + oneOf(transport).receiveConfirm(); + will(returnValue(BAD_CONFIRM)); + + // Bob verifies Alice's confirmation record + oneOf(crypto).deriveConfirmationRecord(sharedSecret, ALICE_PAYLOAD, + BOB_PAYLOAD, ALICE_PUBKEY, ourKeyPair, false, true); + will(returnValue(ALICE_CONFIRM)); + + // Bob aborts + oneOf(transport).sendAbort(false); + + // Bob never sends his confirmation record + never(crypto).deriveConfirmationRecord(sharedSecret, ALICE_PAYLOAD, + BOB_PAYLOAD, ALICE_PUBKEY, ourKeyPair, false, false); + }}); + + // execute + protocol.perform(); + } +} \ No newline at end of file -- GitLab