Factor out key agreement crypto from CryptoComponent.

This commit is contained in:
akwizgran
2017-11-28 10:20:11 +00:00
parent 1843aea2a7
commit cc87e6fd1f
14 changed files with 204 additions and 225 deletions

View File

@@ -36,22 +36,14 @@ public interface CryptoComponent {
* Derives a nonce from the given secret key that can be used for key
* binding.
*
* TODO: This just calls mac(), remove it
*
* @param label a namespaced label indicating the purpose of this nonce,
* to prevent it from being repurposed or colliding with a nonce derived
* for another purpose
*/
byte[] deriveKeyBindingNonce(String label, SecretKey k);
/**
* Derives a commitment to the provided public key.
* <p/>
* Used by the key exchange protocol.
*
* @param publicKey the public key
* @return the commitment to the provided public key.
*/
byte[] deriveKeyCommitment(PublicKey publicKey);
/**
* Derives a common shared secret from two public keys and one of the
* corresponding private keys.
@@ -67,25 +59,6 @@ public interface CryptoComponent {
SecretKey deriveSharedSecret(String label, PublicKey theirPublicKey,
KeyPair ourKeyPair, boolean alice) throws GeneralSecurityException;
/**
* Derives the content of a confirmation record.
* <p/>
* Used by the key exchange protocol.
*
* @param sharedSecret the common shared secret
* @param theirPayload the key exchange payload of the remote party
* @param ourPayload the key exchange payload of the local party
* @param theirPublicKey the ephemeral public key of the remote party
* @param ourKeyPair our ephemeral key pair of the local party
* @param alice true if the local party is Alice
* @param aliceRecord true if the confirmation record is for use by Alice
* @return the confirmation record
*/
byte[] deriveConfirmationRecord(SecretKey sharedSecret,
byte[] theirPayload, byte[] ourPayload,
PublicKey theirPublicKey, KeyPair ourKeyPair,
boolean alice, boolean aliceRecord);
/**
* Signs the given byte[] with the given ECDSA private key.
*

View File

@@ -0,0 +1,50 @@
package org.briarproject.bramble.api.crypto;
public interface KeyAgreementCrypto {
/**
* Hash label for public key commitment.
*/
String COMMIT_LABEL = "org.briarproject.bramble.keyagreement/COMMIT";
/**
* Key derivation label for confirmation record.
*/
String CONFIRMATION_KEY_LABEL =
"org.briarproject.bramble.keyagreement/CONFIRMATION_KEY";
/**
* MAC label for confirmation record.
*/
String CONFIRMATION_MAC_LABEL =
"org.briarproject.bramble.keyagreement/CONFIRMATION_MAC";
/**
* Derives a commitment to the provided public key.
* <p/>
* Used by the key exchange protocol.
*
* @param publicKey the public key
* @return the commitment to the provided public key.
*/
byte[] deriveKeyCommitment(PublicKey publicKey);
/**
* Derives the content of a confirmation record.
* <p/>
* Used by the key exchange protocol.
*
* @param sharedSecret the common shared secret
* @param theirPayload the key exchange payload of the remote party
* @param ourPayload the key exchange payload of the local party
* @param theirPublicKey the ephemeral public key of the remote party
* @param ourKeyPair our ephemeral key pair of the local party
* @param alice true if the local party is Alice
* @param aliceRecord true if the confirmation record is for use by Alice
* @return the confirmation record
*/
byte[] deriveConfirmationRecord(SecretKey sharedSecret,
byte[] theirPayload, byte[] ourPayload,
PublicKey theirPublicKey, KeyPair ourKeyPair,
boolean alice, boolean aliceRecord);
}

View File

@@ -1,15 +0,0 @@
package org.briarproject.bramble.api.keyagreement;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* Manages tasks for conducting key agreements with remote peers.
*/
@NotNullByDefault
public interface KeyAgreementTaskFactory {
/**
* Gets the current key agreement task.
*/
KeyAgreementTask createTask();
}

View File

