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 * Derives a nonce from the given secret key that can be used for key
* binding. * binding.
* *
* TODO: This just calls mac(), remove it
*
* @param label a namespaced label indicating the purpose of this nonce, * @param label a namespaced label indicating the purpose of this nonce,
* to prevent it from being repurposed or colliding with a nonce derived * to prevent it from being repurposed or colliding with a nonce derived
* for another purpose * for another purpose
*/ */
byte[] deriveKeyBindingNonce(String label, SecretKey k); 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 * Derives a common shared secret from two public keys and one of the
* corresponding private keys. * corresponding private keys.
@@ -67,25 +59,6 @@ public interface CryptoComponent {
SecretKey deriveSharedSecret(String label, PublicKey theirPublicKey, SecretKey deriveSharedSecret(String label, PublicKey theirPublicKey,
KeyPair ourKeyPair, boolean alice) throws GeneralSecurityException; 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. * 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 javax.inject.Inject;
import static java.util.logging.Level.INFO; 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.crypto.EllipticCurveConstants.PARAMETERS;
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES; 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_TARGET_MILLIS = 500;
private static final int PBKDF_SAMPLES = 30; 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 SecureRandom secureRandom;
private final ECKeyPairGenerator agreementKeyPairGenerator; private final ECKeyPairGenerator agreementKeyPairGenerator;
private final ECKeyPairGenerator signatureKeyPairGenerator; private final ECKeyPairGenerator signatureKeyPairGenerator;
@@ -230,23 +219,13 @@ class CryptoComponentImpl implements CryptoComponent {
} }
@Override @Override
public SecretKey deriveKey(String label, SecretKey k, public SecretKey deriveKey(String label, SecretKey k, byte[]... inputs) {
byte[]... inputs) { return new SecretKey(mac(label, k, inputs));
return new SecretKey(macKdf(label, k, inputs));
} }
@Override @Override
public byte[] deriveKeyBindingNonce(String label, SecretKey k) { public byte[] deriveKeyBindingNonce(String label, SecretKey k) {
return macKdf(label, k); return mac(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;
} }
@Override @Override
@@ -265,32 +244,6 @@ class CryptoComponentImpl implements CryptoComponent {
return new SecretKey(hash(label, raw, alicePub, bobPub)); 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 @Override
public byte[] sign(String label, byte[] toSign, byte[] privateKey) public byte[] sign(String label, byte[] toSign, byte[] privateKey)
throws GeneralSecurityException { throws GeneralSecurityException {
@@ -464,15 +417,6 @@ class CryptoComponentImpl implements CryptoComponent {
return AsciiArmour.wrap(b, lineLength); 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 // Password-based key derivation function - see PKCS#5 v2.1, section 5.2
private byte[] pbkdf2(String password, byte[] salt, int iterations) { private byte[] pbkdf2(String password, byte[] salt, int iterations) {
byte[] utf8 = StringUtils.toUtf8(password); 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.TimeLoggingExecutor;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.CryptoExecutor; 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.PasswordStrengthEstimator;
import org.briarproject.bramble.api.crypto.StreamDecrypterFactory; import org.briarproject.bramble.api.crypto.StreamDecrypterFactory;
import org.briarproject.bramble.api.crypto.StreamEncrypterFactory; import org.briarproject.bramble.api.crypto.StreamEncrypterFactory;
@@ -95,6 +96,12 @@ public class CryptoModule {
cipherProvider); cipherProvider);
} }
@Provides
KeyAgreementCrypto provideKeyAgreementCrypto(
KeyAgreementCryptoImpl keyAgreementCrypto) {
return keyAgreementCrypto;
}
@Provides @Provides
@Singleton @Singleton
@CryptoExecutor @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; 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.KeyPair;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection; import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
@@ -46,7 +46,7 @@ class KeyAgreementConnector {
private final Callbacks callbacks; private final Callbacks callbacks;
private final Clock clock; private final Clock clock;
private final CryptoComponent crypto; private final KeyAgreementCrypto keyAgreementCrypto;
private final PluginManager pluginManager; private final PluginManager pluginManager;
private final CompletionService<KeyAgreementConnection> connect; private final CompletionService<KeyAgreementConnection> connect;
@@ -58,11 +58,11 @@ class KeyAgreementConnector {
private volatile boolean alice = false; private volatile boolean alice = false;
KeyAgreementConnector(Callbacks callbacks, Clock clock, KeyAgreementConnector(Callbacks callbacks, Clock clock,
CryptoComponent crypto, PluginManager pluginManager, KeyAgreementCrypto keyAgreementCrypto, PluginManager pluginManager,
Executor ioExecutor) { Executor ioExecutor) {
this.callbacks = callbacks; this.callbacks = callbacks;
this.clock = clock; this.clock = clock;
this.crypto = crypto; this.keyAgreementCrypto = keyAgreementCrypto;
this.pluginManager = pluginManager; this.pluginManager = pluginManager;
connect = new ExecutorCompletionService<>(ioExecutor); connect = new ExecutorCompletionService<>(ioExecutor);
} }
@@ -70,8 +70,8 @@ class KeyAgreementConnector {
public Payload listen(KeyPair localKeyPair) { public Payload listen(KeyPair localKeyPair) {
LOG.info("Starting BQP listeners"); LOG.info("Starting BQP listeners");
// Derive commitment // Derive commitment
byte[] commitment = byte[] commitment = keyAgreementCrypto.deriveKeyCommitment(
crypto.deriveKeyCommitment(localKeyPair.getPublic()); localKeyPair.getPublic());
// Start all listeners and collect their descriptors // Start all listeners and collect their descriptors
List<TransportDescriptor> descriptors = new ArrayList<>(); List<TransportDescriptor> descriptors = new ArrayList<>();
for (DuplexPlugin plugin : pluginManager.getKeyAgreementPlugins()) { for (DuplexPlugin plugin : pluginManager.getKeyAgreementPlugins()) {

View File

@@ -1,19 +1,10 @@
package org.briarproject.bramble.keyagreement; 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.BdfReaderFactory;
import org.briarproject.bramble.api.data.BdfWriterFactory; import org.briarproject.bramble.api.data.BdfWriterFactory;
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.keyagreement.PayloadEncoder;
import org.briarproject.bramble.api.keyagreement.PayloadParser; 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.Module;
import dagger.Provides; import dagger.Provides;
@@ -22,13 +13,9 @@ import dagger.Provides;
public class KeyAgreementModule { public class KeyAgreementModule {
@Provides @Provides
@Singleton KeyAgreementTask provideKeyAgreementTask(
KeyAgreementTaskFactory provideKeyAgreementTaskFactory(Clock clock, KeyAgreementTaskImpl keyAgreementTask) {
CryptoComponent crypto, EventBus eventBus, return keyAgreementTask;
@IoExecutor Executor ioExecutor, PayloadEncoder payloadEncoder,
PluginManager pluginManager) {
return new KeyAgreementTaskFactoryImpl(clock, crypto, eventBus,
ioExecutor, payloadEncoder, pluginManager);
} }
@Provides @Provides

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.keyagreement; package org.briarproject.bramble.keyagreement;
import org.briarproject.bramble.api.crypto.CryptoComponent; 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.KeyPair;
import org.briarproject.bramble.api.crypto.KeyParser; import org.briarproject.bramble.api.crypto.KeyParser;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
@@ -62,6 +63,7 @@ class KeyAgreementProtocol {
private final Callbacks callbacks; private final Callbacks callbacks;
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final KeyAgreementCrypto keyAgreementCrypto;
private final PayloadEncoder payloadEncoder; private final PayloadEncoder payloadEncoder;
private final KeyAgreementTransport transport; private final KeyAgreementTransport transport;
private final Payload theirPayload, ourPayload; private final Payload theirPayload, ourPayload;
@@ -69,11 +71,13 @@ class KeyAgreementProtocol {
private final boolean alice; private final boolean alice;
KeyAgreementProtocol(Callbacks callbacks, CryptoComponent crypto, KeyAgreementProtocol(Callbacks callbacks, CryptoComponent crypto,
KeyAgreementCrypto keyAgreementCrypto,
PayloadEncoder payloadEncoder, KeyAgreementTransport transport, PayloadEncoder payloadEncoder, KeyAgreementTransport transport,
Payload theirPayload, Payload ourPayload, KeyPair ourKeyPair, Payload theirPayload, Payload ourPayload, KeyPair ourKeyPair,
boolean alice) { boolean alice) {
this.callbacks = callbacks; this.callbacks = callbacks;
this.crypto = crypto; this.crypto = crypto;
this.keyAgreementCrypto = keyAgreementCrypto;
this.payloadEncoder = payloadEncoder; this.payloadEncoder = payloadEncoder;
this.transport = transport; this.transport = transport;
this.theirPayload = theirPayload; this.theirPayload = theirPayload;
@@ -126,7 +130,7 @@ class KeyAgreementProtocol {
KeyParser keyParser = crypto.getAgreementKeyParser(); KeyParser keyParser = crypto.getAgreementKeyParser();
try { try {
PublicKey publicKey = keyParser.parsePublicKey(publicKeyBytes); PublicKey publicKey = keyParser.parsePublicKey(publicKeyBytes);
byte[] expected = crypto.deriveKeyCommitment(publicKey); byte[] expected = keyAgreementCrypto.deriveKeyCommitment(publicKey);
if (!Arrays.equals(expected, theirPayload.getCommitment())) if (!Arrays.equals(expected, theirPayload.getCommitment()))
throw new AbortException(); throw new AbortException();
return publicKey; return publicKey;
@@ -147,7 +151,7 @@ class KeyAgreementProtocol {
private void sendConfirm(SecretKey s, PublicKey theirPublicKey) private void sendConfirm(SecretKey s, PublicKey theirPublicKey)
throws IOException { throws IOException {
byte[] confirm = crypto.deriveConfirmationRecord(s, byte[] confirm = keyAgreementCrypto.deriveConfirmationRecord(s,
payloadEncoder.encode(theirPayload), payloadEncoder.encode(theirPayload),
payloadEncoder.encode(ourPayload), payloadEncoder.encode(ourPayload),
theirPublicKey, ourKeyPair, theirPublicKey, ourKeyPair,
@@ -158,7 +162,7 @@ class KeyAgreementProtocol {
private void receiveConfirm(SecretKey s, PublicKey theirPublicKey) private void receiveConfirm(SecretKey s, PublicKey theirPublicKey)
throws AbortException { throws AbortException {
byte[] confirm = transport.receiveConfirm(); byte[] confirm = transport.receiveConfirm();
byte[] expected = crypto.deriveConfirmationRecord(s, byte[] expected = keyAgreementCrypto.deriveConfirmationRecord(s,
payloadEncoder.encode(theirPayload), payloadEncoder.encode(theirPayload),
payloadEncoder.encode(ourPayload), payloadEncoder.encode(ourPayload),
theirPublicKey, ourKeyPair, 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; package org.briarproject.bramble.keyagreement;
import org.briarproject.bramble.api.crypto.CryptoComponent; 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.KeyPair;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.event.EventBus; 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.KeyAgreementListeningEvent;
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementStartedEvent; import org.briarproject.bramble.api.keyagreement.event.KeyAgreementStartedEvent;
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementWaitingEvent; 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.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginManager; import org.briarproject.bramble.api.plugin.PluginManager;
@@ -23,6 +25,8 @@ import java.io.IOException;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -35,6 +39,7 @@ class KeyAgreementTaskImpl extends Thread implements
Logger.getLogger(KeyAgreementTaskImpl.class.getName()); Logger.getLogger(KeyAgreementTaskImpl.class.getName());
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final KeyAgreementCrypto keyAgreementCrypto;
private final EventBus eventBus; private final EventBus eventBus;
private final PayloadEncoder payloadEncoder; private final PayloadEncoder payloadEncoder;
private final KeyPair localKeyPair; private final KeyPair localKeyPair;
@@ -43,14 +48,17 @@ class KeyAgreementTaskImpl extends Thread implements
private Payload localPayload; private Payload localPayload;
private Payload remotePayload; private Payload remotePayload;
@Inject
KeyAgreementTaskImpl(Clock clock, CryptoComponent crypto, KeyAgreementTaskImpl(Clock clock, CryptoComponent crypto,
EventBus eventBus, PayloadEncoder payloadEncoder, KeyAgreementCrypto keyAgreementCrypto, EventBus eventBus,
PluginManager pluginManager, Executor ioExecutor) { PayloadEncoder payloadEncoder, PluginManager pluginManager,
@IoExecutor Executor ioExecutor) {
this.crypto = crypto; this.crypto = crypto;
this.keyAgreementCrypto = keyAgreementCrypto;
this.eventBus = eventBus; this.eventBus = eventBus;
this.payloadEncoder = payloadEncoder; this.payloadEncoder = payloadEncoder;
localKeyPair = crypto.generateAgreementKeyPair(); localKeyPair = crypto.generateAgreementKeyPair();
connector = new KeyAgreementConnector(this, clock, crypto, connector = new KeyAgreementConnector(this, clock, keyAgreementCrypto,
pluginManager, ioExecutor); pluginManager, ioExecutor);
} }
@@ -100,8 +108,8 @@ class KeyAgreementTaskImpl extends Thread implements
// Run BQP protocol over the connection // Run BQP protocol over the connection
LOG.info("Starting BQP protocol"); LOG.info("Starting BQP protocol");
KeyAgreementProtocol protocol = new KeyAgreementProtocol(this, crypto, KeyAgreementProtocol protocol = new KeyAgreementProtocol(this, crypto,
payloadEncoder, transport, remotePayload, localPayload, keyAgreementCrypto, payloadEncoder, transport, remotePayload,
localKeyPair, alice); localPayload, localKeyPair, alice);
try { try {
SecretKey master = protocol.perform(); SecretKey master = protocol.perform();
KeyAgreementResult result = KeyAgreementResult result =

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.keyagreement; package org.briarproject.bramble.keyagreement;
import org.briarproject.bramble.api.crypto.CryptoComponent; 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.KeyPair;
import org.briarproject.bramble.api.crypto.KeyParser; import org.briarproject.bramble.api.crypto.KeyParser;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
@@ -55,6 +56,8 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Mock @Mock
CryptoComponent crypto; CryptoComponent crypto;
@Mock @Mock
KeyAgreementCrypto keyAgreementCrypto;
@Mock
KeyParser keyParser; KeyParser keyParser;
@Mock @Mock
PayloadEncoder payloadEncoder; PayloadEncoder payloadEncoder;
@@ -72,9 +75,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
SecretKey sharedSecret = getSecretKey(); SecretKey sharedSecret = getSecretKey();
SecretKey masterSecret = getSecretKey(); SecretKey masterSecret = getSecretKey();
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks,
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, crypto, keyAgreementCrypto, payloadEncoder, transport,
transport, theirPayload, ourPayload, ourKeyPair, true); theirPayload, ourPayload, ourKeyPair, true);
// expectations // expectations
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -100,7 +103,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(bobPubKey)); will(returnValue(bobPubKey));
// Alice verifies Bob's public key // Alice verifies Bob's public key
oneOf(crypto).deriveKeyCommitment(bobPubKey); oneOf(keyAgreementCrypto).deriveKeyCommitment(bobPubKey);
will(returnValue(bobCommit)); will(returnValue(bobCommit));
// Alice computes shared secret // Alice computes shared secret
@@ -109,8 +112,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(sharedSecret)); will(returnValue(sharedSecret));
// Alice sends her confirmation record // Alice sends her confirmation record
oneOf(crypto).deriveConfirmationRecord(sharedSecret, bobPayload, oneOf(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
alicePayload, bobPubKey, ourKeyPair, true, true); bobPayload, alicePayload, bobPubKey, ourKeyPair,
true, true);
will(returnValue(aliceConfirm)); will(returnValue(aliceConfirm));
oneOf(transport).sendConfirm(aliceConfirm); oneOf(transport).sendConfirm(aliceConfirm);
@@ -119,8 +123,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(bobConfirm)); will(returnValue(bobConfirm));
// Alice verifies Bob's confirmation record // Alice verifies Bob's confirmation record
oneOf(crypto).deriveConfirmationRecord(sharedSecret, bobPayload, oneOf(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
alicePayload, bobPubKey, ourKeyPair, true, false); bobPayload, alicePayload, bobPubKey, ourKeyPair,
true, false);
will(returnValue(bobConfirm)); will(returnValue(bobConfirm));
// Alice computes master secret // Alice computes master secret
@@ -141,9 +146,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
SecretKey sharedSecret = getSecretKey(); SecretKey sharedSecret = getSecretKey();
SecretKey masterSecret = getSecretKey(); SecretKey masterSecret = getSecretKey();
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks,
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, crypto, keyAgreementCrypto, payloadEncoder, transport,
transport, theirPayload, ourPayload, ourKeyPair, false); theirPayload, ourPayload, ourKeyPair, false);
// expectations // expectations
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -165,7 +170,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(alicePubKey)); will(returnValue(alicePubKey));
// Bob verifies Alice's public key // Bob verifies Alice's public key
oneOf(crypto).deriveKeyCommitment(alicePubKey); oneOf(keyAgreementCrypto).deriveKeyCommitment(alicePubKey);
will(returnValue(aliceCommit)); will(returnValue(aliceCommit));
// Bob sends his public key // Bob sends his public key
@@ -181,13 +186,15 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(aliceConfirm)); will(returnValue(aliceConfirm));
// Bob verifies Alice's confirmation record // Bob verifies Alice's confirmation record
oneOf(crypto).deriveConfirmationRecord(sharedSecret, alicePayload, oneOf(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
bobPayload, alicePubKey, ourKeyPair, false, true); alicePayload, bobPayload, alicePubKey, ourKeyPair,
false, true);
will(returnValue(aliceConfirm)); will(returnValue(aliceConfirm));
// Bob sends his confirmation record // Bob sends his confirmation record
oneOf(crypto).deriveConfirmationRecord(sharedSecret, alicePayload, oneOf(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
bobPayload, alicePubKey, ourKeyPair, false, false); alicePayload, bobPayload, alicePubKey, ourKeyPair,
false, false);
will(returnValue(bobConfirm)); will(returnValue(bobConfirm));
oneOf(transport).sendConfirm(bobConfirm); oneOf(transport).sendConfirm(bobConfirm);
@@ -207,9 +214,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
Payload ourPayload = new Payload(aliceCommit, null); Payload ourPayload = new Payload(aliceCommit, null);
KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks,
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, crypto, keyAgreementCrypto, payloadEncoder, transport,
transport, theirPayload, ourPayload, ourKeyPair, true); theirPayload, ourPayload, ourKeyPair, true);
// expectations // expectations
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -231,7 +238,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(badPubKey)); will(returnValue(badPubKey));
// Alice verifies Bob's public key // Alice verifies Bob's public key
oneOf(crypto).deriveKeyCommitment(badPubKey); oneOf(keyAgreementCrypto).deriveKeyCommitment(badPubKey);
will(returnValue(badCommit)); will(returnValue(badCommit));
// Alice aborts // Alice aborts
@@ -253,9 +260,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
Payload ourPayload = new Payload(bobCommit, null); Payload ourPayload = new Payload(bobCommit, null);
KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks,
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, crypto, keyAgreementCrypto, payloadEncoder, transport,
transport, theirPayload, ourPayload, ourKeyPair, false); theirPayload, ourPayload, ourKeyPair, false);
// expectations // expectations
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -273,7 +280,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(badPubKey)); will(returnValue(badPubKey));
// Bob verifies Alice's public key // Bob verifies Alice's public key
oneOf(crypto).deriveKeyCommitment(badPubKey); oneOf(keyAgreementCrypto).deriveKeyCommitment(badPubKey);
will(returnValue(badCommit)); will(returnValue(badCommit));
// Bob aborts // Bob aborts
@@ -295,9 +302,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
SecretKey sharedSecret = getSecretKey(); SecretKey sharedSecret = getSecretKey();
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks,
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, crypto, keyAgreementCrypto, payloadEncoder, transport,
transport, theirPayload, ourPayload, ourKeyPair, true); theirPayload, ourPayload, ourKeyPair, true);
// expectations // expectations
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -323,7 +330,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(bobPubKey)); will(returnValue(bobPubKey));
// Alice verifies Bob's public key // Alice verifies Bob's public key
oneOf(crypto).deriveKeyCommitment(bobPubKey); oneOf(keyAgreementCrypto).deriveKeyCommitment(bobPubKey);
will(returnValue(bobCommit)); will(returnValue(bobCommit));
// Alice computes shared secret // Alice computes shared secret
@@ -332,8 +339,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(sharedSecret)); will(returnValue(sharedSecret));
// Alice sends her confirmation record // Alice sends her confirmation record
oneOf(crypto).deriveConfirmationRecord(sharedSecret, bobPayload, oneOf(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
alicePayload, bobPubKey, ourKeyPair, true, true); bobPayload, alicePayload, bobPubKey, ourKeyPair,
true, true);
will(returnValue(aliceConfirm)); will(returnValue(aliceConfirm));
oneOf(transport).sendConfirm(aliceConfirm); oneOf(transport).sendConfirm(aliceConfirm);
@@ -342,8 +350,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(badConfirm)); will(returnValue(badConfirm));
// Alice verifies Bob's confirmation record // Alice verifies Bob's confirmation record
oneOf(crypto).deriveConfirmationRecord(sharedSecret, bobPayload, oneOf(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
alicePayload, bobPubKey, ourKeyPair, true, false); bobPayload, alicePayload, bobPubKey, ourKeyPair,
true, false);
will(returnValue(bobConfirm)); will(returnValue(bobConfirm));
// Alice aborts // Alice aborts
@@ -365,9 +374,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
KeyPair ourKeyPair = new KeyPair(ourPubKey, null); KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
SecretKey sharedSecret = getSecretKey(); SecretKey sharedSecret = getSecretKey();
KeyAgreementProtocol protocol = KeyAgreementProtocol protocol = new KeyAgreementProtocol(callbacks,
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder, crypto, keyAgreementCrypto, payloadEncoder, transport,
transport, theirPayload, ourPayload, ourKeyPair, false); theirPayload, ourPayload, ourKeyPair, false);
// expectations // expectations
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -389,7 +398,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(alicePubKey)); will(returnValue(alicePubKey));
// Bob verifies Alice's public key // Bob verifies Alice's public key
oneOf(crypto).deriveKeyCommitment(alicePubKey); oneOf(keyAgreementCrypto).deriveKeyCommitment(alicePubKey);
will(returnValue(aliceCommit)); will(returnValue(aliceCommit));
// Bob sends his public key // Bob sends his public key
@@ -405,16 +414,18 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
will(returnValue(badConfirm)); will(returnValue(badConfirm));
// Bob verifies Alice's confirmation record // Bob verifies Alice's confirmation record
oneOf(crypto).deriveConfirmationRecord(sharedSecret, alicePayload, oneOf(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
bobPayload, alicePubKey, ourKeyPair, false, true); alicePayload, bobPayload, alicePubKey, ourKeyPair,
false, true);
will(returnValue(aliceConfirm)); will(returnValue(aliceConfirm));
// Bob aborts // Bob aborts
oneOf(transport).sendAbort(false); oneOf(transport).sendAbort(false);
// Bob never sends his confirmation record // Bob never sends his confirmation record
never(crypto).deriveConfirmationRecord(sharedSecret, alicePayload, never(keyAgreementCrypto).deriveConfirmationRecord(sharedSecret,
bobPayload, alicePubKey, ourKeyPair, false, false); alicePayload, bobPayload, alicePubKey, ourKeyPair,
false, false);
}}); }});
// execute // 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.db.DatabaseExecutor;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.IdentityManager; 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.PayloadEncoder;
import org.briarproject.bramble.api.keyagreement.PayloadParser; import org.briarproject.bramble.api.keyagreement.PayloadParser;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
@@ -125,7 +125,7 @@ public interface AndroidComponent
ContactExchangeTask contactExchangeTask(); ContactExchangeTask contactExchangeTask();
KeyAgreementTaskFactory keyAgreementTaskFactory(); KeyAgreementTask keyAgreementTask();
PayloadEncoder payloadEncoder(); 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.Event;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.keyagreement.KeyAgreementTask; 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.Payload;
import org.briarproject.bramble.api.keyagreement.PayloadEncoder; import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
import org.briarproject.bramble.api.keyagreement.PayloadParser; import org.briarproject.bramble.api.keyagreement.PayloadParser;
@@ -48,6 +47,7 @@ import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Provider;
import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED; import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
import static android.bluetooth.BluetoothAdapter.EXTRA_STATE; import static android.bluetooth.BluetoothAdapter.EXTRA_STATE;
@@ -68,7 +68,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
private static final Logger LOG = Logger.getLogger(TAG); private static final Logger LOG = Logger.getLogger(TAG);
@Inject @Inject
KeyAgreementTaskFactory keyAgreementTaskFactory; Provider<KeyAgreementTask> keyAgreementTaskProvider;
@Inject @Inject
PayloadEncoder payloadEncoder; PayloadEncoder payloadEncoder;
@Inject @Inject
@@ -187,7 +187,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
@UiThread @UiThread
private void startListening() { private void startListening() {
KeyAgreementTask oldTask = task; KeyAgreementTask oldTask = task;
KeyAgreementTask newTask = keyAgreementTaskFactory.createTask(); KeyAgreementTask newTask = keyAgreementTaskProvider.get();
task = newTask; task = newTask;
ioExecutor.execute(() -> { ioExecutor.execute(() -> {
if (oldTask != null) oldTask.stopListening(); if (oldTask != null) oldTask.stopListening();