Preliminaries for private group invitation protocol.

This commit is contained in:
akwizgran
2016-11-08 15:44:23 +00:00
parent 32f0b53d15
commit edbf5ff5b4
21 changed files with 179 additions and 84 deletions

View File

@@ -1,10 +1,10 @@
package org.briarproject.clients;
import org.briarproject.api.FormatException;
import org.briarproject.api.clients.BdfMessageContext;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.MessageQueueManager.QueueMessageValidator;
import org.briarproject.api.clients.QueueMessage;
import org.briarproject.api.clients.BdfMessageContext;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder;
@@ -12,13 +12,15 @@ import org.briarproject.api.db.Metadata;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.InvalidMessageException;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.ValidationManager.MessageValidator;
import org.briarproject.api.sync.MessageContext;
import org.briarproject.api.sync.ValidationManager.MessageValidator;
import org.briarproject.api.system.Clock;
import org.briarproject.util.StringUtils;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
@@ -78,7 +80,7 @@ public abstract class BdfMessageValidator implements MessageValidator,
}
}
protected void checkLength(String s, int minLength, int maxLength)
protected void checkLength(@Nullable String s, int minLength, int maxLength)
throws FormatException {
if (s != null) {
int length = StringUtils.toUtf8(s).length;
@@ -87,12 +89,13 @@ public abstract class BdfMessageValidator implements MessageValidator,
}
}
protected void checkLength(String s, int length) throws FormatException {
protected void checkLength(@Nullable String s, int length)
throws FormatException {
if (s != null && StringUtils.toUtf8(s).length != length)
throw new FormatException();
}
protected void checkLength(byte[] b, int minLength, int maxLength)
protected void checkLength(@Nullable byte[] b, int minLength, int maxLength)
throws FormatException {
if (b != null) {
if (b.length < minLength) throw new FormatException();
@@ -100,7 +103,8 @@ public abstract class BdfMessageValidator implements MessageValidator,
}
}
protected void checkLength(byte[] b, int length) throws FormatException {
protected void checkLength(@Nullable byte[] b, int length)
throws FormatException {
if (b != null && b.length != length) throw new FormatException();
}
@@ -112,11 +116,12 @@ public abstract class BdfMessageValidator implements MessageValidator,
}
}
protected void checkSize(BdfList list, int size) throws FormatException {
protected void checkSize(@Nullable BdfList list, int size)
throws FormatException {
if (list != null && list.size() != size) throw new FormatException();
}
protected void checkSize(BdfDictionary dictionary, int minSize,
protected void checkSize(@Nullable BdfDictionary dictionary, int minSize,
int maxSize) throws FormatException {
if (dictionary != null) {
if (dictionary.size() < minSize) throw new FormatException();
@@ -124,7 +129,7 @@ public abstract class BdfMessageValidator implements MessageValidator,
}
}
protected void checkSize(BdfDictionary dictionary, int size)
protected void checkSize(@Nullable BdfDictionary dictionary, int size)
throws FormatException {
if (dictionary != null && dictionary.size() != size)
throw new FormatException();

View File

@@ -19,6 +19,7 @@ import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Metadata;
import org.briarproject.api.db.Transaction;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageFactory;
@@ -37,28 +38,35 @@ import javax.inject.Inject;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
@NotNullByDefault
class ClientHelperImpl implements ClientHelper {
/**
* Length in bytes of the random salt used for creating local messages for
* storing metadata.
*/
private static final int SALT_LENGTH = 32;
private final DatabaseComponent db;
private final MessageFactory messageFactory;
private final BdfReaderFactory bdfReaderFactory;
private final BdfWriterFactory bdfWriterFactory;
private final MetadataParser metadataParser;
private final MetadataEncoder metadataEncoder;
private final CryptoComponent cryptoComponent;
private final CryptoComponent crypto;
@Inject
ClientHelperImpl(DatabaseComponent db, MessageFactory messageFactory,
BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory, MetadataParser metadataParser,
MetadataEncoder metadataEncoder, CryptoComponent cryptoComponent) {
MetadataEncoder metadataEncoder, CryptoComponent crypto) {
this.db = db;
this.messageFactory = messageFactory;
this.bdfReaderFactory = bdfReaderFactory;
this.bdfWriterFactory = bdfWriterFactory;
this.metadataParser = metadataParser;
this.metadataEncoder = metadataEncoder;
this.cryptoComponent = cryptoComponent;
this.crypto = crypto;
}
@Override
@@ -81,15 +89,36 @@ class ClientHelperImpl implements ClientHelper {
}
@Override
public Message createMessage(GroupId g, long timestamp, BdfDictionary body)
public Message createMessage(GroupId g, long timestamp, BdfList body)
throws FormatException {
return messageFactory.createMessage(g, timestamp, toByteArray(body));
}
@Override
public Message createMessage(GroupId g, long timestamp, BdfList body)
throws FormatException {
return messageFactory.createMessage(g, timestamp, toByteArray(body));
public Message createMessageForStoringMetadata(GroupId g) {
byte[] salt = new byte[SALT_LENGTH];
crypto.getSecureRandom().nextBytes(salt);
return messageFactory.createMessage(g, 0, salt);
}
@Override
public Message getMessage(MessageId m) throws DbException {
Message message;
Transaction txn = db.startTransaction(true);
try {
message = getMessage(txn, m);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return message;
}
@Override
public Message getMessage(Transaction txn, MessageId m) throws DbException {
byte[] raw = db.getRawMessage(txn, m);
if (raw == null) return null;
return messageFactory.createMessage(m, raw);
}
@Override
@@ -310,13 +339,19 @@ class ClientHelperImpl implements ClientHelper {
return toList(b, 0, b.length);
}
@Override
public BdfList toList(Message m) throws FormatException {
byte[] raw = m.getRaw();
return toList(raw, MESSAGE_HEADER_LENGTH,
raw.length - MESSAGE_HEADER_LENGTH);
}
@Override
public byte[] sign(BdfList toSign, byte[] privateKey)
throws FormatException, GeneralSecurityException {
Signature signature = cryptoComponent.getSignature();
KeyParser keyParser = cryptoComponent.getSignatureKeyParser();
PrivateKey key =
keyParser.parsePrivateKey(privateKey);
Signature signature = crypto.getSignature();
KeyParser keyParser = crypto.getSignatureKeyParser();
PrivateKey key = keyParser.parsePrivateKey(privateKey);
signature.initSign(key);
signature.update(toByteArray(toSign));
return signature.sign();
@@ -326,10 +361,10 @@ class ClientHelperImpl implements ClientHelper {
public void verifySignature(byte[] sig, byte[] publicKey, BdfList signed)
throws FormatException, GeneralSecurityException {
// Parse the public key
KeyParser keyParser = cryptoComponent.getSignatureKeyParser();
KeyParser keyParser = crypto.getSignatureKeyParser();
PublicKey key = keyParser.parsePublicKey(publicKey);
// Verify the signature
Signature signature = cryptoComponent.getSignature();
Signature signature = crypto.getSignature();
signature.initVerify(key);
signature.update(toByteArray(signed));
if (!signature.verify(sig)) {

View File

@@ -1,8 +1,8 @@
package org.briarproject.clients;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.MessageQueueManager;
import org.briarproject.api.clients.ContactGroupFactory;
import org.briarproject.api.clients.MessageQueueManager;
import org.briarproject.api.clients.QueueMessageFactory;
import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.data.BdfReaderFactory;
@@ -33,7 +33,7 @@ public class ClientsModule {
}
@Provides
ContactGroupFactory providePrivateGroupFactory(GroupFactory groupFactory,
ContactGroupFactory provideContactGroupFactory(GroupFactory groupFactory,
ClientHelper clientHelper) {
return new ContactGroupFactoryImpl(groupFactory, clientHelper);
}

View File

@@ -5,20 +5,23 @@ import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.privategroup.PrivateGroup;
import org.briarproject.api.privategroup.PrivateGroupFactory;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupFactory;
import org.briarproject.util.StringUtils;
import org.jetbrains.annotations.NotNull;
import java.security.SecureRandom;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static org.briarproject.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
@Immutable
@NotNullByDefault
class PrivateGroupFactoryImpl implements PrivateGroupFactory {
private final GroupFactory groupFactory;
@@ -37,7 +40,6 @@ class PrivateGroupFactoryImpl implements PrivateGroupFactory {
this.random = random;
}
@NotNull
@Override
public PrivateGroup createPrivateGroup(String name, Author author) {
int length = StringUtils.toUtf8(name).length;
@@ -50,7 +52,6 @@ class PrivateGroupFactoryImpl implements PrivateGroupFactory {
return createPrivateGroup(name, author, salt);
}
@NotNull
@Override
public PrivateGroup createPrivateGroup(String name, Author author,
byte[] salt) {

View File

@@ -24,14 +24,24 @@ class MessageFactoryImpl implements MessageFactory {
}
@Override
public Message createMessage(GroupId groupId, long timestamp, byte[] body) {
public Message createMessage(GroupId g, long timestamp, byte[] body) {
if (body.length > MAX_MESSAGE_BODY_LENGTH)
throw new IllegalArgumentException();
byte[] raw = new byte[MESSAGE_HEADER_LENGTH + body.length];
System.arraycopy(groupId.getBytes(), 0, raw, 0, UniqueId.LENGTH);
System.arraycopy(g.getBytes(), 0, raw, 0, UniqueId.LENGTH);
ByteUtils.writeUint64(timestamp, raw, UniqueId.LENGTH);
System.arraycopy(body, 0, raw, MESSAGE_HEADER_LENGTH, body.length);
MessageId id = new MessageId(crypto.hash(MessageId.LABEL, raw));
return new Message(id, groupId, timestamp, raw);
return new Message(id, g, timestamp, raw);
}
@Override
public Message createMessage(MessageId m, byte[] raw) {
if (raw.length < MESSAGE_HEADER_LENGTH)
throw new IllegalArgumentException();
byte[] groupId = new byte[UniqueId.LENGTH];
System.arraycopy(raw, 0, groupId, 0, UniqueId.LENGTH);
long timestamp = ByteUtils.readUint64(raw, UniqueId.LENGTH);
return new Message(m, new GroupId(groupId), timestamp, raw);
}
}

View File

@@ -274,7 +274,8 @@ class ValidationManagerImpl implements ValidationManager, Service,
MessageContext context = v.validateMessage(m, g);
storeMessageContextAsync(m, g.getClientId(), context);
} catch (InvalidMessageException e) {
if (LOG.isLoggable(INFO)) LOG.info(e.toString());
if (LOG.isLoggable(INFO))
LOG.log(INFO, e.toString(), e);
Queue<MessageId> invalidate = new LinkedList<MessageId>();
invalidate.add(m.getId());
invalidateNextMessageAsync(invalidate);