@@ -39,7 +39,6 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
import static org.briarproject.bramble.crypto.EllipticCurveConstants.PARAMETERS;
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
@@ -56,16 +55,6 @@ class CryptoComponentImpl implements CryptoComponent {
private static final int PBKDF_TARGET_MILLIS = 500;
private static final int PBKDF_SAMPLES = 30;
// Hash label for BQP public key commitment derivation
private static final String COMMIT_LABEL =
"org.briarproject.bramble.keyagreement/COMMIT";
// KDF label for BQP confirmation key derivation
private static final String CONFIRMATION_KEY_LABEL =
"org.briarproject.bramble.keyagreement/CONFIRMATION_KEY";
// MAC label for BQP confirmation record
private static final String CONFIRMATION_MAC_LABEL =
"org.briarproject.bramble.keyagreement/CONFIRMATION_MAC";
private final SecureRandom secureRandom;
private final ECKeyPairGenerator agreementKeyPairGenerator;
private final ECKeyPairGenerator signatureKeyPairGenerator;
@@ -230,23 +219,13 @@ class CryptoComponentImpl implements CryptoComponent {
}
@Override
public SecretKey deriveKey(String label, SecretKey k,
byte[]... inputs) {
return new SecretKey(macKdf(label, k, inputs));
public SecretKey deriveKey(String label, SecretKey k, byte[]... inputs) {
return new SecretKey(mac(label, k, inputs));
}
@Override
public byte[] deriveKeyBindingNonce(String label, SecretKey k) {
return macKdf(label, k);
}
@Override
public byte[] deriveKeyCommitment(PublicKey publicKey) {
byte[] hash = hash(COMMIT_LABEL, publicKey.getEncoded());
// The output is the first COMMIT_LENGTH bytes of the hash
byte[] commitment = new byte[COMMIT_LENGTH];
System.arraycopy(hash, 0, commitment, 0, COMMIT_LENGTH);
return commitment;
return mac(label, k);
}
@Override
@@ -265,32 +244,6 @@ class CryptoComponentImpl implements CryptoComponent {
return new SecretKey(hash(label, raw, alicePub, bobPub));
}
@Override
public byte[] deriveConfirmationRecord(SecretKey sharedSecret,
byte[] theirPayload, byte[] ourPayload, PublicKey theirPublicKey,
KeyPair ourKeyPair, boolean alice, boolean aliceRecord) {
SecretKey ck = deriveKey(CONFIRMATION_KEY_LABEL, sharedSecret);
byte[] alicePayload, alicePub, bobPayload, bobPub;
if (alice) {
alicePayload = ourPayload;
alicePub = ourKeyPair.getPublic().getEncoded();
bobPayload = theirPayload;
bobPub = theirPublicKey.getEncoded();
} else {
alicePayload = theirPayload;
alicePub = theirPublicKey.getEncoded();
bobPayload = ourPayload;
bobPub = ourKeyPair.getPublic().getEncoded();
}
if (aliceRecord) {
return macKdf(CONFIRMATION_MAC_LABEL, ck, alicePayload, alicePub,
bobPayload, bobPub);
} else {
return macKdf(CONFIRMATION_MAC_LABEL, ck, bobPayload, bobPub,
alicePayload, alicePub);
}
}
@Override
public byte[] sign(String label, byte[] toSign, byte[] privateKey)
throws GeneralSecurityException {
@@ -464,15 +417,6 @@ class CryptoComponentImpl implements CryptoComponent {
return AsciiArmour.wrap(b, lineLength);
}
// Key derivation function based on a pseudo-random function - see
// NIST SP 800-108, section 5.1
private byte[] macKdf(String label, SecretKey k, byte[]... inputs) {
byte[] mac = mac(label, k, inputs);
// The output of the PRF must be usable as a key
if (mac.length != SecretKey.LENGTH) throw new IllegalStateException();
return mac;
}
// Password-based key derivation function - see PKCS#5 v2.1, section 5.2
private byte[] pbkdf2(String password, byte[] salt, int iterations) {
byte[] utf8 = StringUtils.toUtf8(password);

View File

@@ -3,6 +3,7 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.TimeLoggingExecutor;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.CryptoExecutor;
import org.briarproject.bramble.api.crypto.KeyAgreementCrypto;
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
import org.briarproject.bramble.api.crypto.StreamDecrypterFactory;
import org.briarproject.bramble.api.crypto.StreamEncrypterFactory;
@@ -95,6 +96,12 @@ public class CryptoModule {
cipherProvider);
}
@Provides
KeyAgreementCrypto provideKeyAgreementCrypto(
KeyAgreementCryptoImpl keyAgreementCrypto) {
return keyAgreementCrypto;
}
@Provides
@Singleton
@CryptoExecutor

View File

@@ -0,0 +1,56 @@
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyAgreementCrypto;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.crypto.SecretKey;
import javax.inject.Inject;
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
class KeyAgreementCryptoImpl implements KeyAgreementCrypto {
private final CryptoComponent crypto;
@Inject
KeyAgreementCryptoImpl(CryptoComponent crypto) {
this.crypto = crypto;
}
@Override
public byte[] deriveKeyCommitment(PublicKey publicKey) {
byte[] hash = crypto.hash(COMMIT_LABEL, publicKey.getEncoded());
// The output is the first COMMIT_LENGTH bytes of the hash
byte[] commitment = new byte[COMMIT_LENGTH];
System.arraycopy(hash, 0, commitment, 0, COMMIT_LENGTH);
return commitment;
}
@Override
public byte[] deriveConfirmationRecord(SecretKey sharedSecret,
byte[] theirPayload, byte[] ourPayload, PublicKey theirPublicKey,
KeyPair ourKeyPair, boolean alice, boolean aliceRecord) {
SecretKey ck = crypto.deriveKey(CONFIRMATION_KEY_LABEL, sharedSecret);
byte[] alicePayload, alicePub, bobPayload, bobPub;
if (alice) {
alicePayload = ourPayload;
alicePub = ourKeyPair.getPublic().getEncoded();
bobPayload = theirPayload;
bobPub = theirPublicKey.getEncoded();
} else {
alicePayload = theirPayload;
alicePub = theirPublicKey.getEncoded();
bobPayload = ourPayload;
bobPub = ourKeyPair.getPublic().getEncoded();
}
if (aliceRecord) {
return crypto.mac(CONFIRMATION_MAC_LABEL, ck, alicePayload,
alicePub, bobPayload, bobPub);
} else {
return crypto.mac(CONFIRMATION_MAC_LABEL, ck, bobPayload, bobPub,
alicePayload, alicePub);
}
}
}

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.keyagreement;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyAgreementCrypto;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
@@ -46,7 +46,7 @@ class KeyAgreementConnector {
private final Callbacks callbacks;
private final Clock clock;
private final CryptoComponent crypto;
private final KeyAgreementCrypto keyAgreementCrypto;
private final PluginManager pluginManager;
private final CompletionService<KeyAgreementConnection> connect;
@@ -58,11 +58,11 @@ class KeyAgreementConnector {
private volatile boolean alice = false;
KeyAgreementConnector(Callbacks callbacks, Clock clock,
CryptoComponent crypto, PluginManager pluginManager,
KeyAgreementCrypto keyAgreementCrypto, PluginManager pluginManager,
Executor ioExecutor) {
this.callbacks = callbacks;
this.clock = clock;
this.crypto = crypto;
this.keyAgreementCrypto = keyAgreementCrypto;
this.pluginManager = pluginManager;
connect = new ExecutorCompletionService<>(ioExecutor);
}
@@ -70,8 +70,8 @@ class KeyAgreementConnector {
public Payload listen(KeyPair localKeyPair) {
LOG.info("Starting BQP listeners");
// Derive commitment
byte[] commitment =
crypto.deriveKeyCommitment(localKeyPair.getPublic());
byte[] commitment = keyAgreementCrypto.deriveKeyCommitment(
localKeyPair.getPublic());
// Start all listeners and collect their descriptors
List<TransportDescriptor> descriptors = new ArrayList<>();
for (DuplexPlugin plugin : pluginManager.getKeyAgreementPlugins()) {

View File

@@ -1,19 +1,10 @@
package org.briarproject.bramble.keyagreement;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.data.BdfReaderFactory;
import org.briarproject.bramble.api.data.BdfWriterFactory;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.keyagreement.KeyAgreementTaskFactory;
import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
import org.briarproject.bramble.api.keyagreement.PayloadParser;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.plugin.PluginManager;
import org.briarproject.bramble.api.system.Clock;
import java.util.concurrent.Executor;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@@ -22,13 +13,9 @@ import dagger.Provides;
public class KeyAgreementModule {
@Provides
@Singleton
KeyAgreementTaskFactory provideKeyAgreementTaskFactory(Clock clock,
CryptoComponent crypto, EventBus eventBus,
@IoExecutor Executor ioExecutor, PayloadEncoder payloadEncoder,
PluginManager pluginManager) {
return new KeyAgreementTaskFactoryImpl(clock, crypto, eventBus,
ioExecutor, payloadEncoder, pluginManager);
KeyAgreementTask provideKeyAgreementTask(
KeyAgreementTaskImpl keyAgreementTask) {
return keyAgreementTask;
}
@Provides

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.keyagreement;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyAgreementCrypto;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.KeyParser;
import org.briarproject.bramble.api.crypto.PublicKey;
@@ -62,6 +63,7 @@ class KeyAgreementProtocol {
private final Callbacks callbacks;
private final CryptoComponent crypto;
private final KeyAgreementCrypto keyAgreementCrypto;
private final PayloadEncoder payloadEncoder;
private final KeyAgreementTransport transport;
private final Payload theirPayload, ourPayload;
@@ -69,11 +71,13 @@ class KeyAgreementProtocol {
private final boolean alice;
KeyAgreementProtocol(Callbacks callbacks, CryptoComponent crypto,
KeyAgreementCrypto keyAgreementCrypto,
PayloadEncoder payloadEncoder, KeyAgreementTransport transport,
Payload theirPayload, Payload ourPayload, KeyPair ourKeyPair,
boolean alice) {
this.callbacks = callbacks;
this.crypto = crypto;
this.keyAgreementCrypto = keyAgreementCrypto;
this.payloadEncoder = payloadEncoder;
this.transport = transport;
this.theirPayload = theirPayload;
@@ -126,7 +130,7 @@ class KeyAgreementProtocol {
KeyParser keyParser = crypto.getAgreementKeyParser();
try {
PublicKey publicKey = keyParser.parsePublicKey(publicKeyBytes);
byte[] expected = crypto.deriveKeyCommitment(publicKey);
byte[] expected = keyAgreementCrypto.deriveKeyCommitment(publicKey);
if (!Arrays.equals(expected, theirPayload.getCommitment()))
throw new AbortException();
return publicKey;
@@ -147,7 +151,7 @@ class KeyAgreementProtocol {
private void sendConfirm(SecretKey s, PublicKey theirPublicKey)
throws IOException {
byte[] confirm = crypto.deriveConfirmationRecord(s,
byte[] confirm = keyAgreementCrypto.deriveConfirmationRecord(s,
payloadEncoder.encode(theirPayload),
payloadEncoder.encode(ourPayload),
theirPublicKey, ourKeyPair,
@@ -158,7 +162,7 @@ class KeyAgreementProtocol {
private void receiveConfirm(SecretKey s, PublicKey theirPublicKey)
throws AbortException {
byte[] confirm = transport.receiveConfirm();
byte[] expected = crypto.deriveConfirmationRecord(s,
byte[] expected = keyAgreementCrypto.deriveConfirmationRecord(s,
payloadEncoder.encode(theirPayload),
payloadEncoder.encode(ourPayload),
theirPublicKey, ourKeyPair,

View File

@@ -1,46 +0,0 @@
package org.briarproject.bramble.keyagreement;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
import org.briarproject.bramble.api.keyagreement.KeyAgreementTaskFactory;
import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginManager;
import org.briarproject.bramble.api.system.Clock;
import java.util.concurrent.Executor;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
@Immutable
@NotNullByDefault
class KeyAgreementTaskFactoryImpl implements KeyAgreementTaskFactory {
private final Clock clock;
private final CryptoComponent crypto;
private final EventBus eventBus;
private final Executor ioExecutor;
private final PayloadEncoder payloadEncoder;
private final PluginManager pluginManager;
@Inject
KeyAgreementTaskFactoryImpl(Clock clock, CryptoComponent crypto,
EventBus eventBus, @IoExecutor Executor ioExecutor,
PayloadEncoder payloadEncoder, PluginManager pluginManager) {
this.clock = clock;
this.crypto = crypto;
this.eventBus = eventBus;
this.ioExecutor = ioExecutor;
this.payloadEncoder = payloadEncoder;
this.pluginManager = pluginManager;
}
@Override
public KeyAgreementTask createTask() {
return new KeyAgreementTaskImpl(clock, crypto, eventBus, payloadEncoder,
pluginManager, ioExecutor);
}
}

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.keyagreement;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyAgreementCrypto;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.event.EventBus;
@@ -14,6 +15,7 @@ import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFinishedEvent
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementListeningEvent;
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementStartedEvent;
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementWaitingEvent;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginManager;
@@ -23,6 +25,8 @@ import java.io.IOException;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
@MethodsNotNullByDefault
@@ -35,6 +39,7 @@ class KeyAgreementTaskImpl extends Thread implements
Logger.getLogger(KeyAgreementTaskImpl.class.getName());
private final CryptoComponent crypto;
private final KeyAgreementCrypto keyAgreementCrypto;
private final EventBus eventBus;
private final PayloadEncoder payloadEncoder;
private final KeyPair localKeyPair;
@@ -43,14 +48,17 @@ class KeyAgreementTaskImpl extends Thread implements
private Payload localPayload;
private Payload remotePayload;
@Inject
KeyAgreementTaskImpl(Clock clock, CryptoComponent crypto,
EventBus eventBus, PayloadEncoder payloadEncoder,
PluginManager pluginManager, Executor ioExecutor) {
KeyAgreementCrypto keyAgreementCrypto, EventBus eventBus,
PayloadEncoder payloadEncoder, PluginManager pluginManager,
@IoExecutor Executor ioExecutor) {
this.crypto = crypto;
this.keyAgreementCrypto = keyAgreementCrypto;
this.eventBus = eventBus;
this.payloadEncoder = payloadEncoder;
localKeyPair = crypto.generateAgreementKeyPair();
connector = new KeyAgreementConnector(this, clock, crypto,
connector = new KeyAgreementConnector(this, clock, keyAgreementCrypto,
pluginManager, ioExecutor);
}
@@ -100,8 +108,8 @@ class KeyAgreementTaskImpl extends Thread implements
// Run BQP protocol over the connection
LOG.info("Starting BQP protocol");
KeyAgreementProtocol protocol = new KeyAgreementProtocol(this, crypto,
payloadEncoder, transport, remotePayload, localPayload,
localKeyPair, alice);
keyAgreementCrypto, payloadEncoder, transport, remotePayload,
localPayload, localKeyPair, alice);
try {
SecretKey master = protocol.perform();
KeyAgreementResult result =

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.keyagreement;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyAgreementCrypto;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.KeyParser;
import org.briarproject.bramble.api.crypto.PublicKey;
@@ -55,6 +56,8 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Mock
CryptoComponent crypto;
@Mock
KeyAgreementCrypto keyAgreementCrypto;
@Mock
KeyParser keyParser;
@Mock
PayloadEncoder payloadEncoder;
@@ -72,9 +75,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
SecretKey sharedSecret = getSecretKey();
SecretKey masterSecret = getSecretKey();
KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
transport, theirPayload, ourPayload, ourKeyPair, true);
KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks,
crypto, keyAgreementCrypto, payloadEncoder, transport,
theirPayload, ourPayload, ourKeyPair, true);
// expectations
context.checking(new Expectations() {{
@@ -100,7 +103,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(bobPubKey));
// Alice verifies Bob's public key
oneOf(crypto).deriveKeyCommitment(bobPubKey);
oneOf(keyAgreementCrypto).deriveKeyCommitment(bobPubKey);
will(returnValue(bobCommit));
// Alice computes shared secret
@@ -109,8 +112,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(sharedSecret));
// Alice sends her confirmation record
oneOf(crypto).deriveConfirmationRecord(sharedSecret, bobPayload,
alicePayload, bobPubKey, ourKeyPair, true, true);
oneOf(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
bobPayload, alicePayload, bobPubKey, ourKeyPair,
true, true);
will(returnValue(aliceConfirm));
oneOf(transport).sendConfirm(aliceConfirm);
@@ -119,8 +123,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(bobConfirm));
// Alice verifies Bob's confirmation record
oneOf(crypto).deriveConfirmationRecord(sharedSecret, bobPayload,
alicePayload, bobPubKey, ourKeyPair, true, false);
oneOf(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
bobPayload, alicePayload, bobPubKey, ourKeyPair,
true, false);
will(returnValue(bobConfirm));
// Alice computes master secret
@@ -141,9 +146,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
SecretKey sharedSecret = getSecretKey();
SecretKey masterSecret = getSecretKey();
KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
transport, theirPayload, ourPayload, ourKeyPair, false);
KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks,
crypto, keyAgreementCrypto, payloadEncoder, transport,
theirPayload, ourPayload, ourKeyPair, false);
// expectations
context.checking(new Expectations() {{
@@ -165,7 +170,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(alicePubKey));
// Bob verifies Alice's public key
oneOf(crypto).deriveKeyCommitment(alicePubKey);
oneOf(keyAgreementCrypto).deriveKeyCommitment(alicePubKey);
will(returnValue(aliceCommit));
// Bob sends his public key
@@ -181,13 +186,15 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(aliceConfirm));
// Bob verifies Alice's confirmation record
oneOf(crypto).deriveConfirmationRecord(sharedSecret, alicePayload,
bobPayload, alicePubKey, ourKeyPair, false, true);
oneOf(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
alicePayload, bobPayload, alicePubKey, ourKeyPair,
false, true);
will(returnValue(aliceConfirm));
// Bob sends his confirmation record
oneOf(crypto).deriveConfirmationRecord(sharedSecret, alicePayload,
bobPayload, alicePubKey, ourKeyPair, false, false);
oneOf(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
alicePayload, bobPayload, alicePubKey, ourKeyPair,
false, false);
will(returnValue(bobConfirm));
oneOf(transport).sendConfirm(bobConfirm);
@@ -207,9 +214,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
Payload ourPayload = new Payload(aliceCommit, null);
KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
transport, theirPayload, ourPayload, ourKeyPair, true);
KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks,
crypto, keyAgreementCrypto, payloadEncoder, transport,
theirPayload, ourPayload, ourKeyPair, true);
// expectations
context.checking(new Expectations() {{
@@ -231,7 +238,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(badPubKey));
// Alice verifies Bob's public key
oneOf(crypto).deriveKeyCommitment(badPubKey);
oneOf(keyAgreementCrypto).deriveKeyCommitment(badPubKey);
will(returnValue(badCommit));
// Alice aborts
@@ -253,9 +260,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
Payload ourPayload = new Payload(bobCommit, null);
KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
transport, theirPayload, ourPayload, ourKeyPair, false);
KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks,
crypto, keyAgreementCrypto, payloadEncoder, transport,
theirPayload, ourPayload, ourKeyPair, false);
// expectations
context.checking(new Expectations() {{
@@ -273,7 +280,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(badPubKey));
// Bob verifies Alice's public key
oneOf(crypto).deriveKeyCommitment(badPubKey);
oneOf(keyAgreementCrypto).deriveKeyCommitment(badPubKey);
will(returnValue(badCommit));
// Bob aborts
@@ -295,9 +302,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
SecretKey sharedSecret = getSecretKey();
KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
transport, theirPayload, ourPayload, ourKeyPair, true);
KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks,
crypto, keyAgreementCrypto, payloadEncoder, transport,
theirPayload, ourPayload, ourKeyPair, true);
// expectations
context.checking(new Expectations() {{
@@ -323,7 +330,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(bobPubKey));
// Alice verifies Bob's public key
oneOf(crypto).deriveKeyCommitment(bobPubKey);
oneOf(keyAgreementCrypto).deriveKeyCommitment(bobPubKey);
will(returnValue(bobCommit));
// Alice computes shared secret
@@ -332,8 +339,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(sharedSecret));
// Alice sends her confirmation record
oneOf(crypto).deriveConfirmationRecord(sharedSecret, bobPayload,
alicePayload, bobPubKey, ourKeyPair, true, true);
oneOf(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
bobPayload, alicePayload, bobPubKey, ourKeyPair,
true, true);
will(returnValue(aliceConfirm));
oneOf(transport).sendConfirm(aliceConfirm);
@@ -342,8 +350,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(badConfirm));
// Alice verifies Bob's confirmation record
oneOf(crypto).deriveConfirmationRecord(sharedSecret, bobPayload,
alicePayload, bobPubKey, ourKeyPair, true, false);
oneOf(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
bobPayload, alicePayload, bobPubKey, ourKeyPair,
true, false);
will(returnValue(bobConfirm));
// Alice aborts
@@ -365,9 +374,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
SecretKey sharedSecret = getSecretKey();
KeyAgreementProtocol protocol =
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
transport, theirPayload, ourPayload, ourKeyPair, false);
KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks,
crypto, keyAgreementCrypto, payloadEncoder, transport,
theirPayload, ourPayload, ourKeyPair, false);
// expectations
context.checking(new Expectations() {{
@@ -389,7 +398,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(alicePubKey));
// Bob verifies Alice's public key
oneOf(crypto).deriveKeyCommitment(alicePubKey);
oneOf(keyAgreementCrypto).deriveKeyCommitment(alicePubKey);
will(returnValue(aliceCommit));
// Bob sends his public key
@@ -405,16 +414,18 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(badConfirm));
// Bob verifies Alice's confirmation record
oneOf(crypto).deriveConfirmationRecord(sharedSecret, alicePayload,
bobPayload, alicePubKey, ourKeyPair, false, true);
oneOf(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
alicePayload, bobPayload, alicePubKey, ourKeyPair,
false, true);
will(returnValue(aliceConfirm));
// Bob aborts
oneOf(transport).sendAbort(false);
// Bob never sends his confirmation record
never(crypto).deriveConfirmationRecord(sharedSecret, alicePayload,
bobPayload, alicePubKey, ourKeyPair, false, false);
never(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
alicePayload, bobPayload, alicePubKey, ourKeyPair,
false, false);
}});
// execute

View File

@@ -12,7 +12,7 @@ import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.keyagreement.KeyAgreementTaskFactory;
import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
import org.briarproject.bramble.api.keyagreement.PayloadParser;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
@@ -125,7 +125,7 @@ public interface AndroidComponent
ContactExchangeTask contactExchangeTask();
KeyAgreementTaskFactory keyAgreementTaskFactory();
KeyAgreementTask keyAgreementTask();
PayloadEncoder payloadEncoder();

View File

@@ -24,7 +24,6 @@ import com.google.zxing.Result;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
import org.briarproject.bramble.api.keyagreement.KeyAgreementTaskFactory;
import org.briarproject.bramble.api.keyagreement.Payload;
import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
import org.briarproject.bramble.api.keyagreement.PayloadParser;
@@ -48,6 +47,7 @@ import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Provider;
import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
import static android.bluetooth.BluetoothAdapter.EXTRA_STATE;
@@ -68,7 +68,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
private static final Logger LOG = Logger.getLogger(TAG);
@Inject
KeyAgreementTaskFactory keyAgreementTaskFactory;
Provider<KeyAgreementTask> keyAgreementTaskProvider;
@Inject
PayloadEncoder payloadEncoder;
@Inject
@@ -187,7 +187,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
@UiThread
private void startListening() {
KeyAgreementTask oldTask = task;
KeyAgreementTask newTask = keyAgreementTaskFactory.createTask();
KeyAgreementTask newTask = keyAgreementTaskProvider.get();
task = newTask;
ioExecutor.execute(() -> {
if (oldTask != null) oldTask.stopListening();