Create HandshakeKeyExchange client and module

This commit is contained in:
ameba23
2021-06-28 09:55:41 +02:00
parent 0a0b79ad9b
commit 47f136904c
5 changed files with 324 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
package org.briarproject.briar.api.handshakekeyexchange;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.briar.api.conversation.ConversationManager;
public interface HandshakeKeyExchangeManager extends ConversationManager.ConversationClient {
/**
* The unique ID of the client.
*/
ClientId CLIENT_ID = new ClientId("org.briarproject.briar.handshakekeyexchange");
/**
* The current major version of the handshake key exchange client.
*/
int MAJOR_VERSION = 0;
/**
* The current minor version of the handshake key exchange client.
*/
int MINOR_VERSION = 0;
}

View File

@@ -0,0 +1,13 @@
package org.briarproject.briar.handshakekeyexchange;
public interface HandshakeKeyExchangeConstants {
// Group metadata keys
String GROUP_KEY_CONTACT_ID = "contactId";
// Message metadata keys
String MSG_KEY_TIMESTAMP = "timestamp";
String MSG_KEY_MESSAGE_TYPE = "messageType";
String MSG_KEY_LOCAL = "local";
String MSG_KEY_VERSION = "version";
}

View File

@@ -0,0 +1,235 @@
package org.briarproject.briar.handshakekeyexchange;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.client.ContactGroupFactory;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.crypto.AgreementPublicKey;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataParser;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.versioning.ClientVersion;
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.conversation.ConversationManager;
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
import org.briarproject.briar.api.conversation.DeletionResult;
import org.briarproject.briar.api.handshakekeyexchange.HandshakeKeyExchangeManager;
import org.briarproject.briar.client.ConversationClientImpl;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import javax.inject.Inject;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.briar.handshakekeyexchange.HandshakeKeyExchangeConstants.GROUP_KEY_CONTACT_ID;
import static org.briarproject.briar.handshakekeyexchange.HandshakeKeyExchangeConstants.MSG_KEY_LOCAL;
import static org.briarproject.briar.handshakekeyexchange.HandshakeKeyExchangeConstants.MSG_KEY_TIMESTAMP;
public class HandshakeKeyExchangeManagerImpl extends ConversationClientImpl
implements
HandshakeKeyExchangeManager, LifecycleManager.OpenDatabaseHook,
ContactManager.ContactHook {
private final ClientVersioningManager clientVersioningManager;
private final ContactGroupFactory contactGroupFactory;
private final ContactManager contactManager;
private final IdentityManager identityManager;
private final Group localGroup;
private final Clock clock;
private PublicKey handshakePublicKey;
private static final Logger LOG =
getLogger(HandshakeKeyExchangeManager.class.getName());
@Inject
protected HandshakeKeyExchangeManagerImpl (
DatabaseComponent db,
ClientHelper clientHelper,
MetadataParser metadataParser,
MessageTracker messageTracker,
ClientVersioningManager clientVersioningManager,
ContactGroupFactory contactGroupFactory,
ContactManager contactManager,
IdentityManager identityManager,
Clock clock
) {
super(db, clientHelper, metadataParser, messageTracker);
this.clientVersioningManager = clientVersioningManager;
this.contactGroupFactory = contactGroupFactory;
this.contactManager = contactManager;
this.identityManager = identityManager;
this.clock = clock;
localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID, MAJOR_VERSION);
}
@Override
public void onDatabaseOpened(Transaction txn) throws DbException {
if (db.containsGroup(txn, localGroup.getId())) return;
db.addGroup(txn, localGroup);
// Get our own handshake public key
handshakePublicKey = identityManager.getHandshakeKeys(txn).getPublic();
// Set things up for any pre-existing contacts
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
}
@Override
public Group getContactGroup(Contact c) {
return contactGroupFactory.createContactGroup(CLIENT_ID,
MAJOR_VERSION, c);
}
@Override
public Collection<ConversationMessageHeader> getMessageHeaders(
Transaction txn, ContactId contactId) throws DbException {
return null;
}
@Override
public Set<MessageId> getMessageIds(Transaction txn, ContactId contactId)
throws DbException {
Contact contact = db.getContact(txn, contactId);
GroupId contactGroupId = getContactGroup(contact).getId();
try {
Map<MessageId, BdfDictionary> messages = clientHelper
.getMessageMetadataAsDictionary(txn, contactGroupId);
return messages.keySet();
} catch (FormatException e) {
throw new DbException(e);
}
}
@Override
public void setReadFlag(GroupId g, MessageId m, boolean read)
throws DbException {
}
@Override
public DeletionResult deleteAllMessages(Transaction txn, ContactId c)
throws DbException {
GroupId g = getContactGroup(db.getContact(txn, c)).getId();
for (MessageId messageId : db.getMessageIds(txn, g)) {
db.deleteMessage(txn, messageId);
db.deleteMessageMetadata(txn, messageId);
}
messageTracker.initializeGroupCount(txn, g);
return new DeletionResult();
}
@Override
public DeletionResult deleteMessages(Transaction txn, ContactId c,
Set<MessageId> messageIds) throws DbException {
for (MessageId m : messageIds) {
db.deleteMessage(txn, m);
db.deleteMessageMetadata(txn, m);
}
return new DeletionResult();
}
@Override
protected boolean incomingMessage(Transaction txn, Message m, BdfList body,
BdfDictionary meta) throws DbException, FormatException {
LOG.info("Incoming HandshakeKeyExchange message");
ContactId contactId = getContactId(txn, m.getGroupId());
Contact c = contactManager.getContact(txn, contactId);
if (c.getHandshakePublicKey() != null) {
LOG.info("Already have public key - ignoring message");
return false;
}
PublicKey handshakePublicKey = new AgreementPublicKey(body.getRaw(0));
return false;
}
private ContactId getContactId(Transaction txn, GroupId g)
throws DbException {
try {
BdfDictionary meta =
clientHelper.getGroupMetadataAsDictionary(txn, g);
return new ContactId(meta.getLong(
HandshakeKeyExchangeConstants.GROUP_KEY_CONTACT_ID).intValue());
} catch (FormatException e) {
throw new DbException(e);
}
}
@Override
public void addingContact(Transaction txn, Contact c) throws DbException {
// Create a group to share with the contact
Group g = getContactGroup(c);
db.addGroup(txn, g);
// Apply the client's visibility to the contact group
Group.Visibility client =
clientVersioningManager.getClientVisibility(txn,
c.getId(), CLIENT_ID, MAJOR_VERSION);
db.setGroupVisibility(txn, c.getId(), g.getId(), client);
// Attach the contact ID to the group
setContactId(txn, g.getId(), c.getId());
if (c.getHandshakePublicKey() == null) {
sendHandshakePublicKey(txn, c);
}
}
private void sendHandshakePublicKey(Transaction txn, Contact c)
throws DbException {
Group group = getContactGroup(c);
GroupId g = group.getId();
if (!db.containsGroup(txn, g)) db.addGroup(txn, group);
long timestamp = clock.currentTimeMillis();
BdfList bodyList = new BdfList();
bodyList.add(handshakePublicKey);
try {
byte[] body = clientHelper.toByteArray(bodyList);
Message m = clientHelper.createMessage(g, timestamp, body);
BdfDictionary meta = BdfDictionary.of(
new BdfEntry(MSG_KEY_LOCAL, true),
new BdfEntry(MSG_KEY_TIMESTAMP, timestamp)
);
clientHelper.addLocalMessage(txn, m, meta, true, false);
} catch (FormatException e) {
throw new DbException();
}
// messageTracker.trackOutgoingMessage(txn, m);
}
@Override
public void removingContact(Transaction txn, Contact c) throws DbException {
db.removeGroup(txn, getContactGroup(c));
}
private void setContactId(Transaction txn, GroupId g, ContactId c)
throws DbException {
BdfDictionary d = new BdfDictionary();
d.put(GROUP_KEY_CONTACT_ID, c.getInt());
try {
clientHelper.mergeGroupMetadata(txn, g, d);
} catch (FormatException e) {
throw new AssertionError(e);
}
}
}

View File

@@ -0,0 +1,23 @@
package org.briarproject.briar.handshakekeyexchange;
import org.briarproject.briar.api.handshakekeyexchange.HandshakeKeyExchangeManager;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class HandshakeKeyExchangeModule {
public static class EagerSingletons {
@Inject
HandshakeKeyExchangeManager handshakeKeyExchangeManager;
}
@Provides
@Singleton
HandshakeKeyExchangeManager handshakeKeyExchangeManager(HandshakeKeyExchangeManagerImpl handshakeKeyExchangeManager) {
return handshakeKeyExchangeManager;
}
}

View File

@@ -0,0 +1,31 @@
package org.briarproject.briar.handshakekeyexchange;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.BdfMessageContext;
import org.briarproject.bramble.api.client.BdfMessageValidator;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.system.Clock;
import javax.inject.Inject;
public class HandshakeKeyExchangeValidator extends BdfMessageValidator {
@Inject
protected HandshakeKeyExchangeValidator(
ClientHelper clientHelper,
MetadataEncoder metadataEncoder,
Clock clock) {
super(clientHelper, metadataEncoder, clock);
}
@Override
protected BdfMessageContext validateMessage(Message m, Group g,
BdfList body) throws InvalidMessageException, FormatException {
return null;
}
}