mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Merge branch '117-qr-contacts' into 'master'
BQP with QR codes This MR implements BQP for key agreement over short-range transports. It also implements the Android UI for using BQP with QR codes. Closes #117. See merge request !84
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package org.briarproject.api.contact;
|
||||
|
||||
import org.briarproject.api.identity.Author;
|
||||
|
||||
public interface ContactExchangeListener {
|
||||
|
||||
void contactExchangeSucceeded(Author remoteAuthor);
|
||||
|
||||
/** The exchange failed because the contact already exists. */
|
||||
void duplicateContact(Author remoteAuthor);
|
||||
|
||||
/** A general failure. */
|
||||
void contactExchangeFailed();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.briarproject.api.contact;
|
||||
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.crypto.SecretKey;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
|
||||
/**
|
||||
* A task for conducting a contact information exchange with a remote peer.
|
||||
*/
|
||||
public interface ContactExchangeTask {
|
||||
|
||||
/**
|
||||
* Exchange contact information with a remote peer.
|
||||
*/
|
||||
void startExchange(ContactExchangeListener listener,
|
||||
LocalAuthor localAuthor, SecretKey masterSecret,
|
||||
DuplexTransportConnection conn, TransportId transportId,
|
||||
boolean alice);
|
||||
}
|
||||
@@ -36,18 +36,17 @@ public interface CryptoComponent {
|
||||
int deriveBTConfirmationCode(SecretKey master, boolean alice);
|
||||
|
||||
/**
|
||||
* Derives a header key for an invitation stream from the given master
|
||||
* secret.
|
||||
* Derives a stream header key from the given master secret.
|
||||
* @param alice whether the key is for use by Alice or Bob.
|
||||
*/
|
||||
SecretKey deriveBTInvitationKey(SecretKey master, boolean alice);
|
||||
SecretKey deriveHeaderKey(SecretKey master, boolean alice);
|
||||
|
||||
/**
|
||||
* Derives a nonce from the given master secret for one of the parties to
|
||||
* sign.
|
||||
* @param alice whether the nonce is for use by Alice or Bob.
|
||||
*/
|
||||
byte[] deriveBTSignatureNonce(SecretKey master, boolean alice);
|
||||
byte[] deriveSignatureNonce(SecretKey master, boolean alice);
|
||||
|
||||
/**
|
||||
* Derives a commitment to the provided public key.
|
||||
@@ -107,7 +106,7 @@ public interface CryptoComponent {
|
||||
* Derives a master secret from two public keys and one of the corresponding
|
||||
* private keys.
|
||||
* <p/>
|
||||
* Part of BQP. This is a helper method that calls
|
||||
* This is a helper method that calls
|
||||
* deriveMasterSecret(deriveSharedSecret(theirPublicKey, ourKeyPair, alice))
|
||||
*
|
||||
* @param theirPublicKey the ephemeral public key of the remote party
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.briarproject.api.event;
|
||||
|
||||
/** An event that is broadcast when a BQP protocol aborts. */
|
||||
public class KeyAgreementAbortedEvent extends Event {
|
||||
|
||||
private final boolean remoteAborted;
|
||||
|
||||
public KeyAgreementAbortedEvent(boolean remoteAborted) {
|
||||
this.remoteAborted = remoteAborted;
|
||||
}
|
||||
|
||||
public boolean didRemoteAbort() {
|
||||
return remoteAborted;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package org.briarproject.api.event;
|
||||
|
||||
/** An event that is broadcast when a BQP connection cannot be created. */
|
||||
public class KeyAgreementFailedEvent extends Event {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.briarproject.api.event;
|
||||
|
||||
import org.briarproject.api.keyagreement.KeyAgreementResult;
|
||||
|
||||
/** An event that is broadcast when a BQP protocol completes. */
|
||||
public class KeyAgreementFinishedEvent extends Event {
|
||||
|
||||
private final KeyAgreementResult result;
|
||||
|
||||
public KeyAgreementFinishedEvent(KeyAgreementResult result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public KeyAgreementResult getResult() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.briarproject.api.event;
|
||||
|
||||
import org.briarproject.api.keyagreement.Payload;
|
||||
|
||||
/** An event that is broadcast when a BQP task is listening. */
|
||||
public class KeyAgreementListeningEvent extends Event {
|
||||
|
||||
private final Payload localPayload;
|
||||
|
||||
public KeyAgreementListeningEvent(Payload localPayload) {
|
||||
this.localPayload = localPayload;
|
||||
}
|
||||
|
||||
public Payload getLocalPayload() {
|
||||
return localPayload;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package org.briarproject.api.event;
|
||||
|
||||
/** An event that is broadcast when a BQP protocol completes. */
|
||||
public class KeyAgreementStartedEvent extends Event {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.briarproject.api.event;
|
||||
|
||||
/**
|
||||
* An event that is broadcast when a BQP protocol is waiting on the remote
|
||||
* peer to start.
|
||||
*/
|
||||
public class KeyAgreementWaitingEvent extends Event {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.briarproject.api.keyagreement;
|
||||
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
|
||||
public class KeyAgreementConnection {
|
||||
private final DuplexTransportConnection conn;
|
||||
private final TransportId id;
|
||||
|
||||
public KeyAgreementConnection(DuplexTransportConnection conn,
|
||||
TransportId id) {
|
||||
this.conn = conn;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public DuplexTransportConnection getConnection() {
|
||||
return conn;
|
||||
}
|
||||
|
||||
public TransportId getTransportId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,17 @@ package org.briarproject.api.keyagreement;
|
||||
|
||||
public interface KeyAgreementConstants {
|
||||
|
||||
/** The current version of the BQP protocol. */
|
||||
byte PROTOCOL_VERSION = 1;
|
||||
|
||||
/** The length of the record header in bytes. */
|
||||
int RECORD_HEADER_LENGTH = 4;
|
||||
|
||||
/** The offset of the payload length in the record header, in bytes. */
|
||||
int RECORD_HEADER_PAYLOAD_LENGTH_OFFSET = 2;
|
||||
|
||||
/** The length of the BQP key commitment in bytes. */
|
||||
int COMMIT_LENGTH = 16;
|
||||
|
||||
long CONNECTION_TIMEOUT = 20 * 1000; // Milliseconds
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.briarproject.api.keyagreement;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* An class for managing a particular key agreement listener.
|
||||
*/
|
||||
public abstract class KeyAgreementListener {
|
||||
|
||||
private final TransportDescriptor descriptor;
|
||||
|
||||
public KeyAgreementListener(TransportDescriptor descriptor) {
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the descriptor that a remote peer can use to connect to this
|
||||
* listener.
|
||||
*/
|
||||
public TransportDescriptor getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts listening for incoming connections, and returns a Callable that
|
||||
* will return a KeyAgreementConnection when an incoming connection is
|
||||
* received.
|
||||
*/
|
||||
public abstract Callable<KeyAgreementConnection> listen();
|
||||
|
||||
/**
|
||||
* Closes the underlying server socket.
|
||||
*/
|
||||
public abstract void close();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.briarproject.api.keyagreement;
|
||||
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.crypto.SecretKey;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
|
||||
public class KeyAgreementResult {
|
||||
|
||||
private final SecretKey masterKey;
|
||||
private final DuplexTransportConnection connection;
|
||||
private final TransportId transportId;
|
||||
private final boolean alice;
|
||||
|
||||
public KeyAgreementResult(SecretKey masterKey,
|
||||
DuplexTransportConnection connection, TransportId transportId,
|
||||
boolean alice) {
|
||||
this.masterKey = masterKey;
|
||||
this.connection = connection;
|
||||
this.transportId = transportId;
|
||||
this.alice = alice;
|
||||
}
|
||||
|
||||
public SecretKey getMasterKey() {
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
public DuplexTransportConnection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
public TransportId getTransportId() {
|
||||
return transportId;
|
||||
}
|
||||
|
||||
public boolean wasAlice() {
|
||||
return alice;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.briarproject.api.keyagreement;
|
||||
|
||||
/** A task for conducting a key agreement with a remote peer. */
|
||||
public interface KeyAgreementTask {
|
||||
|
||||
/**
|
||||
* Start listening for short-range BQP connections, if we are not already.
|
||||
* <p/>
|
||||
* Will trigger a KeyAgreementListeningEvent containing the local Payload,
|
||||
* even if we are already listening.
|
||||
*/
|
||||
void listen();
|
||||
|
||||
/**
|
||||
* Stop listening for short-range BQP connections.
|
||||
*/
|
||||
void stopListening();
|
||||
|
||||
/** Asynchronously start the connection process. */
|
||||
void connectAndRunProtocol(Payload remotePayload);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.briarproject.api.keyagreement;
|
||||
|
||||
/** Manages tasks for conducting key agreements with remote peers. */
|
||||
public interface KeyAgreementTaskFactory {
|
||||
|
||||
/** Gets the current key agreement task. */
|
||||
KeyAgreementTask getTask();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.briarproject.api.keyagreement;
|
||||
|
||||
import org.briarproject.api.UniqueId;
|
||||
|
||||
/**
|
||||
* Type-safe wrapper for a byte array that uniquely identifies a BQP task.
|
||||
*/
|
||||
public class KeyAgreementTaskId extends UniqueId {
|
||||
|
||||
public KeyAgreementTaskId(byte[] id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof KeyAgreementTaskId && super.equals(o);
|
||||
}
|
||||
}
|
||||
34
briar-api/src/org/briarproject/api/keyagreement/Payload.java
Normal file
34
briar-api/src/org/briarproject/api/keyagreement/Payload.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package org.briarproject.api.keyagreement;
|
||||
|
||||
import org.briarproject.api.Bytes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A BQP payload.
|
||||
*/
|
||||
public class Payload implements Comparable<Payload> {
|
||||
|
||||
private final Bytes commitment;
|
||||
private final List<TransportDescriptor> descriptors;
|
||||
|
||||
public Payload(byte[] commitment, List<TransportDescriptor> descriptors) {
|
||||
this.commitment = new Bytes(commitment);
|
||||
this.descriptors = descriptors;
|
||||
}
|
||||
|
||||
/** Returns the commitment contained in this payload. */
|
||||
public byte[] getCommitment() {
|
||||
return commitment.getBytes();
|
||||
}
|
||||
|
||||
/** Returns the transport descriptors contained in this payload. */
|
||||
public List<TransportDescriptor> getTransportDescriptors() {
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Payload p) {
|
||||
return commitment.compareTo(p.commitment);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package org.briarproject.api.keyagreement;
|
||||
|
||||
public interface PayloadEncoder {
|
||||
|
||||
byte[] encode(Payload p);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.briarproject.api.keyagreement;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface PayloadParser {
|
||||
|
||||
Payload parse(byte[] raw) throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.briarproject.api.keyagreement;
|
||||
|
||||
/** Record types for BQP. */
|
||||
public interface RecordTypes {
|
||||
|
||||
byte KEY = 0;
|
||||
byte CONFIRM = 1;
|
||||
byte ABORT = 2;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.briarproject.api.keyagreement;
|
||||
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.properties.TransportProperties;
|
||||
|
||||
/**
|
||||
* Describes how to connect to a device over a short-range transport.
|
||||
*/
|
||||
public class TransportDescriptor {
|
||||
|
||||
private final TransportId id;
|
||||
private final TransportProperties properties;
|
||||
|
||||
public TransportDescriptor(TransportId id, TransportProperties properties) {
|
||||
this.id = id;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/** Returns the transport identifier. */
|
||||
public TransportId getIdentifier() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/** Returns the transport properties. */
|
||||
public TransportProperties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
@@ -19,4 +19,7 @@ public interface PluginManager {
|
||||
|
||||
/** Returns any running duplex plugins that support invitations. */
|
||||
Collection<DuplexPlugin> getInvitationPlugins();
|
||||
|
||||
/** Returns any running duplex plugins that support key agreement. */
|
||||
Collection<DuplexPlugin> getKeyAgreementPlugins();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package org.briarproject.api.plugins.duplex;
|
||||
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.crypto.PseudoRandom;
|
||||
import org.briarproject.api.keyagreement.KeyAgreementListener;
|
||||
import org.briarproject.api.keyagreement.TransportDescriptor;
|
||||
import org.briarproject.api.plugins.Plugin;
|
||||
|
||||
/** An interface for transport plugins that support duplex communication. */
|
||||
@@ -24,4 +26,19 @@ public interface DuplexPlugin extends Plugin {
|
||||
*/
|
||||
DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
||||
long timeout, boolean alice);
|
||||
|
||||
/** Returns true if the plugin supports short-range key agreement. */
|
||||
boolean supportsKeyAgreement();
|
||||
|
||||
/**
|
||||
* Returns a listener that can be used to perform key agreement.
|
||||
*/
|
||||
KeyAgreementListener createKeyAgreementListener(byte[] localCommitment);
|
||||
|
||||
/**
|
||||
* Attempts to connect to the remote peer specified in the given descriptor.
|
||||
* Returns null if no connection can be established within the given time.
|
||||
*/
|
||||
DuplexTransportConnection createKeyAgreementConnection(
|
||||
byte[] remoteCommitment, TransportDescriptor d, long timeout);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user