Merge branch '617-author-versioning' into 'master'

Use a versioned format for encoding authors

See merge request akwizgran/briar!661
This commit is contained in:
Torsten Grote
2018-01-16 18:36:32 +00:00
80 changed files with 1760 additions and 1982 deletions

View File

@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
@@ -93,10 +94,13 @@ public interface ClientHelper {
BdfList toList(Message m) throws FormatException; BdfList toList(Message m) throws FormatException;
BdfList toList(Author a);
byte[] sign(String label, BdfList toSign, byte[] privateKey) byte[] sign(String label, BdfList toSign, byte[] privateKey)
throws FormatException, GeneralSecurityException; throws FormatException, GeneralSecurityException;
void verifySignature(String label, byte[] sig, byte[] publicKey, void verifySignature(String label, byte[] sig, byte[] publicKey,
BdfList signed) throws FormatException, GeneralSecurityException; BdfList signed) throws FormatException, GeneralSecurityException;
Author parseAndValidateAuthor(BdfList author) throws FormatException;
} }

View File

@@ -1,11 +0,0 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.IOException;
@NotNullByDefault
public interface ObjectReader<T> {
T readObject(BdfReader r) throws IOException;
}

View File

@@ -1,11 +1,13 @@
package org.briarproject.bramble.api.identity; package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils;
import java.io.UnsupportedEncodingException;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
/** /**
* A pseudonym for a user. * A pseudonym for a user.
*/ */
@@ -17,20 +19,25 @@ public class Author {
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
} }
/**
* The current version of the author structure.
*/
public static final int FORMAT_VERSION = 0;
private final AuthorId id; private final AuthorId id;
private final int formatVersion;
private final String name; private final String name;
private final byte[] publicKey; private final byte[] publicKey;
public Author(AuthorId id, String name, byte[] publicKey) { public Author(AuthorId id, int formatVersion, String name,
int length; byte[] publicKey) {
try { int nameLength = StringUtils.toUtf8(name).length;
length = name.getBytes("UTF-8").length; if (nameLength == 0 || nameLength > MAX_AUTHOR_NAME_LENGTH)
} catch (UnsupportedEncodingException e) { throw new IllegalArgumentException();
throw new RuntimeException(e); if (publicKey.length == 0 || publicKey.length > MAX_PUBLIC_KEY_LENGTH)
}
if (length == 0 || length > AuthorConstants.MAX_AUTHOR_NAME_LENGTH)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
this.id = id; this.id = id;
this.formatVersion = formatVersion;
this.name = name; this.name = name;
this.publicKey = publicKey; this.publicKey = publicKey;
} }
@@ -42,6 +49,13 @@ public class Author {
return id; return id;
} }
/**
* Returns the version of the author structure used to create the author.
*/
public int getFormatVersion() {
return formatVersion;
}
/** /**
* Returns the author's name. * Returns the author's name.
*/ */

View File

@@ -5,8 +5,27 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault @NotNullByDefault
public interface AuthorFactory { public interface AuthorFactory {
/**
* Creates an author with the current format version and the given name and
* public key.
*/
Author createAuthor(String name, byte[] publicKey); Author createAuthor(String name, byte[] publicKey);
/**
* Creates an author with the given format version, name and public key.
*/
Author createAuthor(int formatVersion, String name, byte[] publicKey);
/**
* Creates a local author with the current format version and the given
* name and keys.
*/
LocalAuthor createLocalAuthor(String name, byte[] publicKey, LocalAuthor createLocalAuthor(String name, byte[] publicKey,
byte[] privateKey); byte[] privateKey);
/**
* Creates a local author with the given format version, name and keys.
*/
LocalAuthor createLocalAuthor(int formatVersion, String name,
byte[] publicKey, byte[] privateKey);
} }

View File

@@ -14,9 +14,9 @@ public class LocalAuthor extends Author {
private final byte[] privateKey; private final byte[] privateKey;
private final long created; private final long created;
public LocalAuthor(AuthorId id, String name, byte[] publicKey, public LocalAuthor(AuthorId id, int formatVersion, String name,
byte[] privateKey, long created) { byte[] publicKey, byte[] privateKey, long created) {
super(id, name, publicKey); super(id, formatVersion, name, publicKey);
this.privateKey = privateKey; this.privateKey = privateKey;
this.created = created; this.created = created;
} }

View File

@@ -20,6 +20,7 @@ import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
@@ -67,7 +68,8 @@ public class TestUtils {
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH); byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
byte[] privateKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH); byte[] privateKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
long created = System.currentTimeMillis(); long created = System.currentTimeMillis();
return new LocalAuthor(id, name, publicKey, privateKey, created); return new LocalAuthor(id, FORMAT_VERSION, name, publicKey, privateKey,
created);
} }
public static Author getAuthor() { public static Author getAuthor() {
@@ -78,7 +80,7 @@ public class TestUtils {
AuthorId id = new AuthorId(getRandomId()); AuthorId id = new AuthorId(getRandomId());
String name = getRandomString(nameLength); String name = getRandomString(nameLength);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH); byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
return new Author(id, name, publicKey); return new Author(id, FORMAT_VERSION, name, publicKey);
} }
public static Group getGroup(ClientId clientId) { public static Group getGroup(ClientId clientId) {

View File

@@ -15,6 +15,8 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
@@ -32,7 +34,12 @@ import java.util.Map.Entry;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
@@ -51,12 +58,14 @@ class ClientHelperImpl implements ClientHelper {
private final MetadataParser metadataParser; private final MetadataParser metadataParser;
private final MetadataEncoder metadataEncoder; private final MetadataEncoder metadataEncoder;
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final AuthorFactory authorFactory;
@Inject @Inject
ClientHelperImpl(DatabaseComponent db, MessageFactory messageFactory, ClientHelperImpl(DatabaseComponent db, MessageFactory messageFactory,
BdfReaderFactory bdfReaderFactory, BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory, MetadataParser metadataParser, BdfWriterFactory bdfWriterFactory, MetadataParser metadataParser,
MetadataEncoder metadataEncoder, CryptoComponent crypto) { MetadataEncoder metadataEncoder, CryptoComponent crypto,
AuthorFactory authorFactory) {
this.db = db; this.db = db;
this.messageFactory = messageFactory; this.messageFactory = messageFactory;
this.bdfReaderFactory = bdfReaderFactory; this.bdfReaderFactory = bdfReaderFactory;
@@ -64,6 +73,7 @@ class ClientHelperImpl implements ClientHelper {
this.metadataParser = metadataParser; this.metadataParser = metadataParser;
this.metadataEncoder = metadataEncoder; this.metadataEncoder = metadataEncoder;
this.crypto = crypto; this.crypto = crypto;
this.authorFactory = authorFactory;
} }
@Override @Override
@@ -341,6 +351,11 @@ class ClientHelperImpl implements ClientHelper {
raw.length - MESSAGE_HEADER_LENGTH); raw.length - MESSAGE_HEADER_LENGTH);
} }
@Override
public BdfList toList(Author a) {
return BdfList.of(a.getFormatVersion(), a.getName(), a.getPublicKey());
}
@Override @Override
public byte[] sign(String label, BdfList toSign, byte[] privateKey) public byte[] sign(String label, BdfList toSign, byte[] privateKey)
throws FormatException, GeneralSecurityException { throws FormatException, GeneralSecurityException {
@@ -355,4 +370,16 @@ class ClientHelperImpl implements ClientHelper {
} }
} }
@Override
public Author parseAndValidateAuthor(BdfList author)
throws FormatException {
checkSize(author, 3);
int formatVersion = author.getLong(0).intValue();
if (formatVersion != FORMAT_VERSION) throw new FormatException();
String name = author.getString(1);
checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH);
byte[] publicKey = author.getRaw(2);
checkLength(publicKey, 1, MAX_PUBLIC_KEY_LENGTH);
return authorFactory.createAuthor(formatVersion, name, publicKey);
}
} }

View File

@@ -2,14 +2,6 @@ package org.briarproject.bramble.client;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.client.ContactGroupFactory; import org.briarproject.bramble.api.client.ContactGroupFactory;
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.data.MetadataEncoder;
import org.briarproject.bramble.api.data.MetadataParser;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.sync.GroupFactory;
import org.briarproject.bramble.api.sync.MessageFactory;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
@@ -18,19 +10,14 @@ import dagger.Provides;
public class ClientModule { public class ClientModule {
@Provides @Provides
ClientHelper provideClientHelper(DatabaseComponent db, ClientHelper provideClientHelper(ClientHelperImpl clientHelper) {
MessageFactory messageFactory, BdfReaderFactory bdfReaderFactory, return clientHelper;
BdfWriterFactory bdfWriterFactory, MetadataParser metadataParser,
MetadataEncoder metadataEncoder, CryptoComponent cryptoComponent) {
return new ClientHelperImpl(db, messageFactory, bdfReaderFactory,
bdfWriterFactory, metadataParser, metadataEncoder,
cryptoComponent);
} }
@Provides @Provides
ContactGroupFactory provideContactGroupFactory(GroupFactory groupFactory, ContactGroupFactory provideContactGroupFactory(
ClientHelper clientHelper) { ContactGroupFactoryImpl contactGroupFactory) {
return new ContactGroupFactoryImpl(groupFactory, clientHelper); return contactGroupFactory;
} }
} }

View File

@@ -43,6 +43,7 @@ import javax.inject.Inject;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
@@ -227,6 +228,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
// Write the name, public key and signature // Write the name, public key and signature
w.writeListStart(); w.writeListStart();
w.writeLong(localAuthor.getFormatVersion());
w.writeString(localAuthor.getName()); w.writeString(localAuthor.getName());
w.writeRaw(localAuthor.getPublicKey()); w.writeRaw(localAuthor.getPublicKey());
w.writeRaw(sig); w.writeRaw(sig);
@@ -236,11 +238,16 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
private Author receivePseudonym(BdfReader r, byte[] nonce) private Author receivePseudonym(BdfReader r, byte[] nonce)
throws GeneralSecurityException, IOException { throws GeneralSecurityException, IOException {
// Read the name, public key and signature // Read the format version, name, public key and signature
r.readListStart(); r.readListStart();
int formatVersion = (int) r.readLong();
if (formatVersion != FORMAT_VERSION) throw new FormatException();
String name = r.readString(MAX_AUTHOR_NAME_LENGTH); String name = r.readString(MAX_AUTHOR_NAME_LENGTH);
if (name.isEmpty()) throw new FormatException();
byte[] publicKey = r.readRaw(MAX_PUBLIC_KEY_LENGTH); byte[] publicKey = r.readRaw(MAX_PUBLIC_KEY_LENGTH);
if (publicKey.length == 0) throw new FormatException();
byte[] sig = r.readRaw(MAX_SIGNATURE_LENGTH); byte[] sig = r.readRaw(MAX_SIGNATURE_LENGTH);
if (sig.length == 0) throw new FormatException();
r.readListEnd(); r.readListEnd();
LOG.info("Received pseudonym"); LOG.info("Received pseudonym");
// Verify the signature // Verify the signature
@@ -249,7 +256,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
LOG.info("Invalid signature"); LOG.info("Invalid signature");
throw new GeneralSecurityException(); throw new GeneralSecurityException();
} }
return authorFactory.createAuthor(name, publicKey); return authorFactory.createAuthor(formatVersion, name, publicKey);
} }
private void sendTimestamp(BdfWriter w, long timestamp) private void sendTimestamp(BdfWriter w, long timestamp)

View File

@@ -68,8 +68,8 @@ import static org.briarproject.bramble.db.ExponentialBackoff.calculateExpiry;
@NotNullByDefault @NotNullByDefault
abstract class JdbcDatabase implements Database<Connection> { abstract class JdbcDatabase implements Database<Connection> {
private static final int SCHEMA_VERSION = 32; private static final int SCHEMA_VERSION = 33;
private static final int MIN_SCHEMA_VERSION = 32; private static final int MIN_SCHEMA_VERSION = 33;
private static final String CREATE_SETTINGS = private static final String CREATE_SETTINGS =
"CREATE TABLE settings" "CREATE TABLE settings"
@@ -81,6 +81,7 @@ abstract class JdbcDatabase implements Database<Connection> {
private static final String CREATE_LOCAL_AUTHORS = private static final String CREATE_LOCAL_AUTHORS =
"CREATE TABLE localAuthors" "CREATE TABLE localAuthors"
+ " (authorId _HASH NOT NULL," + " (authorId _HASH NOT NULL,"
+ " formatVersion INT NOT NULL,"
+ " name _STRING NOT NULL," + " name _STRING NOT NULL,"
+ " publicKey _BINARY NOT NULL," + " publicKey _BINARY NOT NULL,"
+ " privateKey _BINARY NOT NULL," + " privateKey _BINARY NOT NULL,"
@@ -91,6 +92,7 @@ abstract class JdbcDatabase implements Database<Connection> {
"CREATE TABLE contacts" "CREATE TABLE contacts"
+ " (contactId _COUNTER," + " (contactId _COUNTER,"
+ " authorId _HASH NOT NULL," + " authorId _HASH NOT NULL,"
+ " formatVersion INT NOT NULL,"
+ " name _STRING NOT NULL," + " name _STRING NOT NULL,"
+ " publicKey _BINARY NOT NULL," + " publicKey _BINARY NOT NULL,"
+ " localAuthorId _HASH NOT NULL," + " localAuthorId _HASH NOT NULL,"
@@ -513,16 +515,18 @@ abstract class JdbcDatabase implements Database<Connection> {
try { try {
// Create a contact row // Create a contact row
String sql = "INSERT INTO contacts" String sql = "INSERT INTO contacts"
+ " (authorId, name, publicKey, localAuthorId," + " (authorId, formatVersion, name, publicKey,"
+ " localAuthorId,"
+ " verified, active)" + " verified, active)"
+ " VALUES (?, ?, ?, ?, ?, ?)"; + " VALUES (?, ?, ?, ?, ?, ?, ?)";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, remote.getId().getBytes()); ps.setBytes(1, remote.getId().getBytes());
ps.setString(2, remote.getName()); ps.setInt(2, remote.getFormatVersion());
ps.setBytes(3, remote.getPublicKey()); ps.setString(3, remote.getName());
ps.setBytes(4, local.getBytes()); ps.setBytes(4, remote.getPublicKey());
ps.setBoolean(5, verified); ps.setBytes(5, local.getBytes());
ps.setBoolean(6, active); ps.setBoolean(6, verified);
ps.setBoolean(7, active);
int affected = ps.executeUpdate(); int affected = ps.executeUpdate();
if (affected != 1) throw new DbStateException(); if (affected != 1) throw new DbStateException();
ps.close(); ps.close();
@@ -590,14 +594,16 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
String sql = "INSERT INTO localAuthors" String sql = "INSERT INTO localAuthors"
+ " (authorId, name, publicKey, privateKey, created)" + " (authorId, formatVersion, name, publicKey,"
+ " VALUES (?, ?, ?, ?, ?)"; + " privateKey, created)"
+ " VALUES (?, ?, ?, ?, ?, ?)";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, a.getId().getBytes()); ps.setBytes(1, a.getId().getBytes());
ps.setString(2, a.getName()); ps.setInt(2, a.getFormatVersion());
ps.setBytes(3, a.getPublicKey()); ps.setString(3, a.getName());
ps.setBytes(4, a.getPrivateKey()); ps.setBytes(4, a.getPublicKey());
ps.setLong(5, a.getTimeCreated()); ps.setBytes(5, a.getPrivateKey());
ps.setLong(6, a.getTimeCreated());
int affected = ps.executeUpdate(); int affected = ps.executeUpdate();
if (affected != 1) throw new DbStateException(); if (affected != 1) throw new DbStateException();
ps.close(); ps.close();
@@ -1013,7 +1019,7 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
String sql = "SELECT authorId, name, publicKey," String sql = "SELECT authorId, formatVersion, name, publicKey,"
+ " localAuthorId, verified, active" + " localAuthorId, verified, active"
+ " FROM contacts" + " FROM contacts"
+ " WHERE contactId = ?"; + " WHERE contactId = ?";
@@ -1022,14 +1028,16 @@ abstract class JdbcDatabase implements Database<Connection> {
rs = ps.executeQuery(); rs = ps.executeQuery();
if (!rs.next()) throw new DbStateException(); if (!rs.next()) throw new DbStateException();
AuthorId authorId = new AuthorId(rs.getBytes(1)); AuthorId authorId = new AuthorId(rs.getBytes(1));
String name = rs.getString(2); int formatVersion = rs.getInt(2);
byte[] publicKey = rs.getBytes(3); String name = rs.getString(3);
AuthorId localAuthorId = new AuthorId(rs.getBytes(4)); byte[] publicKey = rs.getBytes(4);
boolean verified = rs.getBoolean(5); AuthorId localAuthorId = new AuthorId(rs.getBytes(5));
boolean active = rs.getBoolean(6); boolean verified = rs.getBoolean(6);
boolean active = rs.getBoolean(7);
rs.close(); rs.close();
ps.close(); ps.close();
Author author = new Author(authorId, name, publicKey); Author author =
new Author(authorId, formatVersion, name, publicKey);
return new Contact(c, author, localAuthorId, verified, active); return new Contact(c, author, localAuthorId, verified, active);
} catch (SQLException e) { } catch (SQLException e) {
tryToClose(rs); tryToClose(rs);
@@ -1044,8 +1052,8 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
String sql = "SELECT contactId, authorId, name, publicKey," String sql = "SELECT contactId, authorId, formatVersion, name,"
+ " localAuthorId, verified, active" + " publicKey, localAuthorId, verified, active"
+ " FROM contacts"; + " FROM contacts";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
rs = ps.executeQuery(); rs = ps.executeQuery();
@@ -1053,12 +1061,14 @@ abstract class JdbcDatabase implements Database<Connection> {
while (rs.next()) { while (rs.next()) {
ContactId contactId = new ContactId(rs.getInt(1)); ContactId contactId = new ContactId(rs.getInt(1));
AuthorId authorId = new AuthorId(rs.getBytes(2)); AuthorId authorId = new AuthorId(rs.getBytes(2));
String name = rs.getString(3); int formatVersion = rs.getInt(3);
byte[] publicKey = rs.getBytes(4); String name = rs.getString(4);
Author author = new Author(authorId, name, publicKey); byte[] publicKey = rs.getBytes(5);
AuthorId localAuthorId = new AuthorId(rs.getBytes(5)); Author author =
boolean verified = rs.getBoolean(6); new Author(authorId, formatVersion, name, publicKey);
boolean active = rs.getBoolean(7); AuthorId localAuthorId = new AuthorId(rs.getBytes(6));
boolean verified = rs.getBoolean(7);
boolean active = rs.getBoolean(8);
contacts.add(new Contact(contactId, author, localAuthorId, contacts.add(new Contact(contactId, author, localAuthorId,
verified, active)); verified, active));
} }
@@ -1101,7 +1111,7 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
String sql = "SELECT contactId, name, publicKey," String sql = "SELECT contactId, formatVersion, name, publicKey,"
+ " localAuthorId, verified, active" + " localAuthorId, verified, active"
+ " FROM contacts" + " FROM contacts"
+ " WHERE authorId = ?"; + " WHERE authorId = ?";
@@ -1111,12 +1121,14 @@ abstract class JdbcDatabase implements Database<Connection> {
List<Contact> contacts = new ArrayList<>(); List<Contact> contacts = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
ContactId c = new ContactId(rs.getInt(1)); ContactId c = new ContactId(rs.getInt(1));
String name = rs.getString(2); int formatVersion = rs.getInt(2);
byte[] publicKey = rs.getBytes(3); String name = rs.getString(3);
AuthorId localAuthorId = new AuthorId(rs.getBytes(4)); byte[] publicKey = rs.getBytes(4);
boolean verified = rs.getBoolean(5); AuthorId localAuthorId = new AuthorId(rs.getBytes(5));
boolean active = rs.getBoolean(6); boolean verified = rs.getBoolean(6);
Author author = new Author(remote, name, publicKey); boolean active = rs.getBoolean(7);
Author author =
new Author(remote, formatVersion, name, publicKey);
contacts.add(new Contact(c, author, localAuthorId, verified, contacts.add(new Contact(c, author, localAuthorId, verified,
active)); active));
} }
@@ -1235,19 +1247,21 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
String sql = "SELECT name, publicKey, privateKey, created" String sql = "SELECT formatVersion, name, publicKey,"
+ " privateKey, created"
+ " FROM localAuthors" + " FROM localAuthors"
+ " WHERE authorId = ?"; + " WHERE authorId = ?";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, a.getBytes()); ps.setBytes(1, a.getBytes());
rs = ps.executeQuery(); rs = ps.executeQuery();
if (!rs.next()) throw new DbStateException(); if (!rs.next()) throw new DbStateException();
String name = rs.getString(1); int formatVersion = rs.getInt(1);
byte[] publicKey = rs.getBytes(2); String name = rs.getString(2);
byte[] privateKey = rs.getBytes(3); byte[] publicKey = rs.getBytes(3);
long created = rs.getLong(4); byte[] privateKey = rs.getBytes(4);
LocalAuthor localAuthor = new LocalAuthor(a, name, publicKey, long created = rs.getLong(5);
privateKey, created); LocalAuthor localAuthor = new LocalAuthor(a, formatVersion, name,
publicKey, privateKey, created);
if (rs.next()) throw new DbStateException(); if (rs.next()) throw new DbStateException();
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1265,19 +1279,21 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
String sql = "SELECT authorId, name, publicKey, privateKey, created" String sql = "SELECT authorId, formatVersion, name, publicKey,"
+ " privateKey, created"
+ " FROM localAuthors"; + " FROM localAuthors";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
rs = ps.executeQuery(); rs = ps.executeQuery();
List<LocalAuthor> authors = new ArrayList<>(); List<LocalAuthor> authors = new ArrayList<>();
while (rs.next()) { while (rs.next()) {
AuthorId authorId = new AuthorId(rs.getBytes(1)); AuthorId authorId = new AuthorId(rs.getBytes(1));
String name = rs.getString(2); int formatVersion = rs.getInt(2);
byte[] publicKey = rs.getBytes(3); String name = rs.getString(3);
byte[] privateKey = rs.getBytes(4); byte[] publicKey = rs.getBytes(4);
long created = rs.getLong(5); byte[] privateKey = rs.getBytes(5);
authors.add(new LocalAuthor(authorId, name, publicKey, long created = rs.getLong(6);
privateKey, created)); authors.add(new LocalAuthor(authorId, formatVersion, name,
publicKey, privateKey, created));
} }
rs.close(); rs.close();
ps.close(); ps.close();

View File

@@ -1,61 +1,65 @@
package org.briarproject.bramble.identity; package org.briarproject.bramble.identity;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.data.BdfWriter;
import org.briarproject.bramble.api.data.BdfWriterFactory;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.ByteUtils;
import java.io.ByteArrayOutputStream; import org.briarproject.bramble.util.StringUtils;
import java.io.IOException;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
import static org.briarproject.bramble.api.identity.AuthorId.LABEL;
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
class AuthorFactoryImpl implements AuthorFactory { class AuthorFactoryImpl implements AuthorFactory {
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final BdfWriterFactory bdfWriterFactory;
private final Clock clock; private final Clock clock;
@Inject @Inject
AuthorFactoryImpl(CryptoComponent crypto, BdfWriterFactory bdfWriterFactory, AuthorFactoryImpl(CryptoComponent crypto, Clock clock) {
Clock clock) {
this.crypto = crypto; this.crypto = crypto;
this.bdfWriterFactory = bdfWriterFactory;
this.clock = clock; this.clock = clock;
} }
@Override @Override
public Author createAuthor(String name, byte[] publicKey) { public Author createAuthor(String name, byte[] publicKey) {
return new Author(getId(name, publicKey), name, publicKey); return createAuthor(FORMAT_VERSION, name, publicKey);
}
@Override
public Author createAuthor(int formatVersion, String name,
byte[] publicKey) {
AuthorId id = getId(formatVersion, name, publicKey);
return new Author(id, formatVersion, name, publicKey);
} }
@Override @Override
public LocalAuthor createLocalAuthor(String name, byte[] publicKey, public LocalAuthor createLocalAuthor(String name, byte[] publicKey,
byte[] privateKey) { byte[] privateKey) {
return new LocalAuthor(getId(name, publicKey), name, publicKey, return createLocalAuthor(FORMAT_VERSION, name, publicKey, privateKey);
privateKey, clock.currentTimeMillis());
} }
private AuthorId getId(String name, byte[] publicKey) { @Override
ByteArrayOutputStream out = new ByteArrayOutputStream(); public LocalAuthor createLocalAuthor(int formatVersion, String name,
BdfWriter w = bdfWriterFactory.createWriter(out); byte[] publicKey, byte[] privateKey) {
try { AuthorId id = getId(formatVersion, name, publicKey);
w.writeListStart(); return new LocalAuthor(id, formatVersion, name, publicKey, privateKey,
w.writeString(name); clock.currentTimeMillis());
w.writeRaw(publicKey); }
w.writeListEnd();
} catch (IOException e) { private AuthorId getId(int formatVersion, String name, byte[] publicKey) {
// Shouldn't happen with ByteArrayOutputStream byte[] formatVersionBytes = new byte[INT_32_BYTES];
throw new RuntimeException(e); ByteUtils.writeUint32(formatVersion, formatVersionBytes, 0);
} return new AuthorId(crypto.hash(LABEL, formatVersionBytes,
return new AuthorId(crypto.hash(AuthorId.LABEL, out.toByteArray())); StringUtils.toUtf8(name), publicKey));
} }
} }

View File

@@ -1,36 +0,0 @@
package org.briarproject.bramble.identity;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.data.BdfReader;
import org.briarproject.bramble.api.data.ObjectReader;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.IOException;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
@Immutable
@NotNullByDefault
class AuthorReader implements ObjectReader<Author> {
private final AuthorFactory authorFactory;
AuthorReader(AuthorFactory authorFactory) {
this.authorFactory = authorFactory;
}
@Override
public Author readObject(BdfReader r) throws IOException {
r.readListStart();
String name = r.readString(MAX_AUTHOR_NAME_LENGTH);
if (name.length() == 0) throw new FormatException();
byte[] publicKey = r.readRaw(MAX_PUBLIC_KEY_LENGTH);
r.readListEnd();
return authorFactory.createAuthor(name, publicKey);
}
}

View File

@@ -1,13 +1,7 @@
package org.briarproject.bramble.identity; package org.briarproject.bramble.identity;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.data.BdfWriterFactory;
import org.briarproject.bramble.api.data.ObjectReader;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.system.Clock;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -24,19 +18,14 @@ public class IdentityModule {
} }
@Provides @Provides
AuthorFactory provideAuthorFactory(CryptoComponent crypto, AuthorFactory provideAuthorFactory(AuthorFactoryImpl authorFactory) {
BdfWriterFactory bdfWriterFactory, Clock clock) { return authorFactory;
return new AuthorFactoryImpl(crypto, bdfWriterFactory, clock);
} }
@Provides @Provides
@Singleton @Singleton
IdentityManager provideIdentityModule(DatabaseComponent db) { IdentityManager provideIdentityManager(
return new IdentityManagerImpl(db); IdentityManagerImpl identityManager) {
} return identityManager;
@Provides
ObjectReader<Author> provideAuthorReader(AuthorFactory authorFactory) {
return new AuthorReader(authorFactory);
} }
} }

View File

@@ -15,6 +15,8 @@ import org.briarproject.bramble.api.data.MetadataParser;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageFactory; import org.briarproject.bramble.api.sync.MessageFactory;
@@ -31,9 +33,14 @@ import java.security.GeneralSecurityException;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Random;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
@@ -54,7 +61,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
context.mock(MetadataEncoder.class); context.mock(MetadataEncoder.class);
private final CryptoComponent cryptoComponent = private final CryptoComponent cryptoComponent =
context.mock(CryptoComponent.class); context.mock(CryptoComponent.class);
private final ClientHelper clientHelper; private final AuthorFactory authorFactory =
context.mock(AuthorFactory.class);
private final GroupId groupId = new GroupId(getRandomId()); private final GroupId groupId = new GroupId(getRandomId());
private final BdfDictionary dictionary = new BdfDictionary(); private final BdfDictionary dictionary = new BdfDictionary();
@@ -66,17 +74,15 @@ public class ClientHelperImplTest extends BrambleTestCase {
private final Metadata metadata = new Metadata(); private final Metadata metadata = new Metadata();
private final BdfList list = BdfList.of("Sign this!", getRandomBytes(42)); private final BdfList list = BdfList.of("Sign this!", getRandomBytes(42));
private final String label = StringUtils.getRandomString(5); private final String label = StringUtils.getRandomString(5);
private final Author author = getAuthor();
public ClientHelperImplTest() { private final ClientHelper clientHelper = new ClientHelperImpl(db,
clientHelper = messageFactory, bdfReaderFactory, bdfWriterFactory, metadataParser,
new ClientHelperImpl(db, messageFactory, bdfReaderFactory, metadataEncoder, cryptoComponent, authorFactory);
bdfWriterFactory, metadataParser, metadataEncoder,
cryptoComponent);
}
@Test @Test
public void testAddLocalMessage() throws Exception { public void testAddLocalMessage() throws Exception {
boolean shared = true; boolean shared = new Random().nextBoolean();
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -180,8 +186,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
oneOf(db).endTransaction(txn); oneOf(db).endTransaction(txn);
}}); }});
assertEquals(map, assertEquals(map, clientHelper.getMessageMetadataAsDictionary(groupId));
clientHelper.getMessageMetadataAsDictionary(groupId));
context.assertIsSatisfied(); context.assertIsSatisfied();
} }
@@ -318,8 +323,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
}}); }});
try { try {
clientHelper clientHelper.verifySignature(label, rawMessage, publicKey, list);
.verifySignature(label, rawMessage, publicKey, list);
fail(); fail();
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
// expected // expected
@@ -327,6 +331,166 @@ public class ClientHelperImplTest extends BrambleTestCase {
} }
} }
@Test
public void testParsesAndEncodesAuthor() throws Exception {
context.checking(new Expectations() {{
oneOf(authorFactory).createAuthor(author.getFormatVersion(),
author.getName(), author.getPublicKey());
will(returnValue(author));
}});
BdfList authorList = clientHelper.toList(author);
assertEquals(author, clientHelper.parseAndValidateAuthor(authorList));
}
@Test
public void testAcceptsValidAuthor() throws Exception {
BdfList authorList = BdfList.of(
author.getFormatVersion(),
author.getName(),
author.getPublicKey()
);
context.checking(new Expectations() {{
oneOf(authorFactory).createAuthor(author.getFormatVersion(),
author.getName(), author.getPublicKey());
will(returnValue(author));
}});
assertEquals(author, clientHelper.parseAndValidateAuthor(authorList));
}
@Test(expected = FormatException.class)
public void testRejectsTooShortAuthor() throws Exception {
BdfList invalidAuthor = BdfList.of(
author.getFormatVersion(),
author.getName()
);
clientHelper.parseAndValidateAuthor(invalidAuthor);
}
@Test(expected = FormatException.class)
public void testRejectsTooLongAuthor() throws Exception {
BdfList invalidAuthor = BdfList.of(
author.getFormatVersion(),
author.getName(),
author.getPublicKey(),
"foo"
);
clientHelper.parseAndValidateAuthor(invalidAuthor);
}
@Test(expected = FormatException.class)
public void testRejectsAuthorWithNullFormatVersion() throws Exception {
BdfList invalidAuthor = BdfList.of(
null,
author.getName(),
author.getPublicKey()
);
clientHelper.parseAndValidateAuthor(invalidAuthor);
}
@Test(expected = FormatException.class)
public void testRejectsAuthorWithNonIntegerFormatVersion()
throws Exception {
BdfList invalidAuthor = BdfList.of(
"foo",
author.getName(),
author.getPublicKey()
);
clientHelper.parseAndValidateAuthor(invalidAuthor);
}
@Test(expected = FormatException.class)
public void testRejectsAuthorWithUnknownFormatVersion() throws Exception {
BdfList invalidAuthor = BdfList.of(
author.getFormatVersion() + 1,
author.getName(),
author.getPublicKey()
);
clientHelper.parseAndValidateAuthor(invalidAuthor);
}
@Test(expected = FormatException.class)
public void testRejectsAuthorWithTooShortName() throws Exception {
BdfList invalidAuthor = BdfList.of(
author.getFormatVersion(),
"",
author.getPublicKey()
);
clientHelper.parseAndValidateAuthor(invalidAuthor);
}
@Test(expected = FormatException.class)
public void testRejectsAuthorWithTooLongName() throws Exception {
BdfList invalidAuthor = BdfList.of(
author.getFormatVersion(),
getRandomString(MAX_AUTHOR_NAME_LENGTH + 1),
author.getPublicKey()
);
clientHelper.parseAndValidateAuthor(invalidAuthor);
}
@Test(expected = FormatException.class)
public void testRejectsAuthorWithNullName() throws Exception {
BdfList invalidAuthor = BdfList.of(
author.getFormatVersion(),
null,
author.getPublicKey()
);
clientHelper.parseAndValidateAuthor(invalidAuthor);
}
@Test(expected = FormatException.class)
public void testRejectsAuthorWithNonStringName() throws Exception {
BdfList invalidAuthor = BdfList.of(
author.getFormatVersion(),
getRandomBytes(5),
author.getPublicKey()
);
clientHelper.parseAndValidateAuthor(invalidAuthor);
}
@Test(expected = FormatException.class)
public void testRejectsAuthorWithTooShortPublicKey() throws Exception {
BdfList invalidAuthor = BdfList.of(
author.getFormatVersion(),
author.getName(),
new byte[0]
);
clientHelper.parseAndValidateAuthor(invalidAuthor);
}
@Test(expected = FormatException.class)
public void testRejectsAuthorWithTooLongPublicKey() throws Exception {
BdfList invalidAuthor = BdfList.of(
author.getFormatVersion(),
author.getName(),
getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1)
);
clientHelper.parseAndValidateAuthor(invalidAuthor);
}
@Test(expected = FormatException.class)
public void testRejectsAuthorWithNullPublicKey() throws Exception {
BdfList invalidAuthor = BdfList.of(
author.getFormatVersion(),
author.getName(),
null
);
clientHelper.parseAndValidateAuthor(invalidAuthor);
}
@Test(expected = FormatException.class)
public void testRejectsAuthorWithNonRawPublicKey() throws Exception {
BdfList invalidAuthor = BdfList.of(
author.getFormatVersion(),
author.getName(),
"foo"
);
clientHelper.parseAndValidateAuthor(invalidAuthor);
}
private byte[] expectToByteArray(BdfList list) throws Exception { private byte[] expectToByteArray(BdfList list) throws Exception {
BdfWriter bdfWriter = context.mock(BdfWriter.class); BdfWriter bdfWriter = context.mock(BdfWriter.class);
@@ -352,5 +516,4 @@ public class ClientHelperImplTest extends BrambleTestCase {
will(returnValue(eof)); will(returnValue(eof));
}}); }});
} }
} }

View File

@@ -18,8 +18,9 @@ import org.junit.Test;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Random;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@@ -32,9 +33,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
private final KeyManager keyManager = context.mock(KeyManager.class); private final KeyManager keyManager = context.mock(KeyManager.class);
private final ContactManager contactManager; private final ContactManager contactManager;
private final ContactId contactId = new ContactId(42); private final ContactId contactId = new ContactId(42);
private final Author remote = private final Author remote = getAuthor();
new Author(new AuthorId(getRandomId()), "remote",
getRandomBytes(42));
private final AuthorId local = new AuthorId(getRandomId()); private final AuthorId local = new AuthorId(getRandomId());
private final boolean verified = false, active = true; private final boolean verified = false, active = true;
private final Contact contact = private final Contact contact =
@@ -47,8 +46,8 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testAddContact() throws Exception { public void testAddContact() throws Exception {
SecretKey master = getSecretKey(); SecretKey master = getSecretKey();
long timestamp = 42; long timestamp = System.currentTimeMillis();
boolean alice = true; boolean alice = new Random().nextBoolean();
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{ context.checking(new Expectations() {{

View File

@@ -17,7 +17,6 @@ import org.briarproject.bramble.api.db.NoSuchTransportException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.identity.event.LocalAuthorAddedEvent; import org.briarproject.bramble.api.identity.event.LocalAuthorAddedEvent;
import org.briarproject.bramble.api.identity.event.LocalAuthorRemovedEvent; import org.briarproject.bramble.api.identity.event.LocalAuthorRemovedEvent;
@@ -49,7 +48,6 @@ import org.briarproject.bramble.api.transport.OutgoingKeys;
import org.briarproject.bramble.api.transport.TransportKeys; import org.briarproject.bramble.api.transport.TransportKeys;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.TestUtils; import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.junit.Test; import org.junit.Test;
@@ -59,7 +57,6 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
@@ -68,6 +65,9 @@ import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERE
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN; import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
import static org.briarproject.bramble.api.transport.TransportConstants.REORDERING_WINDOW_SIZE; import static org.briarproject.bramble.api.transport.TransportConstants.REORDERING_WINDOW_SIZE;
import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES; import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
@@ -85,9 +85,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
private final ClientId clientId; private final ClientId clientId;
private final GroupId groupId; private final GroupId groupId;
private final Group group; private final Group group;
private final AuthorId authorId;
private final Author author; private final Author author;
private final AuthorId localAuthorId;
private final LocalAuthor localAuthor; private final LocalAuthor localAuthor;
private final MessageId messageId, messageId1; private final MessageId messageId, messageId1;
private final int size; private final int size;
@@ -100,18 +98,15 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
private final Contact contact; private final Contact contact;
public DatabaseComponentImplTest() { public DatabaseComponentImplTest() {
clientId = new ClientId(StringUtils.getRandomString(5)); clientId = new ClientId(getRandomString(123));
groupId = new GroupId(TestUtils.getRandomId()); groupId = new GroupId(TestUtils.getRandomId());
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH]; byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
group = new Group(groupId, clientId, descriptor); group = new Group(groupId, clientId, descriptor);
authorId = new AuthorId(TestUtils.getRandomId()); author = getAuthor();
author = new Author(authorId, "Alice", new byte[MAX_PUBLIC_KEY_LENGTH]); localAuthor = getLocalAuthor();
localAuthorId = new AuthorId(TestUtils.getRandomId());
long timestamp = System.currentTimeMillis();
localAuthor = new LocalAuthor(localAuthorId, "Bob",
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp);
messageId = new MessageId(TestUtils.getRandomId()); messageId = new MessageId(TestUtils.getRandomId());
messageId1 = new MessageId(TestUtils.getRandomId()); messageId1 = new MessageId(TestUtils.getRandomId());
long timestamp = System.currentTimeMillis();
size = 1234; size = 1234;
raw = new byte[size]; raw = new byte[size];
message = new Message(messageId, groupId, timestamp, raw); message = new Message(messageId, groupId, timestamp, raw);
@@ -120,7 +115,8 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
transportId = new TransportId("id"); transportId = new TransportId("id");
maxLatency = Integer.MAX_VALUE; maxLatency = Integer.MAX_VALUE;
contactId = new ContactId(234); contactId = new ContactId(234);
contact = new Contact(contactId, author, localAuthorId, true, true); contact = new Contact(contactId, author, localAuthor.getId(),
true, true);
} }
private DatabaseComponent createDatabaseComponent(Database<Object> database, private DatabaseComponent createDatabaseComponent(Database<Object> database,
@@ -142,18 +138,20 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
// registerLocalAuthor() // registerLocalAuthor()
oneOf(database).containsLocalAuthor(txn, localAuthorId); oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
will(returnValue(false)); will(returnValue(false));
oneOf(database).addLocalAuthor(txn, localAuthor); oneOf(database).addLocalAuthor(txn, localAuthor);
oneOf(eventBus).broadcast(with(any(LocalAuthorAddedEvent.class))); oneOf(eventBus).broadcast(with(any(LocalAuthorAddedEvent.class)));
// addContact() // addContact()
oneOf(database).containsLocalAuthor(txn, localAuthorId); oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
will(returnValue(true)); will(returnValue(true));
oneOf(database).containsLocalAuthor(txn, authorId); oneOf(database).containsLocalAuthor(txn, author.getId());
will(returnValue(false)); will(returnValue(false));
oneOf(database).containsContact(txn, authorId, localAuthorId); oneOf(database).containsContact(txn, author.getId(),
localAuthor.getId());
will(returnValue(false)); will(returnValue(false));
oneOf(database).addContact(txn, author, localAuthorId, true, true); oneOf(database).addContact(txn, author, localAuthor.getId(),
true, true);
will(returnValue(contactId)); will(returnValue(contactId));
oneOf(eventBus).broadcast(with(any(ContactAddedEvent.class))); oneOf(eventBus).broadcast(with(any(ContactAddedEvent.class)));
oneOf(eventBus).broadcast(with(any( oneOf(eventBus).broadcast(with(any(
@@ -187,9 +185,9 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
oneOf(database).removeContact(txn, contactId); oneOf(database).removeContact(txn, contactId);
oneOf(eventBus).broadcast(with(any(ContactRemovedEvent.class))); oneOf(eventBus).broadcast(with(any(ContactRemovedEvent.class)));
// removeLocalAuthor() // removeLocalAuthor()
oneOf(database).containsLocalAuthor(txn, localAuthorId); oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
will(returnValue(true)); will(returnValue(true));
oneOf(database).removeLocalAuthor(txn, localAuthorId); oneOf(database).removeLocalAuthor(txn, localAuthor.getId());
oneOf(eventBus).broadcast(with(any(LocalAuthorRemovedEvent.class))); oneOf(eventBus).broadcast(with(any(LocalAuthorRemovedEvent.class)));
// endTransaction() // endTransaction()
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
@@ -203,9 +201,8 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
Transaction transaction = db.startTransaction(false); Transaction transaction = db.startTransaction(false);
try { try {
db.addLocalAuthor(transaction, localAuthor); db.addLocalAuthor(transaction, localAuthor);
assertEquals(contactId, assertEquals(contactId, db.addContact(transaction, author,
db.addContact(transaction, author, localAuthorId, true, localAuthor.getId(), true, true));
true));
assertEquals(Collections.singletonList(contact), assertEquals(Collections.singletonList(contact),
db.getContacts(transaction)); db.getContacts(transaction));
db.addGroup(transaction, group); // First time - listeners called db.addGroup(transaction, group); // First time - listeners called
@@ -214,7 +211,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
db.getGroups(transaction, clientId)); db.getGroups(transaction, clientId));
db.removeGroup(transaction, group); db.removeGroup(transaction, group);
db.removeContact(transaction, contactId); db.removeContact(transaction, contactId);
db.removeLocalAuthor(transaction, localAuthorId); db.removeLocalAuthor(transaction, localAuthor.getId());
db.commitTransaction(transaction); db.commitTransaction(transaction);
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
@@ -487,7 +484,8 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
// Check whether the pseudonym is in the DB (which it's not) // Check whether the pseudonym is in the DB (which it's not)
exactly(3).of(database).startTransaction(); exactly(3).of(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
exactly(3).of(database).containsLocalAuthor(txn, localAuthorId); exactly(3).of(database).containsLocalAuthor(txn,
localAuthor.getId());
will(returnValue(false)); will(returnValue(false));
exactly(3).of(database).abortTransaction(txn); exactly(3).of(database).abortTransaction(txn);
}}); }});
@@ -496,7 +494,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
Transaction transaction = db.startTransaction(false); Transaction transaction = db.startTransaction(false);
try { try {
db.addContact(transaction, author, localAuthorId, true, true); db.addContact(transaction, author, localAuthor.getId(), true, true);
fail(); fail();
} catch (NoSuchLocalAuthorException expected) { } catch (NoSuchLocalAuthorException expected) {
// Expected // Expected
@@ -506,7 +504,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
transaction = db.startTransaction(false); transaction = db.startTransaction(false);
try { try {
db.getLocalAuthor(transaction, localAuthorId); db.getLocalAuthor(transaction, localAuthor.getId());
fail(); fail();
} catch (NoSuchLocalAuthorException expected) { } catch (NoSuchLocalAuthorException expected) {
// Expected // Expected
@@ -516,7 +514,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
transaction = db.startTransaction(false); transaction = db.startTransaction(false);
try { try {
db.removeLocalAuthor(transaction, localAuthorId); db.removeLocalAuthor(transaction, localAuthor.getId());
fail(); fail();
} catch (NoSuchLocalAuthorException expected) { } catch (NoSuchLocalAuthorException expected) {
// Expected // Expected
@@ -759,18 +757,20 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
// registerLocalAuthor() // registerLocalAuthor()
oneOf(database).containsLocalAuthor(txn, localAuthorId); oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
will(returnValue(false)); will(returnValue(false));
oneOf(database).addLocalAuthor(txn, localAuthor); oneOf(database).addLocalAuthor(txn, localAuthor);
oneOf(eventBus).broadcast(with(any(LocalAuthorAddedEvent.class))); oneOf(eventBus).broadcast(with(any(LocalAuthorAddedEvent.class)));
// addContact() // addContact()
oneOf(database).containsLocalAuthor(txn, localAuthorId); oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
will(returnValue(true)); will(returnValue(true));
oneOf(database).containsLocalAuthor(txn, authorId); oneOf(database).containsLocalAuthor(txn, author.getId());
will(returnValue(false)); will(returnValue(false));
oneOf(database).containsContact(txn, authorId, localAuthorId); oneOf(database).containsContact(txn, author.getId(),
localAuthor.getId());
will(returnValue(false)); will(returnValue(false));
oneOf(database).addContact(txn, author, localAuthorId, true, true); oneOf(database).addContact(txn, author, localAuthor.getId(),
true, true);
will(returnValue(contactId)); will(returnValue(contactId));
oneOf(eventBus).broadcast(with(any(ContactAddedEvent.class))); oneOf(eventBus).broadcast(with(any(ContactAddedEvent.class)));
oneOf(eventBus).broadcast(with(any( oneOf(eventBus).broadcast(with(any(
@@ -792,9 +792,8 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
Transaction transaction = db.startTransaction(false); Transaction transaction = db.startTransaction(false);
try { try {
db.addLocalAuthor(transaction, localAuthor); db.addLocalAuthor(transaction, localAuthor);
assertEquals(contactId, assertEquals(contactId, db.addContact(transaction, author,
db.addContact(transaction, author, localAuthorId, true, localAuthor.getId(), true, true));
true));
db.commitTransaction(transaction); db.commitTransaction(transaction);
} finally { } finally {
db.endTransaction(transaction); db.endTransaction(transaction);
@@ -1406,10 +1405,10 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
oneOf(database).containsLocalAuthor(txn, localAuthorId); oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
will(returnValue(true)); will(returnValue(true));
// Contact is a local identity // Contact is a local identity
oneOf(database).containsLocalAuthor(txn, authorId); oneOf(database).containsLocalAuthor(txn, author.getId());
will(returnValue(true)); will(returnValue(true));
oneOf(database).abortTransaction(txn); oneOf(database).abortTransaction(txn);
}}); }});
@@ -1419,7 +1418,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
Transaction transaction = db.startTransaction(false); Transaction transaction = db.startTransaction(false);
try { try {
db.addContact(transaction, author, localAuthorId, true, true); db.addContact(transaction, author, localAuthor.getId(), true, true);
fail(); fail();
} catch (ContactExistsException expected) { } catch (ContactExistsException expected) {
// Expected // Expected
@@ -1433,12 +1432,13 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).startTransaction(); oneOf(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
oneOf(database).containsLocalAuthor(txn, localAuthorId); oneOf(database).containsLocalAuthor(txn, localAuthor.getId());
will(returnValue(true)); will(returnValue(true));
oneOf(database).containsLocalAuthor(txn, authorId); oneOf(database).containsLocalAuthor(txn, author.getId());
will(returnValue(false)); will(returnValue(false));
// Contact already exists for this local identity // Contact already exists for this local identity
oneOf(database).containsContact(txn, authorId, localAuthorId); oneOf(database).containsContact(txn, author.getId(),
localAuthor.getId());
will(returnValue(true)); will(returnValue(true));
oneOf(database).abortTransaction(txn); oneOf(database).abortTransaction(txn);
}}); }});
@@ -1448,7 +1448,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
Transaction transaction = db.startTransaction(false); Transaction transaction = db.startTransaction(false);
try { try {
db.addContact(transaction, author, localAuthorId, true, true); db.addContact(transaction, author, localAuthor.getId(), true, true);
fail(); fail();
} catch (ContactExistsException expected) { } catch (ContactExistsException expected) {
// Expected // Expected

View File

@@ -7,7 +7,6 @@ import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.settings.Settings; import org.briarproject.bramble.api.settings.Settings;
@@ -26,7 +25,6 @@ import org.briarproject.bramble.system.SystemClock;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestDatabaseConfig; import org.briarproject.bramble.test.TestDatabaseConfig;
import org.briarproject.bramble.test.TestUtils; import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -46,7 +44,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.SECONDS;
import static org.briarproject.bramble.api.db.Metadata.REMOVE; import static org.briarproject.bramble.api.db.Metadata.REMOVE;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
@@ -56,6 +53,11 @@ import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERE
import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID; import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING; import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN; import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@@ -75,7 +77,6 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
private final ClientId clientId; private final ClientId clientId;
private final Group group; private final Group group;
private final Author author; private final Author author;
private final AuthorId localAuthorId;
private final LocalAuthor localAuthor; private final LocalAuthor localAuthor;
private final MessageId messageId; private final MessageId messageId;
private final long timestamp; private final long timestamp;
@@ -86,19 +87,16 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
private final ContactId contactId; private final ContactId contactId;
JdbcDatabaseTest() throws Exception { JdbcDatabaseTest() throws Exception {
groupId = new GroupId(TestUtils.getRandomId()); groupId = new GroupId(getRandomId());
clientId = new ClientId(StringUtils.getRandomString(5)); clientId = new ClientId(getRandomString(123));
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH]; byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
group = new Group(groupId, clientId, descriptor); group = new Group(groupId, clientId, descriptor);
AuthorId authorId = new AuthorId(TestUtils.getRandomId()); author = getAuthor();
author = new Author(authorId, "Alice", new byte[MAX_PUBLIC_KEY_LENGTH]); localAuthor = getLocalAuthor();
localAuthorId = new AuthorId(TestUtils.getRandomId()); messageId = new MessageId(getRandomId());
timestamp = System.currentTimeMillis(); timestamp = System.currentTimeMillis();
localAuthor = new LocalAuthor(localAuthorId, "Bob",
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp);
messageId = new MessageId(TestUtils.getRandomId());
size = 1234; size = 1234;
raw = TestUtils.getRandomBytes(size); raw = getRandomBytes(size);
message = new Message(messageId, groupId, timestamp, raw); message = new Message(messageId, groupId, timestamp, raw);
transportId = new TransportId("id"); transportId = new TransportId("id");
contactId = new ContactId(1); contactId = new ContactId(1);
@@ -119,7 +117,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
assertFalse(db.containsContact(txn, contactId)); assertFalse(db.containsContact(txn, contactId));
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
assertTrue(db.containsContact(txn, contactId)); assertTrue(db.containsContact(txn, contactId));
assertFalse(db.containsGroup(txn, groupId)); assertFalse(db.containsGroup(txn, groupId));
@@ -182,7 +180,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact, a shared group and a shared message // Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true); db.addGroupVisibility(txn, contactId, groupId, true);
@@ -220,7 +218,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact, a shared group and a shared but unvalidated message // Add a contact, a shared group and a shared but unvalidated message
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true); db.addGroupVisibility(txn, contactId, groupId, true);
@@ -266,7 +264,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact, an invisible group and a shared message // Add a contact, an invisible group and a shared message
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addMessage(txn, message, DELIVERED, true); db.addMessage(txn, message, DELIVERED, true);
@@ -318,7 +316,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact, a shared group and an unshared message // Add a contact, a shared group and an unshared message
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true); db.addGroupVisibility(txn, contactId, groupId, true);
@@ -350,7 +348,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact, a shared group and a shared message // Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true); db.addGroupVisibility(txn, contactId, groupId, true);
@@ -377,13 +375,13 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact and a visible group // Add a contact and a visible group
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, false); db.addGroupVisibility(txn, contactId, groupId, false);
// Add some messages to ack // Add some messages to ack
MessageId messageId1 = new MessageId(TestUtils.getRandomId()); MessageId messageId1 = new MessageId(getRandomId());
Message message1 = new Message(messageId1, groupId, timestamp, raw); Message message1 = new Message(messageId1, groupId, timestamp, raw);
db.addMessage(txn, message, DELIVERED, true); db.addMessage(txn, message, DELIVERED, true);
db.addStatus(txn, contactId, messageId, false, true); db.addStatus(txn, contactId, messageId, false, true);
@@ -414,7 +412,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact, a shared group and a shared message // Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true); db.addGroupVisibility(txn, contactId, groupId, true);
@@ -572,7 +570,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact and a shared group // Add a contact and a shared group
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true); db.addGroupVisibility(txn, contactId, groupId, true);
@@ -592,7 +590,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact // Add a contact
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
// The group is not in the database // The group is not in the database
@@ -610,7 +608,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact, a group and a message // Add a contact, a group and a message
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addMessage(txn, message, DELIVERED, true); db.addMessage(txn, message, DELIVERED, true);
@@ -630,7 +628,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact and a group // Add a contact and a group
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addGroup(txn, group); db.addGroup(txn, group);
@@ -680,7 +678,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add the contact, the transport and the transport keys // Add the contact, the transport and the transport keys
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addTransport(txn, transportId, 123); db.addTransport(txn, transportId, 123);
db.addTransportKeys(txn, contactId, keys); db.addTransportKeys(txn, contactId, keys);
@@ -742,7 +740,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add the contact, transport and transport keys // Add the contact, transport and transport keys
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addTransport(txn, transportId, 123); db.addTransport(txn, transportId, 123);
db.updateTransportKeys(txn, Collections.singletonMap(contactId, keys)); db.updateTransportKeys(txn, Collections.singletonMap(contactId, keys));
@@ -778,7 +776,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add the contact, transport and transport keys // Add the contact, transport and transport keys
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addTransport(txn, transportId, 123); db.addTransport(txn, transportId, 123);
db.updateTransportKeys(txn, Collections.singletonMap(contactId, keys)); db.updateTransportKeys(txn, Collections.singletonMap(contactId, keys));
@@ -813,7 +811,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
// Add a contact associated with the local author // Add a contact associated with the local author
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
// Ensure contact is returned from database by Author ID // Ensure contact is returned from database by Author ID
@@ -838,18 +836,19 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a local author - no contacts should be associated // Add a local author - no contacts should be associated
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
Collection<ContactId> contacts = db.getContacts(txn, localAuthorId); Collection<ContactId> contacts =
db.getContacts(txn, localAuthor.getId());
assertEquals(Collections.emptyList(), contacts); assertEquals(Collections.emptyList(), contacts);
// Add a contact associated with the local author // Add a contact associated with the local author
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
contacts = db.getContacts(txn, localAuthorId); contacts = db.getContacts(txn, localAuthor.getId());
assertEquals(Collections.singletonList(contactId), contacts); assertEquals(Collections.singletonList(contactId), contacts);
// Remove the local author - the contact should be removed // Remove the local author - the contact should be removed
db.removeLocalAuthor(txn, localAuthorId); db.removeLocalAuthor(txn, localAuthor.getId());
contacts = db.getContacts(txn, localAuthorId); contacts = db.getContacts(txn, localAuthor.getId());
assertEquals(Collections.emptyList(), contacts); assertEquals(Collections.emptyList(), contacts);
assertFalse(db.containsContact(txn, contactId)); assertFalse(db.containsContact(txn, contactId));
@@ -864,14 +863,14 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact - initially there should be no offered messages // Add a contact - initially there should be no offered messages
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
assertEquals(0, db.countOfferedMessages(txn, contactId)); assertEquals(0, db.countOfferedMessages(txn, contactId));
// Add some offered messages and count them // Add some offered messages and count them
List<MessageId> ids = new ArrayList<>(); List<MessageId> ids = new ArrayList<>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
MessageId m = new MessageId(TestUtils.getRandomId()); MessageId m = new MessageId(getRandomId());
db.addOfferedMessage(txn, contactId, m); db.addOfferedMessage(txn, contactId, m);
ids.add(m); ids.add(m);
} }
@@ -1056,7 +1055,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
@Test @Test
public void testMetadataQueries() throws Exception { public void testMetadataQueries() throws Exception {
MessageId messageId1 = new MessageId(TestUtils.getRandomId()); MessageId messageId1 = new MessageId(getRandomId());
Message message1 = new Message(messageId1, groupId, timestamp, raw); Message message1 = new Message(messageId1, groupId, timestamp, raw);
Database<Connection> db = open(false); Database<Connection> db = open(false);
@@ -1160,7 +1159,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
@Test @Test
public void testMetadataQueriesOnlyForDeliveredMessages() throws Exception { public void testMetadataQueriesOnlyForDeliveredMessages() throws Exception {
MessageId messageId1 = new MessageId(TestUtils.getRandomId()); MessageId messageId1 = new MessageId(getRandomId());
Message message1 = new Message(messageId1, groupId, timestamp, raw); Message message1 = new Message(messageId1, groupId, timestamp, raw);
Database<Connection> db = open(false); Database<Connection> db = open(false);
@@ -1231,10 +1230,10 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
@Test @Test
public void testMessageDependencies() throws Exception { public void testMessageDependencies() throws Exception {
MessageId messageId1 = new MessageId(TestUtils.getRandomId()); MessageId messageId1 = new MessageId(getRandomId());
MessageId messageId2 = new MessageId(TestUtils.getRandomId()); MessageId messageId2 = new MessageId(getRandomId());
MessageId messageId3 = new MessageId(TestUtils.getRandomId()); MessageId messageId3 = new MessageId(getRandomId());
MessageId messageId4 = new MessageId(TestUtils.getRandomId()); MessageId messageId4 = new MessageId(getRandomId());
Message message1 = new Message(messageId1, groupId, timestamp, raw); Message message1 = new Message(messageId1, groupId, timestamp, raw);
Message message2 = new Message(messageId2, groupId, timestamp, raw); Message message2 = new Message(messageId2, groupId, timestamp, raw);
@@ -1315,21 +1314,21 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
db.addMessage(txn, message, PENDING, true); db.addMessage(txn, message, PENDING, true);
// Add a second group // Add a second group
GroupId groupId1 = new GroupId(TestUtils.getRandomId()); GroupId groupId1 = new GroupId(getRandomId());
Group group1 = new Group(groupId1, clientId, Group group1 = new Group(groupId1, clientId,
TestUtils.getRandomBytes(MAX_GROUP_DESCRIPTOR_LENGTH)); getRandomBytes(MAX_GROUP_DESCRIPTOR_LENGTH));
db.addGroup(txn, group1); db.addGroup(txn, group1);
// Add a message to the second group // Add a message to the second group
MessageId messageId1 = new MessageId(TestUtils.getRandomId()); MessageId messageId1 = new MessageId(getRandomId());
Message message1 = new Message(messageId1, groupId1, timestamp, raw); Message message1 = new Message(messageId1, groupId1, timestamp, raw);
db.addMessage(txn, message1, DELIVERED, true); db.addMessage(txn, message1, DELIVERED, true);
// Create an ID for a missing message // Create an ID for a missing message
MessageId messageId2 = new MessageId(TestUtils.getRandomId()); MessageId messageId2 = new MessageId(getRandomId());
// Add another message to the first group // Add another message to the first group
MessageId messageId3 = new MessageId(TestUtils.getRandomId()); MessageId messageId3 = new MessageId(getRandomId());
Message message3 = new Message(messageId3, groupId, timestamp, raw); Message message3 = new Message(messageId3, groupId, timestamp, raw);
db.addMessage(txn, message3, DELIVERED, true); db.addMessage(txn, message3, DELIVERED, true);
@@ -1364,10 +1363,10 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
@Test @Test
public void testGetPendingMessagesForDelivery() throws Exception { public void testGetPendingMessagesForDelivery() throws Exception {
MessageId mId1 = new MessageId(TestUtils.getRandomId()); MessageId mId1 = new MessageId(getRandomId());
MessageId mId2 = new MessageId(TestUtils.getRandomId()); MessageId mId2 = new MessageId(getRandomId());
MessageId mId3 = new MessageId(TestUtils.getRandomId()); MessageId mId3 = new MessageId(getRandomId());
MessageId mId4 = new MessageId(TestUtils.getRandomId()); MessageId mId4 = new MessageId(getRandomId());
Message m1 = new Message(mId1, groupId, timestamp, raw); Message m1 = new Message(mId1, groupId, timestamp, raw);
Message m2 = new Message(mId2, groupId, timestamp, raw); Message m2 = new Message(mId2, groupId, timestamp, raw);
Message m3 = new Message(mId3, groupId, timestamp, raw); Message m3 = new Message(mId3, groupId, timestamp, raw);
@@ -1401,10 +1400,10 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
@Test @Test
public void testGetMessagesToShare() throws Exception { public void testGetMessagesToShare() throws Exception {
MessageId mId1 = new MessageId(TestUtils.getRandomId()); MessageId mId1 = new MessageId(getRandomId());
MessageId mId2 = new MessageId(TestUtils.getRandomId()); MessageId mId2 = new MessageId(getRandomId());
MessageId mId3 = new MessageId(TestUtils.getRandomId()); MessageId mId3 = new MessageId(getRandomId());
MessageId mId4 = new MessageId(TestUtils.getRandomId()); MessageId mId4 = new MessageId(getRandomId());
Message m1 = new Message(mId1, groupId, timestamp, raw); Message m1 = new Message(mId1, groupId, timestamp, raw);
Message m2 = new Message(mId2, groupId, timestamp, raw); Message m2 = new Message(mId2, groupId, timestamp, raw);
Message m3 = new Message(mId3, groupId, timestamp, raw); Message m3 = new Message(mId3, groupId, timestamp, raw);
@@ -1443,7 +1442,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact, a shared group and a shared message // Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true); db.addGroupVisibility(txn, contactId, groupId, true);
@@ -1512,9 +1511,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
@Test @Test
public void testDifferentLocalAuthorsCanHaveTheSameContact() public void testDifferentLocalAuthorsCanHaveTheSameContact()
throws Exception { throws Exception {
AuthorId localAuthorId1 = new AuthorId(TestUtils.getRandomId()); LocalAuthor localAuthor1 = getLocalAuthor();
LocalAuthor localAuthor1 = new LocalAuthor(localAuthorId1, "Carol",
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp);
Database<Connection> db = open(false); Database<Connection> db = open(false);
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
@@ -1525,15 +1522,15 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add the same contact for each local author // Add the same contact for each local author
ContactId contactId = ContactId contactId =
db.addContact(txn, author, localAuthorId, true, true); db.addContact(txn, author, localAuthor.getId(), true, true);
ContactId contactId1 = ContactId contactId1 =
db.addContact(txn, author, localAuthorId1, true, true); db.addContact(txn, author, localAuthor1.getId(), true, true);
// The contacts should be distinct // The contacts should be distinct
assertNotEquals(contactId, contactId1); assertNotEquals(contactId, contactId1);
assertEquals(2, db.getContacts(txn).size()); assertEquals(2, db.getContacts(txn).size());
assertEquals(1, db.getContacts(txn, localAuthorId).size()); assertEquals(1, db.getContacts(txn, localAuthor.getId()).size());
assertEquals(1, db.getContacts(txn, localAuthorId1).size()); assertEquals(1, db.getContacts(txn, localAuthor1.getId()).size());
db.commitTransaction(txn); db.commitTransaction(txn);
db.close(); db.close();
@@ -1546,7 +1543,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact, a shared group and a shared message // Add a contact, a shared group and a shared message
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
db.addGroup(txn, group); db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true); db.addGroupVisibility(txn, contactId, groupId, true);
@@ -1592,7 +1589,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Add a contact // Add a contact
db.addLocalAuthor(txn, localAuthor); db.addLocalAuthor(txn, localAuthor);
assertEquals(contactId, db.addContact(txn, author, localAuthorId, assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
true, true)); true, true));
// The contact should be active // The contact should be active

View File

@@ -10,8 +10,6 @@ import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.junit.Test; import org.junit.Test;
@@ -23,6 +21,8 @@ import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN; import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED; import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED;
import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED; import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
public class IdentityManagerImplTest extends BrambleMockTestCase { public class IdentityManagerImplTest extends BrambleMockTestCase {
@@ -30,11 +30,7 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
private final IdentityManager identityManager; private final IdentityManager identityManager;
private final DatabaseComponent db = context.mock(DatabaseComponent.class); private final DatabaseComponent db = context.mock(DatabaseComponent.class);
private final Transaction txn = new Transaction(null, false); private final Transaction txn = new Transaction(null, false);
private final LocalAuthor localAuthor = private final LocalAuthor localAuthor = getLocalAuthor();
new LocalAuthor(new AuthorId(TestUtils.getRandomId()),
StringUtils.getRandomString(8),
TestUtils.getRandomBytes(42), TestUtils.getRandomBytes(42),
0);
private final Collection<LocalAuthor> localAuthors = private final Collection<LocalAuthor> localAuthors =
Collections.singletonList(localAuthor); Collections.singletonList(localAuthor);
@@ -80,7 +76,8 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testGetAuthorStatus() throws DbException { public void testGetAuthorStatus() throws DbException {
AuthorId authorId = new AuthorId(TestUtils.getRandomId()); Author author = getAuthor();
AuthorId authorId = author.getId();
Collection<Contact> contacts = new ArrayList<>(); Collection<Contact> contacts = new ArrayList<>();
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -95,20 +92,16 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
assertEquals(UNKNOWN, identityManager.getAuthorStatus(authorId)); assertEquals(UNKNOWN, identityManager.getAuthorStatus(authorId));
// add one unverified contact // add one unverified contact
Author author = new Author(authorId, StringUtils.getRandomString(8), Contact contact = new Contact(new ContactId(1), author,
TestUtils.getRandomBytes(42)); localAuthor.getId(), false, true);
Contact contact =
new Contact(new ContactId(1), author, localAuthor.getId(),
false, true);
contacts.add(contact); contacts.add(contact);
checkAuthorStatusContext(authorId, contacts); checkAuthorStatusContext(authorId, contacts);
assertEquals(UNVERIFIED, identityManager.getAuthorStatus(authorId)); assertEquals(UNVERIFIED, identityManager.getAuthorStatus(authorId));
// add one verified contact // add one verified contact
Contact contact2 = Contact contact2 = new Contact(new ContactId(1), author,
new Contact(new ContactId(1), author, localAuthor.getId(), localAuthor.getId(), true, true);
true, true);
contacts.add(contact2); contacts.add(contact2);
checkAuthorStatusContext(authorId, contacts); checkAuthorStatusContext(authorId, contacts);

View File

@@ -11,8 +11,6 @@ import org.briarproject.bramble.api.data.MetadataParser;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties; import org.briarproject.bramble.api.properties.TransportProperties;
@@ -31,16 +29,15 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.properties.TransportPropertyManager.CLIENT_ID; import static org.briarproject.bramble.api.properties.TransportPropertyManager.CLIENT_ID;
import static org.briarproject.bramble.api.properties.TransportPropertyManager.CLIENT_VERSION; import static org.briarproject.bramble.api.properties.TransportPropertyManager.CLIENT_VERSION;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@@ -609,22 +606,10 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
return new Group(g, CLIENT_ID, descriptor); return new Group(g, CLIENT_ID, descriptor);
} }
private LocalAuthor getLocalAuthor() {
AuthorId id = new AuthorId(getRandomId());
String name = getRandomString(MAX_AUTHOR_NAME_LENGTH);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
byte[] privateKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
long created = System.currentTimeMillis();
return new LocalAuthor(id, name, publicKey, privateKey, created);
}
private Contact getContact(boolean active) { private Contact getContact(boolean active) {
ContactId c = new ContactId(nextContactId++); ContactId c = new ContactId(nextContactId++);
AuthorId a = new AuthorId(getRandomId()); return new Contact(c, getAuthor(), localAuthor.getId(),
String name = getRandomString(MAX_AUTHOR_NAME_LENGTH); true, active);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
return new Contact(c, new Author(a, name, publicKey),
localAuthor.getId(), true, active);
} }
private Message getMessage(GroupId g, long timestamp) { private Message getMessage(GroupId g, long timestamp) {

View File

@@ -9,7 +9,10 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.StringUtils;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
public abstract class ValidatorTestCase extends BrambleMockTestCase { public abstract class ValidatorTestCase extends BrambleMockTestCase {
@@ -21,16 +24,14 @@ public abstract class ValidatorTestCase extends BrambleMockTestCase {
protected final AuthorFactory authorFactory = protected final AuthorFactory authorFactory =
context.mock(AuthorFactory.class); context.mock(AuthorFactory.class);
protected final MessageId messageId = protected final MessageId messageId = new MessageId(getRandomId());
new MessageId(TestUtils.getRandomId()); protected final GroupId groupId = new GroupId(getRandomId());
protected final GroupId groupId = new GroupId(TestUtils.getRandomId());
protected final long timestamp = 1234567890 * 1000L; protected final long timestamp = 1234567890 * 1000L;
protected final byte[] raw = TestUtils.getRandomBytes(123); protected final byte[] raw = getRandomBytes(123);
protected final Message message = protected final Message message =
new Message(messageId, groupId, timestamp, raw); new Message(messageId, groupId, timestamp, raw);
protected final ClientId clientId = protected final ClientId clientId = new ClientId(getRandomString(123));
new ClientId(StringUtils.getRandomString(123)); protected final byte[] descriptor = getRandomBytes(123);
protected final byte[] descriptor = TestUtils.getRandomBytes(123);
protected final Group group = new Group(groupId, clientId, descriptor); protected final Group group = new Group(groupId, clientId, descriptor);
} }

View File

@@ -23,8 +23,10 @@ import org.junit.Test;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Random;
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH; import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.test.TestUtils.getSecretKey;
@@ -59,9 +61,7 @@ public class KeyManagerImplTest extends BrambleTestCase {
@Before @Before
public void testStartService() throws Exception { public void testStartService() throws Exception {
Transaction txn = new Transaction(null, false); Transaction txn = new Transaction(null, false);
AuthorId remoteAuthorId = new AuthorId(getRandomId()); Author remoteAuthor = getAuthor();
Author remoteAuthor = new Author(remoteAuthorId, "author",
getRandomBytes(42));
AuthorId localAuthorId = new AuthorId(getRandomId()); AuthorId localAuthorId = new AuthorId(getRandomId());
Collection<Contact> contacts = new ArrayList<>(); Collection<Contact> contacts = new ArrayList<>();
contacts.add(new Contact(contactId, remoteAuthor, localAuthorId, true, contacts.add(new Contact(contactId, remoteAuthor, localAuthorId, true,
@@ -101,12 +101,12 @@ public class KeyManagerImplTest extends BrambleTestCase {
@Test @Test
public void testAddContact() throws Exception { public void testAddContact() throws Exception {
SecretKey secretKey = getSecretKey(); SecretKey secretKey = getSecretKey();
long timestamp = 42L; long timestamp = System.currentTimeMillis();
boolean alice = true; boolean alice = new Random().nextBoolean();
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(transportKeyManager) oneOf(transportKeyManager).addContact(txn, contactId, secretKey,
.addContact(txn, contactId, secretKey, timestamp, alice); timestamp, alice);
}}); }});
keyManager.addContact(txn, contactId, secretKey, timestamp, alice); keyManager.addContact(txn, contactId, secretKey, timestamp, alice);
@@ -121,8 +121,8 @@ public class KeyManagerImplTest extends BrambleTestCase {
@Test @Test
public void testGetStreamContextForUnknownTransport() throws Exception { public void testGetStreamContextForUnknownTransport() throws Exception {
assertEquals(null, keyManager assertEquals(null,
.getStreamContext(contactId, unknownTransportId)); keyManager.getStreamContext(contactId, unknownTransportId));
} }
@Test @Test

View File

@@ -44,8 +44,8 @@ class RssFeedAdapter extends BriarAdapter<Feed, RssFeedAdapter.FeedViewHolder> {
ui.delete.setOnClickListener(v -> listener.onDeleteClick(item)); ui.delete.setOnClickListener(v -> listener.onDeleteClick(item));
// Author // Author
if (item.getAuthor() != null) { if (item.getRssAuthor() != null) {
ui.author.setText(item.getAuthor()); ui.author.setText(item.getRssAuthor());
ui.author.setVisibility(VISIBLE); ui.author.setVisibility(VISIBLE);
ui.authorLabel.setVisibility(VISIBLE); ui.authorLabel.setVisibility(VISIBLE);
} else { } else {

View File

@@ -6,9 +6,7 @@ import junit.framework.Assert;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.briar.android.TestBriarApplication; import org.briarproject.briar.android.TestBriarApplication;
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler; import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
import org.briarproject.briar.android.threaded.ThreadItemAdapter; import org.briarproject.briar.android.threaded.ThreadItemAdapter;
@@ -29,7 +27,10 @@ import java.util.Arrays;
import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.assertTrue;
import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN; import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -38,30 +39,19 @@ import static org.mockito.Mockito.verify;
packageName = "org.briarproject.briar") packageName = "org.briarproject.briar")
public class ForumActivityTest { public class ForumActivityTest {
private final static String AUTHOR_1 = "Author 1"; private final static MessageId[] MESSAGE_IDS = new MessageId[6];
private final static String AUTHOR_2 = "Author 2";
private final static String AUTHOR_3 = "Author 3";
private final static String AUTHOR_4 = "Author 4";
private final static String AUTHOR_5 = "Author 5";
private final static String AUTHOR_6 = "Author 6";
private final static String[] AUTHORS = {
AUTHOR_1, AUTHOR_2, AUTHOR_3, AUTHOR_4, AUTHOR_5, AUTHOR_6
};
private final static MessageId[] AUTHOR_IDS = new MessageId[AUTHORS.length];
static { static {
for (int i = 0; i < AUTHOR_IDS.length; i++) for (int i = 0; i < MESSAGE_IDS.length; i++)
AUTHOR_IDS[i] = new MessageId(TestUtils.getRandomId()); MESSAGE_IDS[i] = new MessageId(getRandomId());
} }
private final static MessageId[] PARENT_AUTHOR_IDS = { private final static MessageId[] PARENT_IDS = {
null, null,
AUTHOR_IDS[0], MESSAGE_IDS[0],
AUTHOR_IDS[1], MESSAGE_IDS[1],
AUTHOR_IDS[2], MESSAGE_IDS[2],
AUTHOR_IDS[0], MESSAGE_IDS[0],
null null
}; };
@@ -86,7 +76,7 @@ public class ForumActivityTest {
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
Intent intent = new Intent(); Intent intent = new Intent();
intent.putExtra("briar.GROUP_ID", TestUtils.getRandomId()); intent.putExtra("briar.GROUP_ID", getRandomId());
forumActivity = Robolectric.buildActivity(TestForumActivity.class, forumActivity = Robolectric.buildActivity(TestForumActivity.class,
intent).create().start().resume().get(); intent).create().start().resume().get();
} }
@@ -94,11 +84,10 @@ public class ForumActivityTest {
private ThreadItemList<ForumItem> getDummyData() { private ThreadItemList<ForumItem> getDummyData() {
ForumItem[] forumItems = new ForumItem[6]; ForumItem[] forumItems = new ForumItem[6];
for (int i = 0; i < forumItems.length; i++) { for (int i = 0; i < forumItems.length; i++) {
AuthorId authorId = new AuthorId(TestUtils.getRandomId()); Author author = getAuthor();
byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH); String content = getRandomString(MAX_FORUM_POST_BODY_LENGTH);
Author author = new Author(authorId, AUTHORS[i], publicKey); forumItems[i] = new ForumItem(MESSAGE_IDS[i], PARENT_IDS[i],
forumItems[i] = new ForumItem(AUTHOR_IDS[i], PARENT_AUTHOR_IDS[i], content, System.currentTimeMillis(), author, UNKNOWN);
AUTHORS[i], System.currentTimeMillis(), author, UNKNOWN);
forumItems[i].setLevel(LEVELS[i]); forumItems[i].setLevel(LEVELS[i]);
} }
ThreadItemList<ForumItem> list = new ThreadItemListImpl<>(); ThreadItemList<ForumItem> list = new ThreadItemListImpl<>();

View File

@@ -1,15 +1,9 @@
package org.briarproject.briar.api.blog; package org.briarproject.briar.api.blog;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
public interface BlogConstants { public interface BlogConstants {
/**
* The maximum length of a blogs's name in UTF-8 bytes.
*/
int MAX_BLOG_NAME_LENGTH = MAX_AUTHOR_NAME_LENGTH;
/** /**
* The maximum length of a blog post's body in bytes. * The maximum length of a blog post's body in bytes.
*/ */
@@ -24,9 +18,6 @@ public interface BlogConstants {
String KEY_TYPE = "type"; String KEY_TYPE = "type";
String KEY_TIMESTAMP = "timestamp"; String KEY_TIMESTAMP = "timestamp";
String KEY_TIME_RECEIVED = "timeReceived"; String KEY_TIME_RECEIVED = "timeReceived";
String KEY_AUTHOR_ID = "id";
String KEY_AUTHOR_NAME = "name";
String KEY_PUBLIC_KEY = "publicKey";
String KEY_AUTHOR = "author"; String KEY_AUTHOR = "author";
String KEY_RSS_FEED = "rssFeed"; String KEY_RSS_FEED = "rssFeed";
String KEY_READ = "read"; String KEY_READ = "read";

View File

@@ -16,26 +16,26 @@ public class Feed {
private final Blog blog; private final Blog blog;
private final LocalAuthor localAuthor; private final LocalAuthor localAuthor;
@Nullable @Nullable
private final String description, author; private final String description, rssAuthor;
private final long added, updated, lastEntryTime; private final long added, updated, lastEntryTime;
public Feed(String url, Blog blog, LocalAuthor localAuthor, public Feed(String url, Blog blog, LocalAuthor localAuthor,
@Nullable String description, @Nullable String author, long added, @Nullable String description, @Nullable String rssAuthor,
long updated, long lastEntryTime) { long added, long updated, long lastEntryTime) {
this.url = url; this.url = url;
this.blog = blog; this.blog = blog;
this.localAuthor = localAuthor; this.localAuthor = localAuthor;
this.description = description; this.description = description;
this.author = author; this.rssAuthor = rssAuthor;
this.added = added; this.added = added;
this.updated = updated; this.updated = updated;
this.lastEntryTime = lastEntryTime; this.lastEntryTime = lastEntryTime;
} }
public Feed(String url, Blog blog, LocalAuthor localAuthor, public Feed(String url, Blog blog, LocalAuthor localAuthor,
@Nullable String description, @Nullable String author, long added) { @Nullable String description, @Nullable String rssAuthor,
this(url, blog, localAuthor, description, author, added, 0L, 0L); long added) {
this(url, blog, localAuthor, description, rssAuthor, added, 0L, 0L);
} }
public Feed(String url, Blog blog, LocalAuthor localAuthor, long added) { public Feed(String url, Blog blog, LocalAuthor localAuthor, long added) {
@@ -68,8 +68,8 @@ public class Feed {
} }
@Nullable @Nullable
public String getAuthor() { public String getRssAuthor() {
return author; return rssAuthor;
} }
public long getAdded() { public long getAdded() {

View File

@@ -18,11 +18,10 @@ public interface FeedConstants {
// group metadata keys // group metadata keys
String KEY_FEEDS = "feeds"; String KEY_FEEDS = "feeds";
String KEY_FEED_URL = "feedURL"; String KEY_FEED_URL = "feedURL";
String KEY_BLOG_TITLE = "blogTitle";
String KEY_PUBLIC_KEY = "publicKey";
String KEY_PRIVATE_KEY = "privateKey";
String KEY_FEED_DESC = "feedDesc";
String KEY_FEED_AUTHOR = "feedAuthor"; String KEY_FEED_AUTHOR = "feedAuthor";
String KEY_FEED_PRIVATE_KEY = "feedPrivateKey";
String KEY_FEED_DESC = "feedDesc";
String KEY_FEED_RSS_AUTHOR = "feedRssAuthor";
String KEY_FEED_ADDED = "feedAdded"; String KEY_FEED_ADDED = "feedAdded";
String KEY_FEED_UPDATED = "feedUpdated"; String KEY_FEED_UPDATED = "feedUpdated";
String KEY_FEED_LAST_ENTRY = "feedLastEntryTime"; String KEY_FEED_LAST_ENTRY = "feedLastEntryTime";

View File

@@ -14,27 +14,16 @@ public interface ForumConstants {
*/ */
int FORUM_SALT_LENGTH = 32; int FORUM_SALT_LENGTH = 32;
/**
* The maximum length of a forum post's content type in UTF-8 bytes.
*/
int MAX_CONTENT_TYPE_LENGTH = 50;
/** /**
* The maximum length of a forum post's body in bytes. * The maximum length of a forum post's body in bytes.
*/ */
int MAX_FORUM_POST_BODY_LENGTH = MAX_MESSAGE_BODY_LENGTH - 1024; int MAX_FORUM_POST_BODY_LENGTH = MAX_MESSAGE_BODY_LENGTH - 1024;
/* Forum Sharing Constants */ // Metadata keys
String FORUM_NAME = "forumName";
String FORUM_SALT = "forumSalt";
// Database keys
String KEY_TIMESTAMP = "timestamp"; String KEY_TIMESTAMP = "timestamp";
String KEY_PARENT = "parent"; String KEY_PARENT = "parent";
String KEY_ID = "id";
String KEY_NAME = "name";
String KEY_PUBLIC_NAME = "publicKey";
String KEY_AUTHOR = "author"; String KEY_AUTHOR = "author";
String KEY_LOCAL = "local"; String KEY_LOCAL = "local";
String KEY_READ = "read";
} }

View File

@@ -11,12 +11,12 @@ public interface PrivateGroupFactory {
/** /**
* Creates a private group with the given name and author. * Creates a private group with the given name and author.
*/ */
PrivateGroup createPrivateGroup(String name, Author author); PrivateGroup createPrivateGroup(String name, Author creator);
/** /**
* Creates a private group with the given name, author and salt. * Creates a private group with the given name, author and salt.
*/ */
PrivateGroup createPrivateGroup(String name, Author author, byte[] salt); PrivateGroup createPrivateGroup(String name, Author creator, byte[] salt);
/** /**
* Parses a group and returns the corresponding PrivateGroup. * Parses a group and returns the corresponding PrivateGroup.

View File

@@ -4,7 +4,6 @@ import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupFactory; import org.briarproject.bramble.api.sync.GroupFactory;
@@ -14,8 +13,7 @@ import org.briarproject.briar.api.blog.BlogFactory;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.util.ValidationUtils.checkSize;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID; import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID;
import static org.briarproject.briar.api.blog.BlogManager.CLIENT_VERSION; import static org.briarproject.briar.api.blog.BlogManager.CLIENT_VERSION;
@@ -24,15 +22,12 @@ import static org.briarproject.briar.api.blog.BlogManager.CLIENT_VERSION;
class BlogFactoryImpl implements BlogFactory { class BlogFactoryImpl implements BlogFactory {
private final GroupFactory groupFactory; private final GroupFactory groupFactory;
private final AuthorFactory authorFactory;
private final ClientHelper clientHelper; private final ClientHelper clientHelper;
@Inject @Inject
BlogFactoryImpl(GroupFactory groupFactory, AuthorFactory authorFactory, BlogFactoryImpl(GroupFactory groupFactory, ClientHelper clientHelper) {
ClientHelper clientHelper) {
this.groupFactory = groupFactory; this.groupFactory = groupFactory;
this.authorFactory = authorFactory;
this.clientHelper = clientHelper; this.clientHelper = clientHelper;
} }
@@ -48,11 +43,7 @@ class BlogFactoryImpl implements BlogFactory {
private Blog createBlog(Author a, boolean rssFeed) { private Blog createBlog(Author a, boolean rssFeed) {
try { try {
BdfList blog = BdfList.of( BdfList blog = BdfList.of(clientHelper.toList(a), rssFeed);
a.getName(),
a.getPublicKey(),
rssFeed
);
byte[] descriptor = clientHelper.toByteArray(blog); byte[] descriptor = clientHelper.toByteArray(blog);
Group g = groupFactory.createGroup(CLIENT_ID, CLIENT_VERSION, Group g = groupFactory.createGroup(CLIENT_ID, CLIENT_VERSION,
descriptor); descriptor);
@@ -63,20 +54,15 @@ class BlogFactoryImpl implements BlogFactory {
} }
@Override @Override
public Blog parseBlog(Group group) throws FormatException { public Blog parseBlog(Group g) throws FormatException {
byte[] descriptor = group.getDescriptor(); // Author, RSS feed
// Author name, public key, RSS feed BdfList descriptor = clientHelper.toList(g.getDescriptor());
BdfList blog = clientHelper.toList(descriptor); checkSize(descriptor, 2);
String name = blog.getString(0); BdfList authorList = descriptor.getList(0);
if (name.length() > MAX_AUTHOR_NAME_LENGTH) boolean rssFeed = descriptor.getBoolean(1);
throw new IllegalArgumentException();
byte[] publicKey = blog.getRaw(1);
if (publicKey.length > MAX_PUBLIC_KEY_LENGTH)
throw new IllegalArgumentException();
Author author = authorFactory.createAuthor(name, publicKey); Author author = clientHelper.parseAndValidateAuthor(authorList);
boolean rssFeed = blog.getBoolean(2); return new Blog(g, author, rssFeed);
return new Blog(group, author, rssFeed);
} }
} }

View File

@@ -50,13 +50,10 @@ import javax.inject.Inject;
import static org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook; import static org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR; import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_NAME;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_COMMENT; import static org.briarproject.briar.api.blog.BlogConstants.KEY_COMMENT;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_MSG_ID; import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_MSG_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_PARENT_MSG_ID; import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_PARENT_MSG_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID; import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PUBLIC_KEY;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ; import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_RSS_FEED; import static org.briarproject.briar.api.blog.BlogConstants.KEY_RSS_FEED;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIMESTAMP; import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIMESTAMP;
@@ -66,7 +63,6 @@ import static org.briarproject.briar.api.blog.MessageType.COMMENT;
import static org.briarproject.briar.api.blog.MessageType.POST; import static org.briarproject.briar.api.blog.MessageType.POST;
import static org.briarproject.briar.api.blog.MessageType.WRAPPED_COMMENT; import static org.briarproject.briar.api.blog.MessageType.WRAPPED_COMMENT;
import static org.briarproject.briar.api.blog.MessageType.WRAPPED_POST; import static org.briarproject.briar.api.blog.MessageType.WRAPPED_POST;
import static org.briarproject.briar.blog.BlogPostValidator.authorToBdfDictionary;
@NotNullByDefault @NotNullByDefault
class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager, class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
@@ -227,7 +223,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put(KEY_TYPE, POST.getInt()); meta.put(KEY_TYPE, POST.getInt());
meta.put(KEY_TIMESTAMP, p.getMessage().getTimestamp()); meta.put(KEY_TIMESTAMP, p.getMessage().getTimestamp());
meta.put(KEY_AUTHOR, authorToBdfDictionary(p.getAuthor())); meta.put(KEY_AUTHOR, clientHelper.toList(p.getAuthor()));
meta.put(KEY_READ, true); meta.put(KEY_READ, true);
meta.put(KEY_RSS_FEED, b.isRssFeed()); meta.put(KEY_RSS_FEED, b.isRssFeed());
clientHelper.addLocalMessage(txn, p.getMessage(), meta, true); clientHelper.addLocalMessage(txn, p.getMessage(), meta, true);
@@ -270,7 +266,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
meta.put(KEY_ORIGINAL_MSG_ID, message.getId()); meta.put(KEY_ORIGINAL_MSG_ID, message.getId());
meta.put(KEY_ORIGINAL_PARENT_MSG_ID, parentOriginalId); meta.put(KEY_ORIGINAL_PARENT_MSG_ID, parentOriginalId);
meta.put(KEY_PARENT_MSG_ID, parentCurrentId); meta.put(KEY_PARENT_MSG_ID, parentCurrentId);
meta.put(KEY_AUTHOR, authorToBdfDictionary(author)); meta.put(KEY_AUTHOR, clientHelper.toList(author));
// Send comment // Send comment
clientHelper.addLocalMessage(txn, message, meta, true); clientHelper.addLocalMessage(txn, message, meta, true);
@@ -367,7 +363,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
"Unknown Message Type: " + type); "Unknown Message Type: " + type);
} }
meta.put(KEY_ORIGINAL_MSG_ID, originalId); meta.put(KEY_ORIGINAL_MSG_ID, originalId);
meta.put(KEY_AUTHOR, authorToBdfDictionary(header.getAuthor())); meta.put(KEY_AUTHOR, clientHelper.toList(header.getAuthor()));
meta.put(KEY_TIMESTAMP, header.getTimestamp()); meta.put(KEY_TIMESTAMP, header.getTimestamp());
meta.put(KEY_TIME_RECEIVED, header.getTimeReceived()); meta.put(KEY_TIME_RECEIVED, header.getTimeReceived());
@@ -506,9 +502,9 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
// get all authors we need to get the status for // get all authors we need to get the status for
Set<AuthorId> authors = new HashSet<>(); Set<AuthorId> authors = new HashSet<>();
for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) { for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
authors.add(new AuthorId( BdfList authorList = entry.getValue().getList(KEY_AUTHOR);
entry.getValue().getDictionary(KEY_AUTHOR) Author a = clientHelper.parseAndValidateAuthor(authorList);
.getRaw(KEY_AUTHOR_ID))); authors.add(a.getId());
} }
// get statuses for all authors // get statuses for all authors
Map<AuthorId, Status> authorStatuses = new HashMap<>(); Map<AuthorId, Status> authorStatuses = new HashMap<>();
@@ -573,19 +569,16 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
long timestamp = meta.getLong(KEY_TIMESTAMP); long timestamp = meta.getLong(KEY_TIMESTAMP);
long timeReceived = meta.getLong(KEY_TIME_RECEIVED, timestamp); long timeReceived = meta.getLong(KEY_TIME_RECEIVED, timestamp);
BdfDictionary d = meta.getDictionary(KEY_AUTHOR); BdfList authorList = meta.getList(KEY_AUTHOR);
AuthorId authorId = new AuthorId(d.getRaw(KEY_AUTHOR_ID)); Author author = clientHelper.parseAndValidateAuthor(authorList);
String name = d.getString(KEY_AUTHOR_NAME);
byte[] publicKey = d.getRaw(KEY_PUBLIC_KEY);
Author author = new Author(authorId, name, publicKey);
boolean isFeedPost = meta.getBoolean(KEY_RSS_FEED, false); boolean isFeedPost = meta.getBoolean(KEY_RSS_FEED, false);
Status authorStatus; Status authorStatus;
if (isFeedPost) { if (isFeedPost) {
authorStatus = Status.NONE; authorStatus = Status.NONE;
} else if (authorStatuses.containsKey(authorId)) { } else if (authorStatuses.containsKey(author.getId())) {
authorStatus = authorStatuses.get(authorId); authorStatus = authorStatuses.get(author.getId());
} else { } else {
authorStatus = identityManager.getAuthorStatus(txn, authorId); authorStatus = identityManager.getAuthorStatus(txn, author.getId());
} }
boolean read = meta.getBoolean(KEY_READ, false); boolean read = meta.getBoolean(KEY_READ, false);

View File

@@ -3,7 +3,6 @@ package org.briarproject.briar.blog;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.sync.GroupFactory; import org.briarproject.bramble.api.sync.GroupFactory;
import org.briarproject.bramble.api.sync.MessageFactory; import org.briarproject.bramble.api.sync.MessageFactory;
@@ -44,15 +43,14 @@ public class BlogModule {
} }
@Provides @Provides
BlogPostFactory provideBlogPostFactory(ClientHelper clientHelper, BlogPostFactory provideBlogPostFactory(
Clock clock) { BlogPostFactoryImpl blogPostFactory) {
return new BlogPostFactoryImpl(clientHelper, clock); return blogPostFactory;
} }
@Provides @Provides
BlogFactory provideBlogFactory(GroupFactory groupFactory, BlogFactory provideBlogFactory(BlogFactoryImpl blogFactory) {
AuthorFactory authorFactory, ClientHelper clientHelper) { return blogFactory;
return new BlogFactoryImpl(groupFactory, authorFactory, clientHelper);
} }
@Provides @Provides

View File

@@ -5,7 +5,6 @@ import org.briarproject.bramble.api.client.BdfMessageContext;
import org.briarproject.bramble.api.client.BdfMessageValidator; import org.briarproject.bramble.api.client.BdfMessageValidator;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.data.BdfDictionary; 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.BdfList;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
@@ -31,13 +30,10 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATUR
import static org.briarproject.bramble.util.ValidationUtils.checkLength; import static org.briarproject.bramble.util.ValidationUtils.checkLength;
import static org.briarproject.bramble.util.ValidationUtils.checkSize; import static org.briarproject.bramble.util.ValidationUtils.checkSize;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR; import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_NAME;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_COMMENT; import static org.briarproject.briar.api.blog.BlogConstants.KEY_COMMENT;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_MSG_ID; import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_MSG_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_PARENT_MSG_ID; import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_PARENT_MSG_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID; import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PUBLIC_KEY;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ; import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_RSS_FEED; import static org.briarproject.briar.api.blog.BlogConstants.KEY_RSS_FEED;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIMESTAMP; import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIMESTAMP;
@@ -115,9 +111,8 @@ class BlogPostValidator extends BdfMessageValidator {
Blog b = blogFactory.parseBlog(g); Blog b = blogFactory.parseBlog(g);
Author a = b.getAuthor(); Author a = b.getAuthor();
try { try {
clientHelper clientHelper.verifySignature(SIGNING_LABEL_POST, sig,
.verifySignature(SIGNING_LABEL_POST, sig, a.getPublicKey(), a.getPublicKey(), signed);
signed);
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new InvalidMessageException(e); throw new InvalidMessageException(e);
} }
@@ -125,7 +120,7 @@ class BlogPostValidator extends BdfMessageValidator {
// Return the metadata and dependencies // Return the metadata and dependencies
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put(KEY_ORIGINAL_MSG_ID, m.getId()); meta.put(KEY_ORIGINAL_MSG_ID, m.getId());
meta.put(KEY_AUTHOR, authorToBdfDictionary(a)); meta.put(KEY_AUTHOR, clientHelper.toList(a));
meta.put(KEY_RSS_FEED, b.isRssFeed()); meta.put(KEY_RSS_FEED, b.isRssFeed());
return new BdfMessageContext(meta); return new BdfMessageContext(meta);
} }
@@ -156,10 +151,9 @@ class BlogPostValidator extends BdfMessageValidator {
// Signature // Signature
byte[] sig = body.getRaw(3); byte[] sig = body.getRaw(3);
checkLength(sig, 0, MAX_SIGNATURE_LENGTH); checkLength(sig, 1, MAX_SIGNATURE_LENGTH);
BdfList signed = BdfList signed = BdfList.of(g.getId(), m.getTimestamp(), comment,
BdfList.of(g.getId(), m.getTimestamp(), comment, pOriginalId, pOriginalId, currentId);
currentId);
Blog b = blogFactory.parseBlog(g); Blog b = blogFactory.parseBlog(g);
Author a = b.getAuthor(); Author a = b.getAuthor();
try { try {
@@ -175,7 +169,7 @@ class BlogPostValidator extends BdfMessageValidator {
meta.put(KEY_ORIGINAL_MSG_ID, m.getId()); meta.put(KEY_ORIGINAL_MSG_ID, m.getId());
meta.put(KEY_ORIGINAL_PARENT_MSG_ID, pOriginalId); meta.put(KEY_ORIGINAL_PARENT_MSG_ID, pOriginalId);
meta.put(KEY_PARENT_MSG_ID, currentId); meta.put(KEY_PARENT_MSG_ID, currentId);
meta.put(KEY_AUTHOR, authorToBdfDictionary(a)); meta.put(KEY_AUTHOR, clientHelper.toList(a));
Collection<MessageId> dependencies = Collections.singleton(currentId); Collection<MessageId> dependencies = Collections.singleton(currentId);
return new BdfMessageContext(meta, dependencies); return new BdfMessageContext(meta, dependencies);
} }
@@ -215,7 +209,7 @@ class BlogPostValidator extends BdfMessageValidator {
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put(KEY_ORIGINAL_MSG_ID, wMessage.getId()); meta.put(KEY_ORIGINAL_MSG_ID, wMessage.getId());
meta.put(KEY_TIMESTAMP, wTimestamp); meta.put(KEY_TIMESTAMP, wTimestamp);
meta.put(KEY_AUTHOR, c.getDictionary().getDictionary(KEY_AUTHOR)); meta.put(KEY_AUTHOR, c.getDictionary().getList(KEY_AUTHOR));
meta.put(KEY_RSS_FEED, wBlog.isRssFeed()); meta.put(KEY_RSS_FEED, wBlog.isRssFeed());
return new BdfMessageContext(meta); return new BdfMessageContext(meta);
} }
@@ -282,18 +276,10 @@ class BlogPostValidator extends BdfMessageValidator {
meta.put(KEY_PARENT_MSG_ID, parentId); meta.put(KEY_PARENT_MSG_ID, parentId);
meta.put(KEY_TIMESTAMP, wTimestamp); meta.put(KEY_TIMESTAMP, wTimestamp);
if (comment != null) meta.put(KEY_COMMENT, comment); if (comment != null) meta.put(KEY_COMMENT, comment);
meta.put(KEY_AUTHOR, c.getDictionary().getDictionary(KEY_AUTHOR)); meta.put(KEY_AUTHOR, c.getDictionary().getList(KEY_AUTHOR));
return new BdfMessageContext(meta, dependencies); return new BdfMessageContext(meta, dependencies);
} }
static BdfDictionary authorToBdfDictionary(Author a) {
return BdfDictionary.of(
new BdfEntry(KEY_AUTHOR_ID, a.getId()),
new BdfEntry(KEY_AUTHOR_NAME, a.getName()),
new BdfEntry(KEY_PUBLIC_KEY, a.getPublicKey())
);
}
private void addMessageMetadata(BdfMessageContext c, long time) { private void addMessageMetadata(BdfMessageContext c, long time) {
c.getDictionary().put(KEY_TIMESTAMP, time); c.getDictionary().put(KEY_TIMESTAMP, time);
c.getDictionary().put(KEY_TIME_RECEIVED, clock.currentTimeMillis()); c.getDictionary().put(KEY_TIME_RECEIVED, clock.currentTimeMillis());

View File

@@ -3,10 +3,13 @@ package org.briarproject.briar.feed;
import com.rometools.rome.feed.synd.SyndFeed; import com.rometools.rome.feed.synd.SyndFeed;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair; import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry; import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
@@ -18,29 +21,31 @@ import org.briarproject.briar.api.feed.Feed;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_BLOG_TITLE;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_ADDED; import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_ADDED;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_AUTHOR; import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_AUTHOR;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_DESC; import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_DESC;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_LAST_ENTRY; import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_LAST_ENTRY;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_PRIVATE_KEY;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_RSS_AUTHOR;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_UPDATED; import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_UPDATED;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_URL; import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_URL;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_PRIVATE_KEY;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_PUBLIC_KEY;
class FeedFactoryImpl implements FeedFactory { class FeedFactoryImpl implements FeedFactory {
private final CryptoComponent cryptoComponent; private final CryptoComponent cryptoComponent;
private final AuthorFactory authorFactory; private final AuthorFactory authorFactory;
private final BlogFactory blogFactory; private final BlogFactory blogFactory;
private final ClientHelper clientHelper;
private final Clock clock; private final Clock clock;
@Inject @Inject
FeedFactoryImpl(CryptoComponent cryptoComponent, FeedFactoryImpl(CryptoComponent cryptoComponent,
AuthorFactory authorFactory, BlogFactory blogFactory, Clock clock) { AuthorFactory authorFactory, BlogFactory blogFactory,
ClientHelper clientHelper, Clock clock) {
this.cryptoComponent = cryptoComponent; this.cryptoComponent = cryptoComponent;
this.authorFactory = authorFactory; this.authorFactory = authorFactory;
this.blogFactory = blogFactory; this.blogFactory = blogFactory;
this.clientHelper = clientHelper;
this.clock = clock; this.clock = clock;
} }
@@ -48,13 +53,12 @@ class FeedFactoryImpl implements FeedFactory {
public Feed createFeed(String url, SyndFeed syndFeed) { public Feed createFeed(String url, SyndFeed syndFeed) {
String title = syndFeed.getTitle(); String title = syndFeed.getTitle();
if (title == null) title = "RSS"; if (title == null) title = "RSS";
title = StringUtils.truncateUtf8(title, MAX_AUTHOR_NAME_LENGTH); else title = StringUtils.truncateUtf8(title, MAX_AUTHOR_NAME_LENGTH);
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair(); KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
LocalAuthor localAuthor = authorFactory LocalAuthor localAuthor = authorFactory.createLocalAuthor(title,
.createLocalAuthor(title, keyPair.getPublic().getEncoded(),
keyPair.getPublic().getEncoded(), keyPair.getPrivate().getEncoded());
keyPair.getPrivate().getEncoded());
Blog blog = blogFactory.createFeedBlog(localAuthor); Blog blog = blogFactory.createFeedBlog(localAuthor);
long added = clock.currentTimeMillis(); long added = clock.currentTimeMillis();
@@ -73,39 +77,40 @@ class FeedFactoryImpl implements FeedFactory {
public Feed createFeed(BdfDictionary d) throws FormatException { public Feed createFeed(BdfDictionary d) throws FormatException {
String url = d.getString(KEY_FEED_URL); String url = d.getString(KEY_FEED_URL);
String blogTitle = d.getString(KEY_BLOG_TITLE); BdfList authorList = d.getList(KEY_FEED_AUTHOR);
byte[] publicKey = d.getRaw(KEY_PUBLIC_KEY); byte[] privateKey = d.getRaw(KEY_FEED_PRIVATE_KEY);
byte[] privateKey = d.getRaw(KEY_PRIVATE_KEY); Author author = clientHelper.parseAndValidateAuthor(authorList);
LocalAuthor localAuthor = authorFactory LocalAuthor localAuthor = authorFactory.createLocalAuthor(
.createLocalAuthor(blogTitle, publicKey, privateKey); author.getFormatVersion(), author.getName(),
author.getPublicKey(), privateKey);
Blog blog = blogFactory.createFeedBlog(localAuthor); Blog blog = blogFactory.createFeedBlog(localAuthor);
String desc = d.getOptionalString(KEY_FEED_DESC); String desc = d.getOptionalString(KEY_FEED_DESC);
String author = d.getOptionalString(KEY_FEED_AUTHOR); String rssAuthor = d.getOptionalString(KEY_FEED_RSS_AUTHOR);
long added = d.getLong(KEY_FEED_ADDED, 0L); long added = d.getLong(KEY_FEED_ADDED, 0L);
long updated = d.getLong(KEY_FEED_UPDATED, 0L); long updated = d.getLong(KEY_FEED_UPDATED, 0L);
long lastEntryTime = d.getLong(KEY_FEED_LAST_ENTRY, 0L); long lastEntryTime = d.getLong(KEY_FEED_LAST_ENTRY, 0L);
return new Feed(url, blog, localAuthor, desc, author, added, return new Feed(url, blog, localAuthor, desc, rssAuthor, added,
updated, lastEntryTime); updated, lastEntryTime);
} }
@Override @Override
public BdfDictionary feedToBdfDictionary(Feed feed) { public BdfDictionary feedToBdfDictionary(Feed feed) {
LocalAuthor localAuthor = feed.getLocalAuthor();
BdfList authorList = clientHelper.toList(localAuthor);
BdfDictionary d = BdfDictionary.of( BdfDictionary d = BdfDictionary.of(
new BdfEntry(KEY_FEED_URL, feed.getUrl()), new BdfEntry(KEY_FEED_URL, feed.getUrl()),
new BdfEntry(KEY_BLOG_TITLE, feed.getLocalAuthor().getName()), new BdfEntry(KEY_FEED_AUTHOR, authorList),
new BdfEntry(KEY_PUBLIC_KEY, new BdfEntry(KEY_FEED_PRIVATE_KEY, localAuthor.getPrivateKey()),
feed.getLocalAuthor().getPublicKey()),
new BdfEntry(KEY_PRIVATE_KEY,
feed.getLocalAuthor().getPrivateKey()),
new BdfEntry(KEY_FEED_ADDED, feed.getAdded()), new BdfEntry(KEY_FEED_ADDED, feed.getAdded()),
new BdfEntry(KEY_FEED_UPDATED, feed.getUpdated()), new BdfEntry(KEY_FEED_UPDATED, feed.getUpdated()),
new BdfEntry(KEY_FEED_LAST_ENTRY, feed.getLastEntryTime()) new BdfEntry(KEY_FEED_LAST_ENTRY, feed.getLastEntryTime())
); );
if (feed.getDescription() != null) if (feed.getDescription() != null)
d.put(KEY_FEED_DESC, feed.getDescription()); d.put(KEY_FEED_DESC, feed.getDescription());
if (feed.getAuthor() != null) d.put(KEY_FEED_AUTHOR, feed.getAuthor()); if (feed.getRssAuthor() != null)
d.put(KEY_FEED_RSS_AUTHOR, feed.getRssAuthor());
return d; return d;
} }

View File

@@ -31,7 +31,6 @@ class ForumFactoryImpl implements ForumFactory {
@Inject @Inject
ForumFactoryImpl(GroupFactory groupFactory, ClientHelper clientHelper, ForumFactoryImpl(GroupFactory groupFactory, ClientHelper clientHelper,
SecureRandom random) { SecureRandom random) {
this.groupFactory = groupFactory; this.groupFactory = groupFactory;
this.clientHelper = clientHelper; this.clientHelper = clientHelper;
this.random = random; this.random = random;

View File

@@ -47,11 +47,8 @@ import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES; import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
import static org.briarproject.briar.api.forum.ForumConstants.KEY_AUTHOR; import static org.briarproject.briar.api.forum.ForumConstants.KEY_AUTHOR;
import static org.briarproject.briar.api.forum.ForumConstants.KEY_ID;
import static org.briarproject.briar.api.forum.ForumConstants.KEY_LOCAL; import static org.briarproject.briar.api.forum.ForumConstants.KEY_LOCAL;
import static org.briarproject.briar.api.forum.ForumConstants.KEY_NAME;
import static org.briarproject.briar.api.forum.ForumConstants.KEY_PARENT; import static org.briarproject.briar.api.forum.ForumConstants.KEY_PARENT;
import static org.briarproject.briar.api.forum.ForumConstants.KEY_PUBLIC_NAME;
import static org.briarproject.briar.api.forum.ForumConstants.KEY_TIMESTAMP; import static org.briarproject.briar.api.forum.ForumConstants.KEY_TIMESTAMP;
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ; import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
@@ -147,11 +144,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
meta.put(KEY_TIMESTAMP, p.getMessage().getTimestamp()); meta.put(KEY_TIMESTAMP, p.getMessage().getTimestamp());
if (p.getParent() != null) meta.put(KEY_PARENT, p.getParent()); if (p.getParent() != null) meta.put(KEY_PARENT, p.getParent());
Author a = p.getAuthor(); Author a = p.getAuthor();
BdfDictionary authorMeta = new BdfDictionary(); meta.put(KEY_AUTHOR, clientHelper.toList(a));
authorMeta.put(KEY_ID, a.getId());
authorMeta.put(KEY_NAME, a.getName());
authorMeta.put(KEY_PUBLIC_NAME, a.getPublicKey());
meta.put(KEY_AUTHOR, authorMeta);
meta.put(KEY_LOCAL, true); meta.put(KEY_LOCAL, true);
meta.put(MSG_KEY_READ, true); meta.put(MSG_KEY_READ, true);
clientHelper.addLocalMessage(txn, p.getMessage(), meta, true); clientHelper.addLocalMessage(txn, p.getMessage(), meta, true);
@@ -237,10 +230,9 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
// get all authors we need to get the status for // get all authors we need to get the status for
Set<AuthorId> authors = new HashSet<>(); Set<AuthorId> authors = new HashSet<>();
for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) { for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
BdfDictionary d = BdfList authorList = entry.getValue().getList(KEY_AUTHOR);
entry.getValue().getDictionary(KEY_AUTHOR, null); Author a = clientHelper.parseAndValidateAuthor(authorList);
if (d != null) authors.add(a.getId());
authors.add(new AuthorId(d.getRaw(KEY_ID)));
} }
// get statuses for all authors // get statuses for all authors
Map<AuthorId, Status> statuses = new HashMap<>(); Map<AuthorId, Status> statuses = new HashMap<>();
@@ -298,12 +290,9 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager {
MessageId parentId = null; MessageId parentId = null;
if (meta.containsKey(KEY_PARENT)) if (meta.containsKey(KEY_PARENT))
parentId = new MessageId(meta.getRaw(KEY_PARENT)); parentId = new MessageId(meta.getRaw(KEY_PARENT));
BdfDictionary authorDict = meta.getDictionary(KEY_AUTHOR); BdfList authorList = meta.getList(KEY_AUTHOR);
AuthorId authorId = new AuthorId(authorDict.getRaw(KEY_ID)); Author author = clientHelper.parseAndValidateAuthor(authorList);
String name = authorDict.getString(KEY_NAME); Status status = statuses.get(author.getId());
byte[] publicKey = authorDict.getRaw(KEY_PUBLIC_NAME);
Author author = new Author(authorId, name, publicKey);
Status status = statuses.get(authorId);
if (status == null) if (status == null)
status = identityManager.getAuthorStatus(txn, author.getId()); status = identityManager.getAuthorStatus(txn, author.getId());
boolean read = meta.getBoolean(MSG_KEY_READ); boolean read = meta.getBoolean(MSG_KEY_READ);

View File

@@ -2,16 +2,12 @@ package org.briarproject.briar.forum;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.sync.GroupFactory;
import org.briarproject.bramble.api.sync.ValidationManager; import org.briarproject.bramble.api.sync.ValidationManager;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.briar.api.forum.ForumFactory; import org.briarproject.briar.api.forum.ForumFactory;
import org.briarproject.briar.api.forum.ForumManager; import org.briarproject.briar.api.forum.ForumManager;
import org.briarproject.briar.api.forum.ForumPostFactory; import org.briarproject.briar.api.forum.ForumPostFactory;
import java.security.SecureRandom;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -34,10 +30,8 @@ public class ForumModule {
@Singleton @Singleton
ForumManager provideForumManager(ForumManagerImpl forumManager, ForumManager provideForumManager(ForumManagerImpl forumManager,
ValidationManager validationManager) { ValidationManager validationManager) {
validationManager.registerIncomingMessageHook(CLIENT_ID, validationManager.registerIncomingMessageHook(CLIENT_ID,
forumManager); forumManager);
return forumManager; return forumManager;
} }
@@ -48,19 +42,17 @@ public class ForumModule {
} }
@Provides @Provides
ForumFactory provideForumFactory(GroupFactory groupFactory, ForumFactory provideForumFactory(ForumFactoryImpl forumFactory) {
ClientHelper clientHelper, SecureRandom random) { return forumFactory;
return new ForumFactoryImpl(groupFactory, clientHelper, random);
} }
@Provides @Provides
@Singleton @Singleton
ForumPostValidator provideForumPostValidator( ForumPostValidator provideForumPostValidator(
ValidationManager validationManager, AuthorFactory authorFactory, ValidationManager validationManager, ClientHelper clientHelper,
ClientHelper clientHelper, MetadataEncoder metadataEncoder, MetadataEncoder metadataEncoder, Clock clock) {
Clock clock) { ForumPostValidator validator = new ForumPostValidator(clientHelper,
ForumPostValidator validator = new ForumPostValidator(authorFactory, metadataEncoder, clock);
clientHelper, metadataEncoder, clock);
validationManager.registerMessageValidator(CLIENT_ID, validator); validationManager.registerMessageValidator(CLIENT_ID, validator);
return validator; return validator;
} }

View File

@@ -39,8 +39,7 @@ class ForumPostFactoryImpl implements ForumPostFactory {
if (StringUtils.utf8IsTooLong(body, MAX_FORUM_POST_BODY_LENGTH)) if (StringUtils.utf8IsTooLong(body, MAX_FORUM_POST_BODY_LENGTH))
throw new IllegalArgumentException(); throw new IllegalArgumentException();
// Serialise the data to be signed // Serialise the data to be signed
BdfList authorList = BdfList authorList = clientHelper.toList(author);
BdfList.of(author.getName(), author.getPublicKey());
BdfList signed = BdfList.of(groupId, timestamp, parent, authorList, BdfList signed = BdfList.of(groupId, timestamp, parent, authorList,
body); body);
// Sign the data // Sign the data

View File

@@ -9,7 +9,6 @@ import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.InvalidMessageException; import org.briarproject.bramble.api.sync.InvalidMessageException;
@@ -23,11 +22,13 @@ import java.util.Collections;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.util.ValidationUtils.checkLength; import static org.briarproject.bramble.util.ValidationUtils.checkLength;
import static org.briarproject.bramble.util.ValidationUtils.checkSize; import static org.briarproject.bramble.util.ValidationUtils.checkSize;
import static org.briarproject.briar.api.forum.ForumConstants.KEY_AUTHOR;
import static org.briarproject.briar.api.forum.ForumConstants.KEY_PARENT;
import static org.briarproject.briar.api.forum.ForumConstants.KEY_READ;
import static org.briarproject.briar.api.forum.ForumConstants.KEY_TIMESTAMP;
import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH; import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
import static org.briarproject.briar.api.forum.ForumPostFactory.SIGNING_LABEL_POST; import static org.briarproject.briar.api.forum.ForumPostFactory.SIGNING_LABEL_POST;
@@ -35,12 +36,9 @@ import static org.briarproject.briar.api.forum.ForumPostFactory.SIGNING_LABEL_PO
@NotNullByDefault @NotNullByDefault
class ForumPostValidator extends BdfMessageValidator { class ForumPostValidator extends BdfMessageValidator {
private final AuthorFactory authorFactory; ForumPostValidator(ClientHelper clientHelper,
ForumPostValidator(AuthorFactory authorFactory, ClientHelper clientHelper,
MetadataEncoder metadataEncoder, Clock clock) { MetadataEncoder metadataEncoder, Clock clock) {
super(clientHelper, metadataEncoder, clock); super(clientHelper, metadataEncoder, clock);
this.authorFactory = authorFactory;
} }
@Override @Override
@@ -55,24 +53,18 @@ class ForumPostValidator extends BdfMessageValidator {
// Author // Author
BdfList authorList = body.getList(1); BdfList authorList = body.getList(1);
// Name, public key Author author = clientHelper.parseAndValidateAuthor(authorList);
checkSize(authorList, 2);
String name = authorList.getString(0);
checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH);
byte[] publicKey = authorList.getRaw(1);
checkLength(publicKey, 0, MAX_PUBLIC_KEY_LENGTH);
Author author = authorFactory.createAuthor(name, publicKey);
// Forum post body // Forum post body
String forumPostBody = body.getString(2); String content = body.getString(2);
checkLength(forumPostBody, 0, MAX_FORUM_POST_BODY_LENGTH); checkLength(content, 0, MAX_FORUM_POST_BODY_LENGTH);
// Signature // Signature
byte[] sig = body.getRaw(3); byte[] sig = body.getRaw(3);
checkLength(sig, 0, MAX_SIGNATURE_LENGTH); checkLength(sig, 1, MAX_SIGNATURE_LENGTH);
// Verify the signature // Verify the signature
BdfList signed = BdfList.of(g.getId(), m.getTimestamp(), parent, BdfList signed = BdfList.of(g.getId(), m.getTimestamp(), parent,
authorList, forumPostBody); authorList, content);
try { try {
clientHelper.verifySignature(SIGNING_LABEL_POST, sig, clientHelper.verifySignature(SIGNING_LABEL_POST, sig,
author.getPublicKey(), signed); author.getPublicKey(), signed);
@@ -83,17 +75,13 @@ class ForumPostValidator extends BdfMessageValidator {
// Return the metadata and dependencies // Return the metadata and dependencies
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
Collection<MessageId> dependencies = Collections.emptyList(); Collection<MessageId> dependencies = Collections.emptyList();
meta.put("timestamp", m.getTimestamp()); meta.put(KEY_TIMESTAMP, m.getTimestamp());
if (parent != null) { if (parent != null) {
meta.put("parent", parent); meta.put(KEY_PARENT, parent);
dependencies = Collections.singletonList(new MessageId(parent)); dependencies = Collections.singletonList(new MessageId(parent));
} }
BdfDictionary authorMeta = new BdfDictionary(); meta.put(KEY_AUTHOR, authorList);
authorMeta.put("id", author.getId()); meta.put(KEY_READ, false);
authorMeta.put("name", author.getName());
authorMeta.put("publicKey", author.getPublicKey());
meta.put("author", authorMeta);
meta.put("read", false);
return new BdfMessageContext(meta, dependencies); return new BdfMessageContext(meta, dependencies);
} }
} }

View File

@@ -169,6 +169,7 @@ class IntroduceeManager {
d.put(ANSWERED, false); d.put(ANSWERED, false);
// check if the contact we are introduced to does already exist // check if the contact we are introduced to does already exist
// TODO: Exchange author format version
AuthorId remoteAuthorId = authorFactory AuthorId remoteAuthorId = authorFactory
.createAuthor(message.getString(NAME), .createAuthor(message.getString(NAME),
message.getRaw(PUBLIC_KEY)).getId(); message.getRaw(PUBLIC_KEY)).getId();
@@ -339,6 +340,7 @@ class IntroduceeManager {
long timestamp = Math.min(ourTime, theirTime); long timestamp = Math.min(ourTime, theirTime);
// Add the contact to the database as inactive // Add the contact to the database as inactive
// TODO: Exchange author format version
Author remoteAuthor = authorFactory Author remoteAuthor = authorFactory
.createAuthor(localState.getString(NAME), .createAuthor(localState.getString(NAME),
localState.getRaw(PUBLIC_KEY)); localState.getRaw(PUBLIC_KEY));

View File

@@ -87,6 +87,8 @@ class IntroductionValidator extends BdfQueueMessageValidator {
checkSize(message, 4, 5); checkSize(message, 4, 5);
// TODO: Exchange author format version
// parse contact name // parse contact name
String name = message.getString(2); String name = message.getString(2);
checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH); checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH);
@@ -131,7 +133,7 @@ class IntroductionValidator extends BdfQueueMessageValidator {
// parse ephemeral public key // parse ephemeral public key
pubkey = message.getRaw(4); pubkey = message.getRaw(4);
checkLength(pubkey, 0, MAX_PUBLIC_KEY_LENGTH); checkLength(pubkey, 1, MAX_PUBLIC_KEY_LENGTH);
// parse transport properties // parse transport properties
tp = message.getDictionary(5); tp = message.getDictionary(5);

View File

@@ -4,15 +4,13 @@ import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ
interface GroupConstants { interface GroupConstants {
// Database keys // Metadata keys
String KEY_TYPE = "type"; String KEY_TYPE = "type";
String KEY_TIMESTAMP = "timestamp"; String KEY_TIMESTAMP = "timestamp";
String KEY_READ = MSG_KEY_READ; String KEY_READ = MSG_KEY_READ;
String KEY_PARENT_MSG_ID = "parentMsgId"; String KEY_PARENT_MSG_ID = "parentMsgId";
String KEY_PREVIOUS_MSG_ID = "previousMsgId"; String KEY_PREVIOUS_MSG_ID = "previousMsgId";
String KEY_MEMBER_ID = "memberId"; String KEY_MEMBER = "member";
String KEY_MEMBER_NAME = "memberName";
String KEY_MEMBER_PUBLIC_KEY = "memberPublicKey";
String KEY_INITIAL_JOIN_MSG = "initialJoinMsg"; String KEY_INITIAL_JOIN_MSG = "initialJoinMsg";
String GROUP_KEY_MEMBERS = "members"; String GROUP_KEY_MEMBERS = "members";

View File

@@ -50,47 +50,65 @@ class GroupMessageFactoryImpl implements GroupMessageFactory {
LocalAuthor member, @Nullable BdfList invite) { LocalAuthor member, @Nullable BdfList invite) {
try { try {
// Generate the signature // Generate the signature
int type = JOIN.getInt(); BdfList memberList = clientHelper.toList(member);
BdfList toSign = BdfList.of(groupId, timestamp, type, BdfList toSign = BdfList.of(
member.getName(), member.getPublicKey(), invite); groupId,
byte[] memberSignature = clientHelper timestamp,
.sign(SIGNING_LABEL_JOIN, toSign, member.getPrivateKey()); memberList,
invite
);
byte[] memberSignature = clientHelper.sign(SIGNING_LABEL_JOIN,
toSign, member.getPrivateKey());
// Compose the message // Compose the message
BdfList body = BdfList body = BdfList.of(
BdfList.of(type, member.getName(), JOIN.getInt(),
member.getPublicKey(), invite, memberSignature); memberList,
invite,
memberSignature
);
Message m = clientHelper.createMessage(groupId, timestamp, body); Message m = clientHelper.createMessage(groupId, timestamp, body);
return new GroupMessage(m, null, member); return new GroupMessage(m, null, member);
} catch (GeneralSecurityException | FormatException e) { } catch (GeneralSecurityException e) {
throw new RuntimeException(e); throw new IllegalArgumentException(e);
} catch (FormatException e) {
throw new AssertionError(e);
} }
} }
@Override @Override
public GroupMessage createGroupMessage(GroupId groupId, long timestamp, public GroupMessage createGroupMessage(GroupId groupId, long timestamp,
@Nullable MessageId parentId, LocalAuthor author, String content, @Nullable MessageId parentId, LocalAuthor member, String content,
MessageId previousMsgId) { MessageId previousMsgId) {
try { try {
// Generate the signature // Generate the signature
int type = POST.getInt(); BdfList memberList = clientHelper.toList(member);
BdfList toSign = BdfList.of(groupId, timestamp, type, BdfList toSign = BdfList.of(
author.getName(), author.getPublicKey(), parentId, groupId,
previousMsgId, content); timestamp,
byte[] signature = clientHelper memberList,
.sign(SIGNING_LABEL_POST, toSign, author.getPrivateKey()); parentId,
previousMsgId,
content
);
byte[] signature = clientHelper.sign(SIGNING_LABEL_POST, toSign,
member.getPrivateKey());
// Compose the message // Compose the message
BdfList body = BdfList body = BdfList.of(
BdfList.of(type, author.getName(), POST.getInt(),
author.getPublicKey(), parentId, previousMsgId, memberList,
content, signature); parentId,
previousMsgId,
content,
signature
);
Message m = clientHelper.createMessage(groupId, timestamp, body); Message m = clientHelper.createMessage(groupId, timestamp, body);
return new GroupMessage(m, parentId, member);
return new GroupMessage(m, parentId, author); } catch (GeneralSecurityException e) {
} catch (GeneralSecurityException | FormatException e) { throw new IllegalArgumentException(e);
throw new RuntimeException(e); } catch (FormatException e) {
throw new AssertionError(e);
} }
} }

View File

@@ -8,7 +8,6 @@ import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.InvalidMessageException; import org.briarproject.bramble.api.sync.InvalidMessageException;
@@ -25,8 +24,6 @@ import java.util.Collection;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.util.ValidationUtils.checkLength; import static org.briarproject.bramble.util.ValidationUtils.checkLength;
import static org.briarproject.bramble.util.ValidationUtils.checkSize; import static org.briarproject.bramble.util.ValidationUtils.checkSize;
@@ -37,9 +34,7 @@ import static org.briarproject.briar.api.privategroup.MessageType.POST;
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH; import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE; import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG; import static org.briarproject.briar.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_ID; import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_NAME;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_PARENT_MSG_ID; import static org.briarproject.briar.privategroup.GroupConstants.KEY_PARENT_MSG_ID;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_PREVIOUS_MSG_ID; import static org.briarproject.briar.privategroup.GroupConstants.KEY_PREVIOUS_MSG_ID;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_READ; import static org.briarproject.briar.privategroup.GroupConstants.KEY_READ;
@@ -51,16 +46,13 @@ import static org.briarproject.briar.privategroup.GroupConstants.KEY_TYPE;
class GroupMessageValidator extends BdfMessageValidator { class GroupMessageValidator extends BdfMessageValidator {
private final PrivateGroupFactory privateGroupFactory; private final PrivateGroupFactory privateGroupFactory;
private final AuthorFactory authorFactory;
private final GroupInvitationFactory groupInvitationFactory; private final GroupInvitationFactory groupInvitationFactory;
GroupMessageValidator(PrivateGroupFactory privateGroupFactory, GroupMessageValidator(PrivateGroupFactory privateGroupFactory,
ClientHelper clientHelper, MetadataEncoder metadataEncoder, ClientHelper clientHelper, MetadataEncoder metadataEncoder,
Clock clock, AuthorFactory authorFactory, Clock clock, GroupInvitationFactory groupInvitationFactory) {
GroupInvitationFactory groupInvitationFactory) {
super(clientHelper, metadataEncoder, clock); super(clientHelper, metadataEncoder, clock);
this.privateGroupFactory = privateGroupFactory; this.privateGroupFactory = privateGroupFactory;
this.authorFactory = authorFactory;
this.groupInvitationFactory = groupInvitationFactory; this.groupInvitationFactory = groupInvitationFactory;
} }
@@ -68,27 +60,22 @@ class GroupMessageValidator extends BdfMessageValidator {
protected BdfMessageContext validateMessage(Message m, Group g, protected BdfMessageContext validateMessage(Message m, Group g,
BdfList body) throws InvalidMessageException, FormatException { BdfList body) throws InvalidMessageException, FormatException {
checkSize(body, 5, 7); checkSize(body, 4, 6);
// message type (int) // Message type (int)
int type = body.getLong(0).intValue(); int type = body.getLong(0).intValue();
// member_name (string) // Member (list of int, string, raw)
String memberName = body.getString(1); BdfList memberList = body.getList(1);
checkLength(memberName, 1, MAX_AUTHOR_NAME_LENGTH); Author member = clientHelper.parseAndValidateAuthor(memberList);
// member_public_key (raw)
byte[] memberPublicKey = body.getRaw(2);
checkLength(memberPublicKey, 1, MAX_PUBLIC_KEY_LENGTH);
Author member = authorFactory.createAuthor(memberName, memberPublicKey);
BdfMessageContext c; BdfMessageContext c;
if (type == JOIN.getInt()) { if (type == JOIN.getInt()) {
c = validateJoin(m, g, body, member); c = validateJoin(m, g, body, member);
addMessageMetadata(c, member, m.getTimestamp()); addMessageMetadata(c, memberList, m.getTimestamp());
} else if (type == POST.getInt()) { } else if (type == POST.getInt()) {
c = validatePost(m, g, body, member); c = validatePost(m, g, body, member);
addMessageMetadata(c, member, m.getTimestamp()); addMessageMetadata(c, memberList, m.getTimestamp());
} else { } else {
throw new InvalidMessageException("Unknown Message Type"); throw new InvalidMessageException("Unknown Message Type");
} }
@@ -97,64 +84,54 @@ class GroupMessageValidator extends BdfMessageValidator {
} }
private BdfMessageContext validateJoin(Message m, Group g, BdfList body, private BdfMessageContext validateJoin(Message m, Group g, BdfList body,
Author member) Author member) throws FormatException {
throws InvalidMessageException, FormatException { // Message type, member, optional invite, member's signature
checkSize(body, 4);
BdfList inviteList = body.getOptionalList(2);
byte[] memberSignature = body.getRaw(3);
checkLength(memberSignature, 1, MAX_SIGNATURE_LENGTH);
// The content is a BDF list with five elements // Invite is null if the member is the creator of the private group
checkSize(body, 5);
PrivateGroup pg = privateGroupFactory.parsePrivateGroup(g); PrivateGroup pg = privateGroupFactory.parsePrivateGroup(g);
// invite is null if the member is the creator of the private group
Author creator = pg.getCreator(); Author creator = pg.getCreator();
boolean isCreator = false; boolean isCreator = member.equals(creator);
BdfList invite = body.getOptionalList(3); if (isCreator) {
if (invite == null) { if (inviteList != null) throw new FormatException();
if (!member.equals(creator))
throw new InvalidMessageException();
isCreator = true;
} else { } else {
if (member.equals(creator)) if (inviteList == null) throw new FormatException();
throw new InvalidMessageException(); // Timestamp, creator's signature
checkSize(inviteList, 2);
// Otherwise invite is a list with two elements // Join timestamp must be greater than invite timestamp
checkSize(invite, 2); long inviteTimestamp = inviteList.getLong(0);
// invite_timestamp (int)
// join_timestamp must be greater than invite_timestamp
long inviteTimestamp = invite.getLong(0);
if (m.getTimestamp() <= inviteTimestamp) if (m.getTimestamp() <= inviteTimestamp)
throw new InvalidMessageException(); throw new FormatException();
byte[] creatorSignature = inviteList.getRaw(1);
// creator_signature (raw)
byte[] creatorSignature = invite.getRaw(1);
checkLength(creatorSignature, 1, MAX_SIGNATURE_LENGTH); checkLength(creatorSignature, 1, MAX_SIGNATURE_LENGTH);
// The invite token is signed by the creator of the private group
// the invite token is signed by the creator of the private group BdfList token = groupInvitationFactory.createInviteToken(
BdfList token = groupInvitationFactory creator.getId(), member.getId(), g.getId(),
.createInviteToken(creator.getId(), member.getId(), inviteTimestamp);
pg.getId(), inviteTimestamp);
try { try {
clientHelper clientHelper.verifySignature(SIGNING_LABEL_INVITE,
.verifySignature(SIGNING_LABEL_INVITE, creatorSignature, creatorSignature, creator.getPublicKey(), token);
creator.getPublicKey(), token);
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new InvalidMessageException(e); throw new FormatException();
} }
} }
// member_signature (raw) // Verify the member's signature
// a signature with the member's private key over a list with 6 elements BdfList memberList = body.getList(1); // Already validated
byte[] memberSignature = body.getRaw(4); BdfList signed = BdfList.of(
checkLength(memberSignature, 1, MAX_SIGNATURE_LENGTH); g.getId(),
m.getTimestamp(),
// Verify Signature memberList,
BdfList signed = BdfList.of(g.getId(), m.getTimestamp(), JOIN.getInt(), inviteList
member.getName(), member.getPublicKey(), invite); );
try { try {
clientHelper.verifySignature(SIGNING_LABEL_JOIN, memberSignature, clientHelper.verifySignature(SIGNING_LABEL_JOIN, memberSignature,
member.getPublicKey(), signed); member.getPublicKey(), signed);
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new InvalidMessageException(e); throw new FormatException();
} }
// Return the metadata and no dependencies // Return the metadata and no dependencies
@@ -164,44 +141,38 @@ class GroupMessageValidator extends BdfMessageValidator {
} }
private BdfMessageContext validatePost(Message m, Group g, BdfList body, private BdfMessageContext validatePost(Message m, Group g, BdfList body,
Author member) Author member) throws FormatException {
throws InvalidMessageException, FormatException { // Message type, member, optional parent ID, previous message ID,
// content, signature
// The content is a BDF list with seven elements checkSize(body, 6);
checkSize(body, 7); byte[] parentId = body.getOptionalRaw(2);
// parent_id (raw or null)
// the identifier of the post to which this is a reply, if any
byte[] parentId = body.getOptionalRaw(3);
checkLength(parentId, MessageId.LENGTH); checkLength(parentId, MessageId.LENGTH);
byte[] previousMessageId = body.getRaw(3);
// previous_message_id (raw)
// the identifier of the member's previous post or join message
byte[] previousMessageId = body.getRaw(4);
checkLength(previousMessageId, MessageId.LENGTH); checkLength(previousMessageId, MessageId.LENGTH);
String content = body.getString(4);
// content (string)
String content = body.getString(5);
checkLength(content, 1, MAX_GROUP_POST_BODY_LENGTH); checkLength(content, 1, MAX_GROUP_POST_BODY_LENGTH);
byte[] signature = body.getRaw(5);
// signature (raw)
// a signature with the member's private key over a list with 7 elements
byte[] signature = body.getRaw(6);
checkLength(signature, 1, MAX_SIGNATURE_LENGTH); checkLength(signature, 1, MAX_SIGNATURE_LENGTH);
// Verify Signature // Verify the member's signature
BdfList signed = BdfList.of(g.getId(), m.getTimestamp(), POST.getInt(), BdfList memberList = body.getList(1); // Already validated
member.getName(), member.getPublicKey(), parentId, BdfList signed = BdfList.of(
previousMessageId, content); g.getId(),
m.getTimestamp(),
memberList,
parentId,
previousMessageId,
content
);
try { try {
clientHelper.verifySignature(SIGNING_LABEL_POST, signature, clientHelper.verifySignature(SIGNING_LABEL_POST, signature,
member.getPublicKey(), signed); member.getPublicKey(), signed);
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new InvalidMessageException(e); throw new FormatException();
} }
// The parent post, if any, // The parent post, if any, and the member's previous message are
// and the member's previous message are dependencies // dependencies
Collection<MessageId> dependencies = new ArrayList<>(); Collection<MessageId> dependencies = new ArrayList<>();
if (parentId != null) dependencies.add(new MessageId(parentId)); if (parentId != null) dependencies.add(new MessageId(parentId));
dependencies.add(new MessageId(previousMessageId)); dependencies.add(new MessageId(previousMessageId));
@@ -213,13 +184,11 @@ class GroupMessageValidator extends BdfMessageValidator {
return new BdfMessageContext(meta, dependencies); return new BdfMessageContext(meta, dependencies);
} }
private void addMessageMetadata(BdfMessageContext c, Author member, private void addMessageMetadata(BdfMessageContext c, BdfList member,
long time) { long timestamp) {
c.getDictionary().put(KEY_TIMESTAMP, time); c.getDictionary().put(KEY_MEMBER, member);
c.getDictionary().put(KEY_TIMESTAMP, timestamp);
c.getDictionary().put(KEY_READ, false); c.getDictionary().put(KEY_READ, false);
c.getDictionary().put(KEY_MEMBER_ID, member.getId());
c.getDictionary().put(KEY_MEMBER_NAME, member.getName());
c.getDictionary().put(KEY_MEMBER_PUBLIC_KEY, member.getPublicKey());
} }
} }

View File

@@ -4,7 +4,6 @@ import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupFactory; import org.briarproject.bramble.api.sync.GroupFactory;
@@ -17,6 +16,8 @@ import java.security.SecureRandom;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH; import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH; import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID; import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID;
@@ -28,58 +29,55 @@ class PrivateGroupFactoryImpl implements PrivateGroupFactory {
private final GroupFactory groupFactory; private final GroupFactory groupFactory;
private final ClientHelper clientHelper; private final ClientHelper clientHelper;
private final AuthorFactory authorFactory;
private final SecureRandom random; private final SecureRandom random;
@Inject @Inject
PrivateGroupFactoryImpl(GroupFactory groupFactory, PrivateGroupFactoryImpl(GroupFactory groupFactory,
ClientHelper clientHelper, AuthorFactory authorFactory, ClientHelper clientHelper, SecureRandom random) {
SecureRandom random) {
this.groupFactory = groupFactory; this.groupFactory = groupFactory;
this.clientHelper = clientHelper; this.clientHelper = clientHelper;
this.authorFactory = authorFactory;
this.random = random; this.random = random;
} }
@Override @Override
public PrivateGroup createPrivateGroup(String name, Author author) { public PrivateGroup createPrivateGroup(String name, Author creator) {
int length = StringUtils.toUtf8(name).length; int length = StringUtils.toUtf8(name).length;
if (length == 0) throw new IllegalArgumentException("Group name empty"); if (length == 0 || length > MAX_GROUP_NAME_LENGTH)
if (length > MAX_GROUP_NAME_LENGTH) throw new IllegalArgumentException();
throw new IllegalArgumentException(
"Group name exceeds maximum length");
byte[] salt = new byte[GROUP_SALT_LENGTH]; byte[] salt = new byte[GROUP_SALT_LENGTH];
random.nextBytes(salt); random.nextBytes(salt);
return createPrivateGroup(name, author, salt); return createPrivateGroup(name, creator, salt);
} }
@Override @Override
public PrivateGroup createPrivateGroup(String name, Author author, public PrivateGroup createPrivateGroup(String name, Author creator,
byte[] salt) { byte[] salt) {
try { try {
BdfList group = BdfList.of( BdfList creatorList = clientHelper.toList(creator);
name, BdfList group = BdfList.of(creatorList, name, salt);
author.getName(),
author.getPublicKey(),
salt
);
byte[] descriptor = clientHelper.toByteArray(group); byte[] descriptor = clientHelper.toByteArray(group);
Group g = groupFactory.createGroup(CLIENT_ID, CLIENT_VERSION, Group g = groupFactory.createGroup(CLIENT_ID, CLIENT_VERSION,
descriptor); descriptor);
return new PrivateGroup(g, name, author, salt); return new PrivateGroup(g, name, creator, salt);
} catch (FormatException e) { } catch (FormatException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
@Override @Override
public PrivateGroup parsePrivateGroup(Group group) throws FormatException { public PrivateGroup parsePrivateGroup(Group g) throws FormatException {
byte[] descriptor = group.getDescriptor(); // Creator, group name, salt
BdfList list = clientHelper.toList(descriptor); BdfList descriptor = clientHelper.toList(g.getDescriptor());
Author a = checkSize(descriptor, 3);
authorFactory.createAuthor(list.getString(1), list.getRaw(2)); BdfList creatorList = descriptor.getList(0);
return new PrivateGroup(group, list.getString(0), a, list.getRaw(3)); String groupName = descriptor.getString(1);
checkLength(groupName, 1, MAX_GROUP_NAME_LENGTH);
byte[] salt = descriptor.getRaw(2);
checkLength(salt, GROUP_SALT_LENGTH);
Author creator = clientHelper.parseAndValidateAuthor(creatorList);
return new PrivateGroup(g, groupName, creator, salt);
} }
} }

View File

@@ -40,7 +40,6 @@ import org.briarproject.briar.api.privategroup.event.GroupMessageAddedEvent;
import org.briarproject.briar.client.BdfIncomingMessageHook; import org.briarproject.briar.client.BdfIncomingMessageHook;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@@ -69,9 +68,7 @@ import static org.briarproject.briar.privategroup.GroupConstants.GROUP_KEY_MEMBE
import static org.briarproject.briar.privategroup.GroupConstants.GROUP_KEY_OUR_GROUP; import static org.briarproject.briar.privategroup.GroupConstants.GROUP_KEY_OUR_GROUP;
import static org.briarproject.briar.privategroup.GroupConstants.GROUP_KEY_VISIBILITY; import static org.briarproject.briar.privategroup.GroupConstants.GROUP_KEY_VISIBILITY;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG; import static org.briarproject.briar.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_ID; import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_NAME;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_PARENT_MSG_ID; import static org.briarproject.briar.privategroup.GroupConstants.KEY_PARENT_MSG_ID;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_PREVIOUS_MSG_ID; import static org.briarproject.briar.privategroup.GroupConstants.KEY_PREVIOUS_MSG_ID;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_READ; import static org.briarproject.briar.privategroup.GroupConstants.KEY_READ;
@@ -139,7 +136,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
meta.put(KEY_TYPE, JOIN.getInt()); meta.put(KEY_TYPE, JOIN.getInt());
meta.put(KEY_INITIAL_JOIN_MSG, creator); meta.put(KEY_INITIAL_JOIN_MSG, creator);
addMessageMetadata(meta, m, true); addMessageMetadata(meta, m);
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true); clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
messageTracker.trackOutgoingMessage(txn, m.getMessage()); messageTracker.trackOutgoingMessage(txn, m.getMessage());
addMember(txn, m.getMessage().getGroupId(), m.getMember(), VISIBLE); addMember(txn, m.getMessage().getGroupId(), m.getMember(), VISIBLE);
@@ -217,7 +214,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
meta.put(KEY_TYPE, POST.getInt()); meta.put(KEY_TYPE, POST.getInt());
if (m.getParent() != null) if (m.getParent() != null)
meta.put(KEY_PARENT_MSG_ID, m.getParent()); meta.put(KEY_PARENT_MSG_ID, m.getParent());
addMessageMetadata(meta, m, true); addMessageMetadata(meta, m);
GroupId g = m.getMessage().getGroupId(); GroupId g = m.getMessage().getGroupId();
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true); clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
@@ -239,13 +236,10 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
m.getMessage().getTimestamp(), m.getMember(), OURSELVES, true); m.getMessage().getTimestamp(), m.getMember(), OURSELVES, true);
} }
private void addMessageMetadata(BdfDictionary meta, GroupMessage m, private void addMessageMetadata(BdfDictionary meta, GroupMessage m) {
boolean read) { meta.put(KEY_MEMBER, clientHelper.toList(m.getMember()));
meta.put(KEY_TIMESTAMP, m.getMessage().getTimestamp()); meta.put(KEY_TIMESTAMP, m.getMessage().getTimestamp());
meta.put(KEY_READ, read); meta.put(KEY_READ, true);
meta.put(KEY_MEMBER_ID, m.getMember().getId());
meta.put(KEY_MEMBER_NAME, m.getMember().getName());
meta.put(KEY_MEMBER_PUBLIC_KEY, m.getMember().getPublicKey());
} }
@Override @Override
@@ -316,9 +310,9 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
} }
private String getMessageBody(BdfList body) throws FormatException { private String getMessageBody(BdfList body) throws FormatException {
// type(0), member_name(1), member_public_key(2), parent_id(3), // Message type (0), member (1), parent ID (2), previous message ID (3),
// previous_message_id(4), content(5), signature(6) // content (4), signature (5)
return body.getString(5); return body.getString(4);
} }
@Override @Override
@@ -332,8 +326,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
// get all authors we need to get the status for // get all authors we need to get the status for
Set<AuthorId> authors = new HashSet<>(); Set<AuthorId> authors = new HashSet<>();
for (BdfDictionary meta : metadata.values()) { for (BdfDictionary meta : metadata.values()) {
byte[] idBytes = meta.getRaw(KEY_MEMBER_ID); authors.add(getAuthor(meta).getId());
authors.add(new AuthorId(idBytes));
} }
// get statuses for all authors // get statuses for all authors
Map<AuthorId, Status> statuses = new HashMap<>(); Map<AuthorId, Status> statuses = new HashMap<>();
@@ -348,13 +341,11 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
if (meta.getLong(KEY_TYPE) == JOIN.getInt()) { if (meta.getLong(KEY_TYPE) == JOIN.getInt()) {
Author member = getAuthor(meta); Author member = getAuthor(meta);
Visibility v = visibilities.get(member); Visibility v = visibilities.get(member);
headers.add( headers.add(getJoinMessageHeader(txn, g, entry.getKey(),
getJoinMessageHeader(txn, g, entry.getKey(), meta, meta, statuses, v));
statuses, v));
} else { } else {
headers.add( headers.add(getGroupMessageHeader(txn, g, entry.getKey(),
getGroupMessageHeader(txn, g, entry.getKey(), meta, meta, statuses));
statuses));
} }
} }
db.commitTransaction(txn); db.commitTransaction(txn);
@@ -376,16 +367,16 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
} }
long timestamp = meta.getLong(KEY_TIMESTAMP); long timestamp = meta.getLong(KEY_TIMESTAMP);
Author author = getAuthor(meta); Author member = getAuthor(meta);
Status status; Status status;
if (statuses.containsKey(author.getId())) { if (statuses.containsKey(member.getId())) {
status = statuses.get(author.getId()); status = statuses.get(member.getId());
} else { } else {
status = identityManager.getAuthorStatus(txn, author.getId()); status = identityManager.getAuthorStatus(txn, member.getId());
} }
boolean read = meta.getBoolean(KEY_READ); boolean read = meta.getBoolean(KEY_READ);
return new GroupMessageHeader(g, id, parentId, timestamp, author, return new GroupMessageHeader(g, id, parentId, timestamp, member,
status, read); status, read);
} }
@@ -475,8 +466,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
boolean foundMember = false, changed = false; boolean foundMember = false, changed = false;
for (int i = 0; i < members.size(); i++) { for (int i = 0; i < members.size(); i++) {
BdfDictionary d = members.getDictionary(i); BdfDictionary d = members.getDictionary(i);
AuthorId memberId = new AuthorId(d.getRaw(KEY_MEMBER_ID)); if (a.equals(getAuthor(d).getId())) {
if (a.equals(memberId)) {
foundMember = true; foundMember = true;
// Don't update the visibility if the contact is already visible // Don't update the visibility if the contact is already visible
if (getVisibility(d) == INVISIBLE) { if (getVisibility(d) == INVISIBLE) {
@@ -565,8 +555,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
if (timestamp <= previousMeta.getLong(KEY_TIMESTAMP)) if (timestamp <= previousMeta.getLong(KEY_TIMESTAMP))
throw new FormatException(); throw new FormatException();
// previous message must be from same member // previous message must be from same member
if (!Arrays.equals(meta.getRaw(KEY_MEMBER_ID), if (!getAuthor(meta).equals(getAuthor(previousMeta)))
previousMeta.getRaw(KEY_MEMBER_ID)))
throw new FormatException(); throw new FormatException();
// previous message must be a POST or JOIN // previous message must be a POST or JOIN
MessageType previousType = MessageType MessageType previousType = MessageType
@@ -603,9 +592,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(txn, g); BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(txn, g);
BdfList members = meta.getList(GROUP_KEY_MEMBERS); BdfList members = meta.getList(GROUP_KEY_MEMBERS);
members.add(BdfDictionary.of( members.add(BdfDictionary.of(
new BdfEntry(KEY_MEMBER_ID, a.getId()), new BdfEntry(KEY_MEMBER, clientHelper.toList(a)),
new BdfEntry(KEY_MEMBER_NAME, a.getName()),
new BdfEntry(KEY_MEMBER_PUBLIC_KEY, a.getPublicKey()),
new BdfEntry(GROUP_KEY_VISIBILITY, v.getInt()) new BdfEntry(GROUP_KEY_VISIBILITY, v.getInt())
)); ));
clientHelper.mergeGroupMetadata(txn, g, meta); clientHelper.mergeGroupMetadata(txn, g, meta);
@@ -615,10 +602,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
} }
private Author getAuthor(BdfDictionary meta) throws FormatException { private Author getAuthor(BdfDictionary meta) throws FormatException {
AuthorId authorId = new AuthorId(meta.getRaw(KEY_MEMBER_ID)); return clientHelper.parseAndValidateAuthor(meta.getList(KEY_MEMBER));
String name = meta.getString(KEY_MEMBER_NAME);
byte[] publicKey = meta.getRaw(KEY_MEMBER_PUBLIC_KEY);
return new Author(authorId, name, publicKey);
} }
private Visibility getVisibility(BdfDictionary meta) private Visibility getVisibility(BdfDictionary meta)

View File

@@ -2,7 +2,6 @@ package org.briarproject.briar.privategroup;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.sync.ValidationManager; import org.briarproject.bramble.api.sync.ValidationManager;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.briar.api.privategroup.GroupMessageFactory; import org.briarproject.briar.api.privategroup.GroupMessageFactory;
@@ -54,12 +53,11 @@ public class PrivateGroupModule {
GroupMessageValidator provideGroupMessageValidator( GroupMessageValidator provideGroupMessageValidator(
PrivateGroupFactory privateGroupFactory, PrivateGroupFactory privateGroupFactory,
ClientHelper clientHelper, MetadataEncoder metadataEncoder, ClientHelper clientHelper, MetadataEncoder metadataEncoder,
Clock clock, AuthorFactory authorFactory, Clock clock, GroupInvitationFactory groupInvitationFactory,
GroupInvitationFactory groupInvitationFactory,
ValidationManager validationManager) { ValidationManager validationManager) {
GroupMessageValidator validator = new GroupMessageValidator( GroupMessageValidator validator = new GroupMessageValidator(
privateGroupFactory, clientHelper, metadataEncoder, clock, privateGroupFactory, clientHelper, metadataEncoder, clock,
authorFactory, groupInvitationFactory); groupInvitationFactory);
validationManager.registerMessageValidator(CLIENT_ID, validator); validationManager.registerMessageValidator(CLIENT_ID, validator);
return validator; return validator;
} }

View File

@@ -140,10 +140,10 @@ abstract class AbstractProtocolEngine<S extends Session>
return m; return m;
} }
void markMessageVisibleInUi(Transaction txn, MessageId m, boolean visible) void markMessageVisibleInUi(Transaction txn, MessageId m)
throws DbException { throws DbException {
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
messageEncoder.setVisibleInUi(meta, visible); messageEncoder.setVisibleInUi(meta, true);
try { try {
clientHelper.mergeMessageMetadata(txn, m, meta); clientHelper.mergeMessageMetadata(txn, m, meta);
} catch (FormatException e) { } catch (FormatException e) {
@@ -174,10 +174,9 @@ abstract class AbstractProtocolEngine<S extends Session>
markMessageAvailableToAnswer(txn, m, false); markMessageAvailableToAnswer(txn, m, false);
} }
void markInviteAccepted(Transaction txn, MessageId m, boolean accepted) void markInviteAccepted(Transaction txn, MessageId m) throws DbException {
throws DbException {
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
messageEncoder.setInvitationAccepted(meta, accepted); messageEncoder.setInvitationAccepted(meta, true);
try { try {
clientHelper.mergeMessageMetadata(txn, m, meta); clientHelper.mergeMessageMetadata(txn, m, meta);
} catch (FormatException e) { } catch (FormatException e) {

View File

@@ -183,7 +183,7 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
// Send a JOIN message // Send a JOIN message
Message sent = sendJoinMessage(txn, s, false); Message sent = sendJoinMessage(txn, s, false);
// Mark the response visible in the UI // Mark the response visible in the UI
markMessageVisibleInUi(txn, m.getId(), true); markMessageVisibleInUi(txn, m.getId());
// Track the message // Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(), messageTracker.trackMessage(txn, m.getContactGroupId(),
m.getTimestamp(), false); m.getTimestamp(), false);
@@ -207,7 +207,7 @@ class CreatorProtocolEngine extends AbstractProtocolEngine<CreatorSession> {
if (!isValidDependency(s, m.getPreviousMessageId())) if (!isValidDependency(s, m.getPreviousMessageId()))
return abort(txn, s); return abort(txn, s);
// Mark the response visible in the UI // Mark the response visible in the UI
markMessageVisibleInUi(txn, m.getId(), true); markMessageVisibleInUi(txn, m.getId());
// Track the message // Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(), messageTracker.trackMessage(txn, m.getContactGroupId(),
m.getTimestamp(), false); m.getTimestamp(), false);

View File

@@ -3,7 +3,6 @@ package org.briarproject.briar.privategroup.invitation;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.sync.ValidationManager; import org.briarproject.bramble.api.sync.ValidationManager;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
@@ -53,13 +52,12 @@ public class GroupInvitationModule {
@Singleton @Singleton
GroupInvitationValidator provideGroupInvitationValidator( GroupInvitationValidator provideGroupInvitationValidator(
ClientHelper clientHelper, MetadataEncoder metadataEncoder, ClientHelper clientHelper, MetadataEncoder metadataEncoder,
Clock clock, AuthorFactory authorFactory, Clock clock, PrivateGroupFactory privateGroupFactory,
PrivateGroupFactory privateGroupFactory,
MessageEncoder messageEncoder, MessageEncoder messageEncoder,
ValidationManager validationManager) { ValidationManager validationManager) {
GroupInvitationValidator validator = new GroupInvitationValidator( GroupInvitationValidator validator = new GroupInvitationValidator(
clientHelper, metadataEncoder, clock, authorFactory, clientHelper, metadataEncoder, clock, privateGroupFactory,
privateGroupFactory, messageEncoder); messageEncoder);
validationManager.registerMessageValidator(CLIENT_ID, validator); validationManager.registerMessageValidator(CLIENT_ID, validator);
return validator; return validator;
} }

View File

@@ -9,7 +9,6 @@ import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
@@ -23,10 +22,7 @@ import java.security.GeneralSecurityException;
import java.util.Collections; import java.util.Collections;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.util.ValidationUtils.checkLength; import static org.briarproject.bramble.util.ValidationUtils.checkLength;
import static org.briarproject.bramble.util.ValidationUtils.checkSize; import static org.briarproject.bramble.util.ValidationUtils.checkSize;
@@ -43,18 +39,14 @@ import static org.briarproject.briar.privategroup.invitation.MessageType.LEAVE;
@NotNullByDefault @NotNullByDefault
class GroupInvitationValidator extends BdfMessageValidator { class GroupInvitationValidator extends BdfMessageValidator {
private final AuthorFactory authorFactory;
private final PrivateGroupFactory privateGroupFactory; private final PrivateGroupFactory privateGroupFactory;
private final MessageEncoder messageEncoder; private final MessageEncoder messageEncoder;
@Inject
GroupInvitationValidator(ClientHelper clientHelper, GroupInvitationValidator(ClientHelper clientHelper,
MetadataEncoder metadataEncoder, Clock clock, MetadataEncoder metadataEncoder, Clock clock,
AuthorFactory authorFactory,
PrivateGroupFactory privateGroupFactory, PrivateGroupFactory privateGroupFactory,
MessageEncoder messageEncoder) { MessageEncoder messageEncoder) {
super(clientHelper, metadataEncoder, clock); super(clientHelper, metadataEncoder, clock);
this.authorFactory = authorFactory;
this.privateGroupFactory = privateGroupFactory; this.privateGroupFactory = privateGroupFactory;
this.messageEncoder = messageEncoder; this.messageEncoder = messageEncoder;
} }
@@ -79,22 +71,20 @@ class GroupInvitationValidator extends BdfMessageValidator {
private BdfMessageContext validateInviteMessage(Message m, BdfList body) private BdfMessageContext validateInviteMessage(Message m, BdfList body)
throws FormatException { throws FormatException {
checkSize(body, 7); // Message type, creator, group name, salt, optional message, signature
String groupName = body.getString(1); checkSize(body, 6);
BdfList creatorList = body.getList(1);
String groupName = body.getString(2);
checkLength(groupName, 1, MAX_GROUP_NAME_LENGTH); checkLength(groupName, 1, MAX_GROUP_NAME_LENGTH);
String creatorName = body.getString(2); byte[] salt = body.getRaw(3);
checkLength(creatorName, 1, MAX_AUTHOR_NAME_LENGTH);
byte[] creatorPublicKey = body.getRaw(3);
checkLength(creatorPublicKey, 1, MAX_PUBLIC_KEY_LENGTH);
byte[] salt = body.getRaw(4);
checkLength(salt, GROUP_SALT_LENGTH); checkLength(salt, GROUP_SALT_LENGTH);
String message = body.getOptionalString(5); String message = body.getOptionalString(4);
checkLength(message, 1, MAX_GROUP_INVITATION_MSG_LENGTH); checkLength(message, 1, MAX_GROUP_INVITATION_MSG_LENGTH);
byte[] signature = body.getRaw(6); byte[] signature = body.getRaw(5);
checkLength(signature, 1, MAX_SIGNATURE_LENGTH); checkLength(signature, 1, MAX_SIGNATURE_LENGTH);
// Create the private group
Author creator = authorFactory.createAuthor(creatorName, // Validate the creator and create the private group
creatorPublicKey); Author creator = clientHelper.parseAndValidateAuthor(creatorList);
PrivateGroup privateGroup = privateGroupFactory.createPrivateGroup( PrivateGroup privateGroup = privateGroupFactory.createPrivateGroup(
groupName, creator, salt); groupName, creator, salt);
// Verify the signature // Verify the signature
@@ -105,7 +95,7 @@ class GroupInvitationValidator extends BdfMessageValidator {
); );
try { try {
clientHelper.verifySignature(SIGNING_LABEL_INVITE, signature, clientHelper.verifySignature(SIGNING_LABEL_INVITE, signature,
creatorPublicKey, signed); creator.getPublicKey(), signed);
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new FormatException(); throw new FormatException();
} }

View File

@@ -173,7 +173,7 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
if (inviteId == null) throw new IllegalStateException(); if (inviteId == null) throw new IllegalStateException();
markMessageAvailableToAnswer(txn, inviteId, false); markMessageAvailableToAnswer(txn, inviteId, false);
// Record the response // Record the response
markInviteAccepted(txn, inviteId, true); markInviteAccepted(txn, inviteId);
// Send a JOIN message // Send a JOIN message
Message sent = sendJoinMessage(txn, s, true); Message sent = sendJoinMessage(txn, s, true);
// Track the message // Track the message
@@ -228,7 +228,7 @@ class InviteeProtocolEngine extends AbstractProtocolEngine<InviteeSession> {
if (!contact.getId().equals(m.getCreator().getId())) if (!contact.getId().equals(m.getCreator().getId()))
return abort(txn, s); return abort(txn, s);
// Mark the invite message visible in the UI and available to answer // Mark the invite message visible in the UI and available to answer
markMessageVisibleInUi(txn, m.getId(), true); markMessageVisibleInUi(txn, m.getId());
markMessageAvailableToAnswer(txn, m.getId(), true); markMessageAvailableToAnswer(txn, m.getId(), true);
// Track the message // Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(), messageTracker.trackMessage(txn, m.getContactGroupId(),

View File

@@ -78,11 +78,11 @@ class MessageEncoderImpl implements MessageEncoder {
GroupId privateGroupId, long timestamp, String groupName, GroupId privateGroupId, long timestamp, String groupName,
Author creator, byte[] salt, @Nullable String message, Author creator, byte[] salt, @Nullable String message,
byte[] signature) { byte[] signature) {
BdfList creatorList = clientHelper.toList(creator);
BdfList body = BdfList.of( BdfList body = BdfList.of(
INVITE.getValue(), INVITE.getValue(),
creatorList,
groupName, groupName,
creator.getName(),
creator.getPublicKey(),
salt, salt,
message, message,
signature signature

View File

@@ -19,6 +19,7 @@ import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ; import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AVAILABLE_TO_ANSWER; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_AVAILABLE_TO_ANSWER;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_INVITATION_ACCEPTED; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.MSG_KEY_INVITATION_ACCEPTED;
@@ -39,7 +40,8 @@ class MessageParserImpl implements MessageParser {
@Inject @Inject
MessageParserImpl(AuthorFactory authorFactory, MessageParserImpl(AuthorFactory authorFactory,
PrivateGroupFactory privateGroupFactory, ClientHelper clientHelper) { PrivateGroupFactory privateGroupFactory,
ClientHelper clientHelper) {
this.authorFactory = authorFactory; this.authorFactory = authorFactory;
this.privateGroupFactory = privateGroupFactory; this.privateGroupFactory = privateGroupFactory;
this.clientHelper = clientHelper; this.clientHelper = clientHelper;
@@ -97,13 +99,20 @@ class MessageParserImpl implements MessageParser {
@Override @Override
public InviteMessage parseInviteMessage(Message m, BdfList body) public InviteMessage parseInviteMessage(Message m, BdfList body)
throws FormatException { throws FormatException {
String groupName = body.getString(1); // Message type, creator, group name, salt, optional message, signature
String creatorName = body.getString(2); BdfList creatorList = body.getList(1);
byte[] creatorPublicKey = body.getRaw(3); String groupName = body.getString(2);
byte[] salt = body.getRaw(4); byte[] salt = body.getRaw(3);
String message = body.getOptionalString(5); String message = body.getOptionalString(4);
byte[] signature = body.getRaw(6); byte[] signature = body.getRaw(5);
Author creator = authorFactory.createAuthor(creatorName,
// Format version, name, public key
int formatVersion = creatorList.getLong(0).intValue();
if (formatVersion != FORMAT_VERSION) throw new FormatException();
String creatorName = creatorList.getString(1);
byte[] creatorPublicKey = creatorList.getRaw(2);
Author creator = authorFactory.createAuthor(formatVersion, creatorName,
creatorPublicKey); creatorPublicKey);
PrivateGroup privateGroup = privateGroupFactory.createPrivateGroup( PrivateGroup privateGroup = privateGroupFactory.createPrivateGroup(
groupName, creator, salt); groupName, creator, salt);

View File

@@ -12,6 +12,8 @@ import org.briarproject.briar.api.blog.BlogFactory;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
class BlogMessageParserImpl extends MessageParserImpl<Blog> { class BlogMessageParserImpl extends MessageParserImpl<Blog> {
@@ -28,12 +30,19 @@ class BlogMessageParserImpl extends MessageParserImpl<Blog> {
} }
@Override @Override
protected Blog createShareable(BdfList descriptor) protected Blog createShareable(BdfList descriptor) throws FormatException {
throws FormatException { // Author, RSS
String name = descriptor.getString(0); BdfList authorList = descriptor.getList(0);
byte[] publicKey = descriptor.getRaw(1); boolean rssFeed = descriptor.getBoolean(1);
boolean rssFeed = descriptor.getBoolean(2);
Author author = authorFactory.createAuthor(name, publicKey); // Format version, name, public key
int formatVersion = authorList.getLong(0).intValue();
if (formatVersion != FORMAT_VERSION) throw new FormatException();
String name = authorList.getString(1);
byte[] publicKey = authorList.getRaw(2);
Author author = authorFactory.createAuthor(formatVersion, name,
publicKey);
if (rssFeed) return blogFactory.createFeedBlog(author); if (rssFeed) return blogFactory.createFeedBlog(author);
else return blogFactory.createBlog(author); else return blogFactory.createBlog(author);
} }

View File

@@ -5,19 +5,13 @@ import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.briar.api.blog.Blog;
import org.briarproject.briar.api.blog.BlogFactory; import org.briarproject.briar.api.blog.BlogFactory;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
import static org.briarproject.bramble.util.ValidationUtils.checkSize; import static org.briarproject.bramble.util.ValidationUtils.checkSize;
@Immutable @Immutable
@@ -25,35 +19,24 @@ import static org.briarproject.bramble.util.ValidationUtils.checkSize;
class BlogSharingValidator extends SharingValidator { class BlogSharingValidator extends SharingValidator {
private final BlogFactory blogFactory; private final BlogFactory blogFactory;
private final AuthorFactory authorFactory;
@Inject
BlogSharingValidator(MessageEncoder messageEncoder, BlogSharingValidator(MessageEncoder messageEncoder,
ClientHelper clientHelper, MetadataEncoder metadataEncoder, ClientHelper clientHelper, MetadataEncoder metadataEncoder,
Clock clock, BlogFactory blogFactory, AuthorFactory authorFactory) { Clock clock, BlogFactory blogFactory) {
super(messageEncoder, clientHelper, metadataEncoder, clock); super(messageEncoder, clientHelper, metadataEncoder, clock);
this.blogFactory = blogFactory; this.blogFactory = blogFactory;
this.authorFactory = authorFactory;
} }
@Override @Override
protected GroupId validateDescriptor(BdfList descriptor) protected GroupId validateDescriptor(BdfList descriptor)
throws FormatException { throws FormatException {
checkSize(descriptor, 3); // Author, RSS
String name = descriptor.getString(0); checkSize(descriptor, 2);
checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH); BdfList authorList = descriptor.getList(0);
byte[] publicKey = descriptor.getRaw(1); boolean rssFeed = descriptor.getBoolean(1);
checkLength(publicKey, 1, MAX_PUBLIC_KEY_LENGTH); Author author = clientHelper.parseAndValidateAuthor(authorList);
boolean rssFeed = descriptor.getBoolean(2); if (rssFeed) return blogFactory.createFeedBlog(author).getId();
else return blogFactory.createBlog(author).getId();
Author author = authorFactory.createAuthor(name, publicKey);
Blog blog;
if (rssFeed) {
blog = blogFactory.createFeedBlog(author);
} else {
blog = blogFactory.createBlog(author);
}
return blog.getId();
} }
} }

View File

@@ -24,8 +24,8 @@ class ForumMessageParserImpl extends MessageParserImpl<Forum> {
} }
@Override @Override
protected Forum createShareable(BdfList descriptor) protected Forum createShareable(BdfList descriptor) throws FormatException {
throws FormatException { // Name, salt
String name = descriptor.getString(0); String name = descriptor.getString(0);
byte[] salt = descriptor.getRaw(1); byte[] salt = descriptor.getRaw(1);
return forumFactory.createForum(name, salt); return forumFactory.createForum(name, salt);

View File

@@ -35,6 +35,7 @@ class ForumSharingValidator extends SharingValidator {
@Override @Override
protected GroupId validateDescriptor(BdfList descriptor) protected GroupId validateDescriptor(BdfList descriptor)
throws FormatException { throws FormatException {
// Name, salt
checkSize(descriptor, 2); checkSize(descriptor, 2);
String name = descriptor.getString(0); String name = descriptor.getString(0);
checkLength(name, 1, MAX_FORUM_NAME_LENGTH); checkLength(name, 1, MAX_FORUM_NAME_LENGTH);

View File

@@ -112,9 +112,8 @@ abstract class ProtocolEngineImpl<S extends Shareable>
throw new DbException(e); // Invalid group descriptor throw new DbException(e); // Invalid group descriptor
} }
long localTimestamp = Math.max(timestamp, getLocalTimestamp(s)); long localTimestamp = Math.max(timestamp, getLocalTimestamp(s));
Message m = messageEncoder Message m = messageEncoder.encodeInviteMessage(s.getContactGroupId(),
.encodeInviteMessage(s.getContactGroupId(), localTimestamp, localTimestamp, s.getLastLocalMessageId(), descriptor, message);
s.getLastLocalMessageId(), descriptor, message);
sendMessage(txn, m, INVITE, s.getShareableId(), true); sendMessage(txn, m, INVITE, s.getShareableId(), true);
return m; return m;
} }
@@ -143,7 +142,7 @@ abstract class ProtocolEngineImpl<S extends Shareable>
if (inviteId == null) throw new IllegalStateException(); if (inviteId == null) throw new IllegalStateException();
markMessageAvailableToAnswer(txn, inviteId, false); markMessageAvailableToAnswer(txn, inviteId, false);
// Mark the invite message as accepted // Mark the invite message as accepted
markInvitationAccepted(txn, inviteId, true); markInvitationAccepted(txn, inviteId);
// Send a ACCEPT message // Send a ACCEPT message
Message sent = sendAcceptMessage(txn, s); Message sent = sendAcceptMessage(txn, s);
// Track the message // Track the message
@@ -288,7 +287,7 @@ abstract class ProtocolEngineImpl<S extends Shareable>
if (!isValidDependency(s, m.getPreviousMessageId())) if (!isValidDependency(s, m.getPreviousMessageId()))
return abortWithMessage(txn, s); return abortWithMessage(txn, s);
// Mark the invite message visible in the UI and (un)available to answer // Mark the invite message visible in the UI and (un)available to answer
markMessageVisibleInUi(txn, m.getId(), true); markMessageVisibleInUi(txn, m.getId());
markMessageAvailableToAnswer(txn, m.getId(), available); markMessageAvailableToAnswer(txn, m.getId(), available);
// Track the message // Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(), messageTracker.trackMessage(txn, m.getContactGroupId(),
@@ -312,7 +311,7 @@ abstract class ProtocolEngineImpl<S extends Shareable>
if (!isValidDependency(s, m.getPreviousMessageId())) if (!isValidDependency(s, m.getPreviousMessageId()))
return abortWithMessage(txn, s); return abortWithMessage(txn, s);
// Mark the invite message visible in the UI and unavailable to answer // Mark the invite message visible in the UI and unavailable to answer
markMessageVisibleInUi(txn, m.getId(), true); markMessageVisibleInUi(txn, m.getId());
markMessageAvailableToAnswer(txn, m.getId(), false); markMessageAvailableToAnswer(txn, m.getId(), false);
// Track the message // Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(), messageTracker.trackMessage(txn, m.getContactGroupId(),
@@ -359,7 +358,7 @@ abstract class ProtocolEngineImpl<S extends Shareable>
if (!isValidDependency(s, m.getPreviousMessageId())) if (!isValidDependency(s, m.getPreviousMessageId()))
return abortWithMessage(txn, s); return abortWithMessage(txn, s);
// Mark the response visible in the UI // Mark the response visible in the UI
markMessageVisibleInUi(txn, m.getId(), true); markMessageVisibleInUi(txn, m.getId());
// Track the message // Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(), messageTracker.trackMessage(txn, m.getContactGroupId(),
m.getTimestamp(), false); m.getTimestamp(), false);
@@ -411,7 +410,7 @@ abstract class ProtocolEngineImpl<S extends Shareable>
if (!isValidDependency(s, m.getPreviousMessageId())) if (!isValidDependency(s, m.getPreviousMessageId()))
return abortWithMessage(txn, s); return abortWithMessage(txn, s);
// Mark the response visible in the UI // Mark the response visible in the UI
markMessageVisibleInUi(txn, m.getId(), true); markMessageVisibleInUi(txn, m.getId());
// Track the message // Track the message
messageTracker.trackMessage(txn, m.getContactGroupId(), messageTracker.trackMessage(txn, m.getContactGroupId(),
m.getTimestamp(), false); m.getTimestamp(), false);
@@ -576,10 +575,10 @@ abstract class ProtocolEngineImpl<S extends Shareable>
} }
} }
private void markMessageVisibleInUi(Transaction txn, MessageId m, private void markMessageVisibleInUi(Transaction txn, MessageId m)
boolean visible) throws DbException { throws DbException {
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
messageEncoder.setVisibleInUi(meta, visible); messageEncoder.setVisibleInUi(meta, true);
try { try {
clientHelper.mergeMessageMetadata(txn, m, meta); clientHelper.mergeMessageMetadata(txn, m, meta);
} catch (FormatException e) { } catch (FormatException e) {
@@ -587,10 +586,10 @@ abstract class ProtocolEngineImpl<S extends Shareable>
} }
} }
private void markInvitationAccepted(Transaction txn, MessageId m, private void markInvitationAccepted(Transaction txn, MessageId m)
boolean accepted) throws DbException { throws DbException {
BdfDictionary meta = new BdfDictionary(); BdfDictionary meta = new BdfDictionary();
messageEncoder.setInvitationAccepted(meta, accepted); messageEncoder.setInvitationAccepted(meta, true);
try { try {
clientHelper.mergeMessageMetadata(txn, m, meta); clientHelper.mergeMessageMetadata(txn, m, meta);
} catch (FormatException e) { } catch (FormatException e) {

View File

@@ -3,7 +3,6 @@ package org.briarproject.briar.sharing;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.sync.ValidationManager; import org.briarproject.bramble.api.sync.ValidationManager;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
@@ -59,10 +58,10 @@ public class SharingModule {
BlogSharingValidator provideBlogSharingValidator( BlogSharingValidator provideBlogSharingValidator(
ValidationManager validationManager, MessageEncoder messageEncoder, ValidationManager validationManager, MessageEncoder messageEncoder,
ClientHelper clientHelper, MetadataEncoder metadataEncoder, ClientHelper clientHelper, MetadataEncoder metadataEncoder,
Clock clock, BlogFactory blogFactory, AuthorFactory authorFactory) { Clock clock, BlogFactory blogFactory) {
BlogSharingValidator validator = BlogSharingValidator validator =
new BlogSharingValidator(messageEncoder, clientHelper, new BlogSharingValidator(messageEncoder, clientHelper,
metadataEncoder, clock, blogFactory, authorFactory); metadataEncoder, clock, blogFactory);
validationManager.registerMessageValidator(BlogSharingManager.CLIENT_ID, validationManager.registerMessageValidator(BlogSharingManager.CLIENT_ID,
validator); validator);
return validator; return validator;

View File

@@ -190,8 +190,8 @@ public class TestDataCreatorImpl implements TestDataCreator {
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair(); KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
byte[] publicKey = keyPair.getPublic().getEncoded(); byte[] publicKey = keyPair.getPublic().getEncoded();
byte[] privateKey = keyPair.getPrivate().getEncoded(); byte[] privateKey = keyPair.getPrivate().getEncoded();
return authorFactory return authorFactory.createLocalAuthor(authorName, publicKey,
.createLocalAuthor(authorName, publicKey, privateKey); privateKey);
} }
private SecretKey getSecretKey() { private SecretKey getSecretKey() {

View File

@@ -12,7 +12,6 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
@@ -34,20 +33,16 @@ import org.junit.Test;
import static org.briarproject.bramble.api.identity.Author.Status.NONE; import static org.briarproject.bramble.api.identity.Author.Status.NONE;
import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES; import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED; import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_LENGTH; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR; import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_NAME;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_COMMENT; import static org.briarproject.briar.api.blog.BlogConstants.KEY_COMMENT;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_MSG_ID; import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_MSG_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_PARENT_MSG_ID; import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_PARENT_MSG_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID; import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PUBLIC_KEY;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ; import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_RSS_FEED; import static org.briarproject.briar.api.blog.BlogConstants.KEY_RSS_FEED;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIMESTAMP; import static org.briarproject.briar.api.blog.BlogConstants.KEY_TIMESTAMP;
@@ -77,7 +72,7 @@ public class BlogManagerImplTest extends BriarTestCase {
context.mock(BlogPostFactory.class); context.mock(BlogPostFactory.class);
private final LocalAuthor localAuthor1, localAuthor2, rssLocalAuthor; private final LocalAuthor localAuthor1, localAuthor2, rssLocalAuthor;
private final BdfDictionary authorDict1, authorDict2, rssAuthorDict; private final BdfList authorList1, authorList2, rssAuthorList;
private final Blog blog1, blog2, rssBlog; private final Blog blog1, blog2, rssBlog;
private final long timestamp, timeReceived; private final long timestamp, timeReceived;
private final MessageId messageId, rssMessageId; private final MessageId messageId, rssMessageId;
@@ -89,12 +84,12 @@ public class BlogManagerImplTest extends BriarTestCase {
blogManager = new BlogManagerImpl(db, identityManager, clientHelper, blogManager = new BlogManagerImpl(db, identityManager, clientHelper,
metadataParser, blogFactory, blogPostFactory); metadataParser, blogFactory, blogPostFactory);
localAuthor1 = createLocalAuthor(); localAuthor1 = getLocalAuthor();
localAuthor2 = createLocalAuthor(); localAuthor2 = getLocalAuthor();
rssLocalAuthor = createLocalAuthor(); rssLocalAuthor = getLocalAuthor();
authorDict1 = authorToBdfDictionary(localAuthor1); authorList1 = authorToBdfList(localAuthor1);
authorDict2 = authorToBdfDictionary(localAuthor2); authorList2 = authorToBdfList(localAuthor2);
rssAuthorDict = authorToBdfDictionary(rssLocalAuthor); rssAuthorList = authorToBdfList(rssLocalAuthor);
blog1 = createBlog(localAuthor1, false); blog1 = createBlog(localAuthor1, false);
blog2 = createBlog(localAuthor2, false); blog2 = createBlog(localAuthor2, false);
rssBlog = createBlog(rssLocalAuthor, true); rssBlog = createBlog(rssLocalAuthor, true);
@@ -174,12 +169,14 @@ public class BlogManagerImplTest extends BriarTestCase {
new BdfEntry(KEY_TYPE, POST.getInt()), new BdfEntry(KEY_TYPE, POST.getInt()),
new BdfEntry(KEY_TIMESTAMP, timestamp), new BdfEntry(KEY_TIMESTAMP, timestamp),
new BdfEntry(KEY_TIME_RECEIVED, timeReceived), new BdfEntry(KEY_TIME_RECEIVED, timeReceived),
new BdfEntry(KEY_AUTHOR, authorDict1), new BdfEntry(KEY_AUTHOR, authorList1),
new BdfEntry(KEY_READ, false), new BdfEntry(KEY_READ, false),
new BdfEntry(KEY_RSS_FEED, false) new BdfEntry(KEY_RSS_FEED, false)
); );
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(clientHelper).parseAndValidateAuthor(authorList1);
will(returnValue(localAuthor1));
oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId()); oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId());
will(returnValue(VERIFIED)); will(returnValue(VERIFIED));
}}); }});
@@ -213,11 +210,16 @@ public class BlogManagerImplTest extends BriarTestCase {
new BdfEntry(KEY_TYPE, POST.getInt()), new BdfEntry(KEY_TYPE, POST.getInt()),
new BdfEntry(KEY_TIMESTAMP, timestamp), new BdfEntry(KEY_TIMESTAMP, timestamp),
new BdfEntry(KEY_TIME_RECEIVED, timeReceived), new BdfEntry(KEY_TIME_RECEIVED, timeReceived),
new BdfEntry(KEY_AUTHOR, rssAuthorDict), new BdfEntry(KEY_AUTHOR, rssAuthorList),
new BdfEntry(KEY_READ, false), new BdfEntry(KEY_READ, false),
new BdfEntry(KEY_RSS_FEED, true) new BdfEntry(KEY_RSS_FEED, true)
); );
context.checking(new Expectations() {{
oneOf(clientHelper).parseAndValidateAuthor(rssAuthorList);
will(returnValue(rssLocalAuthor));
}});
blogManager.incomingMessage(txn, rssMessage, body, meta); blogManager.incomingMessage(txn, rssMessage, body, meta);
context.assertIsSatisfied(); context.assertIsSatisfied();
@@ -264,7 +266,7 @@ public class BlogManagerImplTest extends BriarTestCase {
BdfDictionary meta = BdfDictionary.of( BdfDictionary meta = BdfDictionary.of(
new BdfEntry(KEY_TYPE, POST.getInt()), new BdfEntry(KEY_TYPE, POST.getInt()),
new BdfEntry(KEY_TIMESTAMP, timestamp), new BdfEntry(KEY_TIMESTAMP, timestamp),
new BdfEntry(KEY_AUTHOR, authorDict1), new BdfEntry(KEY_AUTHOR, authorList1),
new BdfEntry(KEY_READ, true), new BdfEntry(KEY_READ, true),
new BdfEntry(KEY_RSS_FEED, false) new BdfEntry(KEY_RSS_FEED, false)
); );
@@ -276,7 +278,11 @@ public class BlogManagerImplTest extends BriarTestCase {
will(returnValue(blog1.getGroup())); will(returnValue(blog1.getGroup()));
oneOf(blogFactory).parseBlog(blog1.getGroup()); oneOf(blogFactory).parseBlog(blog1.getGroup());
will(returnValue(blog1)); will(returnValue(blog1));
oneOf(clientHelper).toList(localAuthor1);
will(returnValue(authorList1));
oneOf(clientHelper).addLocalMessage(txn, message, meta, true); oneOf(clientHelper).addLocalMessage(txn, message, meta, true);
oneOf(clientHelper).parseAndValidateAuthor(authorList1);
will(returnValue(localAuthor1));
oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId()); oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId());
will(returnValue(OURSELVES)); will(returnValue(OURSELVES));
oneOf(db).commitTransaction(txn); oneOf(db).commitTransaction(txn);
@@ -310,7 +316,7 @@ public class BlogManagerImplTest extends BriarTestCase {
BdfDictionary meta = BdfDictionary.of( BdfDictionary meta = BdfDictionary.of(
new BdfEntry(KEY_TYPE, POST.getInt()), new BdfEntry(KEY_TYPE, POST.getInt()),
new BdfEntry(KEY_TIMESTAMP, timestamp), new BdfEntry(KEY_TIMESTAMP, timestamp),
new BdfEntry(KEY_AUTHOR, rssAuthorDict), new BdfEntry(KEY_AUTHOR, rssAuthorList),
new BdfEntry(KEY_READ, true), new BdfEntry(KEY_READ, true),
new BdfEntry(KEY_RSS_FEED, true) new BdfEntry(KEY_RSS_FEED, true)
); );
@@ -322,7 +328,11 @@ public class BlogManagerImplTest extends BriarTestCase {
will(returnValue(rssBlog.getGroup())); will(returnValue(rssBlog.getGroup()));
oneOf(blogFactory).parseBlog(rssBlog.getGroup()); oneOf(blogFactory).parseBlog(rssBlog.getGroup());
will(returnValue(rssBlog)); will(returnValue(rssBlog));
oneOf(clientHelper).toList(rssLocalAuthor);
will(returnValue(rssAuthorList));
oneOf(clientHelper).addLocalMessage(txn, rssMessage, meta, true); oneOf(clientHelper).addLocalMessage(txn, rssMessage, meta, true);
oneOf(clientHelper).parseAndValidateAuthor(rssAuthorList);
will(returnValue(rssLocalAuthor));
oneOf(db).commitTransaction(txn); oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn); oneOf(db).endTransaction(txn);
}}); }});
@@ -357,7 +367,7 @@ public class BlogManagerImplTest extends BriarTestCase {
new BdfEntry(KEY_TYPE, POST.getInt()), new BdfEntry(KEY_TYPE, POST.getInt()),
new BdfEntry(KEY_RSS_FEED, false), new BdfEntry(KEY_RSS_FEED, false),
new BdfEntry(KEY_ORIGINAL_MSG_ID, messageId), new BdfEntry(KEY_ORIGINAL_MSG_ID, messageId),
new BdfEntry(KEY_AUTHOR, authorDict1), new BdfEntry(KEY_AUTHOR, authorList1),
new BdfEntry(KEY_TIMESTAMP, timestamp), new BdfEntry(KEY_TIMESTAMP, timestamp),
new BdfEntry(KEY_TIME_RECEIVED, timeReceived) new BdfEntry(KEY_TIME_RECEIVED, timeReceived)
); );
@@ -371,7 +381,7 @@ public class BlogManagerImplTest extends BriarTestCase {
new BdfEntry(KEY_ORIGINAL_MSG_ID, commentId), new BdfEntry(KEY_ORIGINAL_MSG_ID, commentId),
new BdfEntry(KEY_ORIGINAL_PARENT_MSG_ID, messageId), new BdfEntry(KEY_ORIGINAL_PARENT_MSG_ID, messageId),
new BdfEntry(KEY_PARENT_MSG_ID, messageId), new BdfEntry(KEY_PARENT_MSG_ID, messageId),
new BdfEntry(KEY_AUTHOR, authorDict1) new BdfEntry(KEY_AUTHOR, authorList1)
); );
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -381,14 +391,20 @@ public class BlogManagerImplTest extends BriarTestCase {
oneOf(blogPostFactory).createBlogComment(blog1.getId(), oneOf(blogPostFactory).createBlogComment(blog1.getId(),
localAuthor1, comment, messageId, messageId); localAuthor1, comment, messageId, messageId);
will(returnValue(commentMsg)); will(returnValue(commentMsg));
oneOf(clientHelper).toList(localAuthor1);
will(returnValue(authorList1));
// Store the comment // Store the comment
oneOf(clientHelper).addLocalMessage(txn, commentMsg, commentMeta, oneOf(clientHelper).addLocalMessage(txn, commentMsg, commentMeta,
true); true);
// Create the headers for the comment and its parent // Create the headers for the comment and its parent
oneOf(clientHelper).parseAndValidateAuthor(authorList1);
will(returnValue(localAuthor1));
oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId()); oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId());
will(returnValue(OURSELVES)); will(returnValue(OURSELVES));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, messageId); oneOf(clientHelper).getMessageMetadataAsDictionary(txn, messageId);
will(returnValue(postMeta)); will(returnValue(postMeta));
oneOf(clientHelper).parseAndValidateAuthor(authorList1);
will(returnValue(localAuthor1));
oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId()); oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId());
will(returnValue(OURSELVES)); will(returnValue(OURSELVES));
oneOf(db).commitTransaction(txn); oneOf(db).commitTransaction(txn);
@@ -447,7 +463,7 @@ public class BlogManagerImplTest extends BriarTestCase {
new BdfEntry(KEY_TYPE, WRAPPED_POST.getInt()), new BdfEntry(KEY_TYPE, WRAPPED_POST.getInt()),
new BdfEntry(KEY_RSS_FEED, false), new BdfEntry(KEY_RSS_FEED, false),
new BdfEntry(KEY_ORIGINAL_MSG_ID, messageId), new BdfEntry(KEY_ORIGINAL_MSG_ID, messageId),
new BdfEntry(KEY_AUTHOR, authorDict1), new BdfEntry(KEY_AUTHOR, authorList1),
new BdfEntry(KEY_TIMESTAMP, timestamp), new BdfEntry(KEY_TIMESTAMP, timestamp),
new BdfEntry(KEY_TIME_RECEIVED, timeReceived) new BdfEntry(KEY_TIME_RECEIVED, timeReceived)
); );
@@ -461,7 +477,7 @@ public class BlogManagerImplTest extends BriarTestCase {
new BdfEntry(KEY_ORIGINAL_MSG_ID, commentId), new BdfEntry(KEY_ORIGINAL_MSG_ID, commentId),
new BdfEntry(KEY_ORIGINAL_PARENT_MSG_ID, messageId), new BdfEntry(KEY_ORIGINAL_PARENT_MSG_ID, messageId),
new BdfEntry(KEY_PARENT_MSG_ID, wrappedPostId), new BdfEntry(KEY_PARENT_MSG_ID, wrappedPostId),
new BdfEntry(KEY_AUTHOR, authorDict2) new BdfEntry(KEY_AUTHOR, authorList2)
); );
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -476,6 +492,8 @@ public class BlogManagerImplTest extends BriarTestCase {
blog1.getGroup().getDescriptor(), timestamp, blog1.getGroup().getDescriptor(), timestamp,
originalPostBody); originalPostBody);
will(returnValue(wrappedPostMsg)); will(returnValue(wrappedPostMsg));
oneOf(clientHelper).toList(localAuthor1);
will(returnValue(authorList1));
// Store the wrapped post // Store the wrapped post
oneOf(clientHelper).addLocalMessage(txn, wrappedPostMsg, oneOf(clientHelper).addLocalMessage(txn, wrappedPostMsg,
wrappedPostMeta, true); wrappedPostMeta, true);
@@ -483,15 +501,21 @@ public class BlogManagerImplTest extends BriarTestCase {
oneOf(blogPostFactory).createBlogComment(blog2.getId(), oneOf(blogPostFactory).createBlogComment(blog2.getId(),
localAuthor2, comment, messageId, wrappedPostId); localAuthor2, comment, messageId, wrappedPostId);
will(returnValue(commentMsg)); will(returnValue(commentMsg));
oneOf(clientHelper).toList(localAuthor2);
will(returnValue(authorList2));
// Store the comment // Store the comment
oneOf(clientHelper).addLocalMessage(txn, commentMsg, commentMeta, oneOf(clientHelper).addLocalMessage(txn, commentMsg, commentMeta,
true); true);
// Create the headers for the comment and the wrapped post // Create the headers for the comment and the wrapped post
oneOf(clientHelper).parseAndValidateAuthor(authorList2);
will(returnValue(localAuthor2));
oneOf(identityManager).getAuthorStatus(txn, localAuthor2.getId()); oneOf(identityManager).getAuthorStatus(txn, localAuthor2.getId());
will(returnValue(OURSELVES)); will(returnValue(OURSELVES));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
wrappedPostId); wrappedPostId);
will(returnValue(wrappedPostMeta)); will(returnValue(wrappedPostMeta));
oneOf(clientHelper).parseAndValidateAuthor(authorList1);
will(returnValue(localAuthor1));
oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId()); oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId());
will(returnValue(VERIFIED)); will(returnValue(VERIFIED));
oneOf(db).commitTransaction(txn); oneOf(db).commitTransaction(txn);
@@ -550,7 +574,7 @@ public class BlogManagerImplTest extends BriarTestCase {
new BdfEntry(KEY_TYPE, WRAPPED_POST.getInt()), new BdfEntry(KEY_TYPE, WRAPPED_POST.getInt()),
new BdfEntry(KEY_RSS_FEED, true), new BdfEntry(KEY_RSS_FEED, true),
new BdfEntry(KEY_ORIGINAL_MSG_ID, rssMessageId), new BdfEntry(KEY_ORIGINAL_MSG_ID, rssMessageId),
new BdfEntry(KEY_AUTHOR, rssAuthorDict), new BdfEntry(KEY_AUTHOR, rssAuthorList),
new BdfEntry(KEY_TIMESTAMP, timestamp), new BdfEntry(KEY_TIMESTAMP, timestamp),
new BdfEntry(KEY_TIME_RECEIVED, timeReceived) new BdfEntry(KEY_TIME_RECEIVED, timeReceived)
); );
@@ -564,7 +588,7 @@ public class BlogManagerImplTest extends BriarTestCase {
new BdfEntry(KEY_ORIGINAL_MSG_ID, commentId), new BdfEntry(KEY_ORIGINAL_MSG_ID, commentId),
new BdfEntry(KEY_ORIGINAL_PARENT_MSG_ID, rssMessageId), new BdfEntry(KEY_ORIGINAL_PARENT_MSG_ID, rssMessageId),
new BdfEntry(KEY_PARENT_MSG_ID, wrappedPostId), new BdfEntry(KEY_PARENT_MSG_ID, wrappedPostId),
new BdfEntry(KEY_AUTHOR, authorDict1) new BdfEntry(KEY_AUTHOR, authorList1)
); );
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -579,6 +603,8 @@ public class BlogManagerImplTest extends BriarTestCase {
rssBlog.getGroup().getDescriptor(), timestamp, rssBlog.getGroup().getDescriptor(), timestamp,
originalPostBody); originalPostBody);
will(returnValue(wrappedPostMsg)); will(returnValue(wrappedPostMsg));
oneOf(clientHelper).toList(rssLocalAuthor);
will(returnValue(rssAuthorList));
// Store the wrapped post // Store the wrapped post
oneOf(clientHelper).addLocalMessage(txn, wrappedPostMsg, oneOf(clientHelper).addLocalMessage(txn, wrappedPostMsg,
wrappedPostMeta, true); wrappedPostMeta, true);
@@ -586,15 +612,21 @@ public class BlogManagerImplTest extends BriarTestCase {
oneOf(blogPostFactory).createBlogComment(blog1.getId(), oneOf(blogPostFactory).createBlogComment(blog1.getId(),
localAuthor1, comment, rssMessageId, wrappedPostId); localAuthor1, comment, rssMessageId, wrappedPostId);
will(returnValue(commentMsg)); will(returnValue(commentMsg));
oneOf(clientHelper).toList(localAuthor1);
will(returnValue(authorList1));
// Store the comment // Store the comment
oneOf(clientHelper).addLocalMessage(txn, commentMsg, commentMeta, oneOf(clientHelper).addLocalMessage(txn, commentMsg, commentMeta,
true); true);
// Create the headers for the comment and the wrapped post // Create the headers for the comment and the wrapped post
oneOf(clientHelper).parseAndValidateAuthor(authorList1);
will(returnValue(localAuthor1));
oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId()); oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId());
will(returnValue(OURSELVES)); will(returnValue(OURSELVES));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
wrappedPostId); wrappedPostId);
will(returnValue(wrappedPostMeta)); will(returnValue(wrappedPostMeta));
oneOf(clientHelper).parseAndValidateAuthor(rssAuthorList);
will(returnValue(rssLocalAuthor));
oneOf(db).commitTransaction(txn); oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn); oneOf(db).endTransaction(txn);
}}); }});
@@ -655,7 +687,7 @@ public class BlogManagerImplTest extends BriarTestCase {
new BdfEntry(KEY_TYPE, WRAPPED_POST.getInt()), new BdfEntry(KEY_TYPE, WRAPPED_POST.getInt()),
new BdfEntry(KEY_RSS_FEED, true), new BdfEntry(KEY_RSS_FEED, true),
new BdfEntry(KEY_ORIGINAL_MSG_ID, messageId), new BdfEntry(KEY_ORIGINAL_MSG_ID, messageId),
new BdfEntry(KEY_AUTHOR, rssAuthorDict), new BdfEntry(KEY_AUTHOR, rssAuthorList),
new BdfEntry(KEY_TIMESTAMP, timestamp), new BdfEntry(KEY_TIMESTAMP, timestamp),
new BdfEntry(KEY_TIME_RECEIVED, timeReceived) new BdfEntry(KEY_TIME_RECEIVED, timeReceived)
); );
@@ -667,7 +699,7 @@ public class BlogManagerImplTest extends BriarTestCase {
new BdfEntry(KEY_COMMENT, comment), new BdfEntry(KEY_COMMENT, comment),
new BdfEntry(KEY_PARENT_MSG_ID, rewrappedPostId), new BdfEntry(KEY_PARENT_MSG_ID, rewrappedPostId),
new BdfEntry(KEY_ORIGINAL_MSG_ID, originalCommentId), new BdfEntry(KEY_ORIGINAL_MSG_ID, originalCommentId),
new BdfEntry(KEY_AUTHOR, authorDict1), new BdfEntry(KEY_AUTHOR, authorList1),
new BdfEntry(KEY_TIMESTAMP, timestamp), new BdfEntry(KEY_TIMESTAMP, timestamp),
new BdfEntry(KEY_TIME_RECEIVED, timeReceived) new BdfEntry(KEY_TIME_RECEIVED, timeReceived)
); );
@@ -682,7 +714,7 @@ public class BlogManagerImplTest extends BriarTestCase {
new BdfEntry(KEY_ORIGINAL_MSG_ID, localCommentId), new BdfEntry(KEY_ORIGINAL_MSG_ID, localCommentId),
new BdfEntry(KEY_ORIGINAL_PARENT_MSG_ID, originalCommentId), new BdfEntry(KEY_ORIGINAL_PARENT_MSG_ID, originalCommentId),
new BdfEntry(KEY_PARENT_MSG_ID, wrappedCommentId), new BdfEntry(KEY_PARENT_MSG_ID, wrappedCommentId),
new BdfEntry(KEY_AUTHOR, authorDict2) new BdfEntry(KEY_AUTHOR, authorList2)
); );
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -694,6 +726,8 @@ public class BlogManagerImplTest extends BriarTestCase {
oneOf(blogPostFactory).rewrapWrappedPost(blog2.getId(), oneOf(blogPostFactory).rewrapWrappedPost(blog2.getId(),
wrappedPostBody); wrappedPostBody);
will(returnValue(rewrappedPostMsg)); will(returnValue(rewrappedPostMsg));
oneOf(clientHelper).toList(rssLocalAuthor);
will(returnValue(rssAuthorList));
// Store the rewrapped post // Store the rewrapped post
oneOf(clientHelper).addLocalMessage(txn, rewrappedPostMsg, oneOf(clientHelper).addLocalMessage(txn, rewrappedPostMsg,
rewrappedPostMeta, true); rewrappedPostMeta, true);
@@ -709,6 +743,8 @@ public class BlogManagerImplTest extends BriarTestCase {
blog1.getGroup().getDescriptor(), timestamp, blog1.getGroup().getDescriptor(), timestamp,
originalCommentBody, rewrappedPostId); originalCommentBody, rewrappedPostId);
will(returnValue(wrappedCommentMsg)); will(returnValue(wrappedCommentMsg));
oneOf(clientHelper).toList(localAuthor1);
will(returnValue(authorList1));
// Store the wrapped comment // Store the wrapped comment
oneOf(clientHelper).addLocalMessage(txn, wrappedCommentMsg, oneOf(clientHelper).addLocalMessage(txn, wrappedCommentMsg,
wrappedCommentMeta, true); wrappedCommentMeta, true);
@@ -717,21 +753,29 @@ public class BlogManagerImplTest extends BriarTestCase {
localAuthor2, localComment, originalCommentId, localAuthor2, localComment, originalCommentId,
wrappedCommentId); wrappedCommentId);
will(returnValue(localCommentMsg)); will(returnValue(localCommentMsg));
oneOf(clientHelper).toList(localAuthor2);
will(returnValue(authorList2));
// Store the new comment // Store the new comment
oneOf(clientHelper).addLocalMessage(txn, localCommentMsg, oneOf(clientHelper).addLocalMessage(txn, localCommentMsg,
localCommentMeta, true); localCommentMeta, true);
// Create the headers for the new comment, the wrapped comment and // Create the headers for the new comment, the wrapped comment and
// the rewrapped post // the rewrapped post
oneOf(clientHelper).parseAndValidateAuthor(authorList2);
will(returnValue(localAuthor2));
oneOf(identityManager).getAuthorStatus(txn, localAuthor2.getId()); oneOf(identityManager).getAuthorStatus(txn, localAuthor2.getId());
will(returnValue(OURSELVES)); will(returnValue(OURSELVES));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
wrappedCommentId); wrappedCommentId);
will(returnValue(wrappedCommentMeta)); will(returnValue(wrappedCommentMeta));
oneOf(clientHelper).parseAndValidateAuthor(authorList1);
will(returnValue(localAuthor1));
oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId()); oneOf(identityManager).getAuthorStatus(txn, localAuthor1.getId());
will(returnValue(VERIFIED)); will(returnValue(VERIFIED));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
rewrappedPostId); rewrappedPostId);
will(returnValue(rewrappedPostMeta)); will(returnValue(rewrappedPostMeta));
oneOf(clientHelper).parseAndValidateAuthor(rssAuthorList);
will(returnValue(rssLocalAuthor));
oneOf(db).commitTransaction(txn); oneOf(db).commitTransaction(txn);
oneOf(db).endTransaction(txn); oneOf(db).endTransaction(txn);
}}); }});
@@ -822,25 +866,14 @@ public class BlogManagerImplTest extends BriarTestCase {
context.assertIsSatisfied(); context.assertIsSatisfied();
} }
private LocalAuthor createLocalAuthor() {
return new LocalAuthor(new AuthorId(getRandomId()),
getRandomString(MAX_AUTHOR_NAME_LENGTH),
getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
getRandomBytes(123), System.currentTimeMillis());
}
private Blog createBlog(LocalAuthor localAuthor, boolean rssFeed) { private Blog createBlog(LocalAuthor localAuthor, boolean rssFeed) {
GroupId groupId = new GroupId(getRandomId()); GroupId groupId = new GroupId(getRandomId());
Group group = new Group(groupId, CLIENT_ID, getRandomBytes(42)); Group group = new Group(groupId, CLIENT_ID, getRandomBytes(42));
return new Blog(group, localAuthor, rssFeed); return new Blog(group, localAuthor, rssFeed);
} }
private BdfDictionary authorToBdfDictionary(Author a) { private BdfList authorToBdfList(Author a) {
return BdfDictionary.of( return BdfList.of(a.getFormatVersion(), a.getName(), a.getPublicKey());
new BdfEntry(KEY_AUTHOR_ID, a.getId()),
new BdfEntry(KEY_AUTHOR_NAME, a.getName()),
new BdfEntry(KEY_PUBLIC_KEY, a.getPublicKey())
);
} }
} }

View File

@@ -3,11 +3,9 @@ package org.briarproject.briar.blog;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.data.BdfDictionary; 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.BdfList;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupFactory; import org.briarproject.bramble.api.sync.GroupFactory;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
@@ -16,8 +14,6 @@ import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.system.SystemClock; import org.briarproject.bramble.system.SystemClock;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.blog.Blog; import org.briarproject.briar.api.blog.Blog;
import org.briarproject.briar.api.blog.BlogFactory; import org.briarproject.briar.api.blog.BlogFactory;
import org.briarproject.briar.test.BriarTestCase; import org.briarproject.briar.test.BriarTestCase;
@@ -28,15 +24,15 @@ import org.junit.Test;
import java.io.IOException; import java.io.IOException;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR; import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_NAME;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_COMMENT; import static org.briarproject.briar.api.blog.BlogConstants.KEY_COMMENT;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_MSG_ID; import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_MSG_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_PARENT_MSG_ID; import static org.briarproject.briar.api.blog.BlogConstants.KEY_ORIGINAL_PARENT_MSG_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID; import static org.briarproject.briar.api.blog.BlogConstants.KEY_PARENT_MSG_ID;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_PUBLIC_KEY;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ; import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_RSS_FEED; import static org.briarproject.briar.api.blog.BlogConstants.KEY_RSS_FEED;
import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID; import static org.briarproject.briar.api.blog.BlogManager.CLIENT_ID;
@@ -54,7 +50,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
private final Mockery context = new Mockery(); private final Mockery context = new Mockery();
private final Blog blog, rssBlog; private final Blog blog, rssBlog;
private final BdfDictionary authorDict; private final BdfList authorList;
private final byte[] descriptor; private final byte[] descriptor;
private final Group group; private final Group group;
private final Message message; private final Message message;
@@ -65,27 +61,24 @@ public class BlogPostValidatorTest extends BriarTestCase {
private final BlogFactory blogFactory = context.mock(BlogFactory.class); private final BlogFactory blogFactory = context.mock(BlogFactory.class);
private final ClientHelper clientHelper = context.mock(ClientHelper.class); private final ClientHelper clientHelper = context.mock(ClientHelper.class);
private final Author author; private final Author author;
private final String body = StringUtils.getRandomString(42); private final String body = getRandomString(42);
public BlogPostValidatorTest() { public BlogPostValidatorTest() {
GroupId groupId = new GroupId(TestUtils.getRandomId()); GroupId groupId = new GroupId(getRandomId());
descriptor = TestUtils.getRandomBytes(42); descriptor = getRandomBytes(42);
group = new Group(groupId, CLIENT_ID, descriptor); group = new Group(groupId, CLIENT_ID, descriptor);
AuthorId authorId = author = getAuthor();
new AuthorId(TestUtils.getRandomBytes(AuthorId.LENGTH)); authorList = BdfList.of(
byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH); author.getFormatVersion(),
author = new Author(authorId, "Author", publicKey); author.getName(),
authorDict = BdfDictionary.of( author.getPublicKey()
new BdfEntry(KEY_AUTHOR_ID, author.getId()),
new BdfEntry(KEY_AUTHOR_NAME, author.getName()),
new BdfEntry(KEY_PUBLIC_KEY, author.getPublicKey())
); );
blog = new Blog(group, author, false); blog = new Blog(group, author, false);
rssBlog = new Blog(group, author, true); rssBlog = new Blog(group, author, true);
MessageId messageId = new MessageId(TestUtils.getRandomId()); MessageId messageId = new MessageId(getRandomId());
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
byte[] raw = TestUtils.getRandomBytes(123); byte[] raw = getRandomBytes(123);
message = new Message(messageId, group.getId(), timestamp, raw); message = new Message(messageId, group.getId(), timestamp, raw);
MetadataEncoder metadataEncoder = context.mock(MetadataEncoder.class); MetadataEncoder metadataEncoder = context.mock(MetadataEncoder.class);
@@ -110,7 +103,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
private void testValidateProperBlogPost(Blog b, boolean rssFeed) private void testValidateProperBlogPost(Blog b, boolean rssFeed)
throws IOException, GeneralSecurityException { throws IOException, GeneralSecurityException {
byte[] sigBytes = TestUtils.getRandomBytes(42); byte[] sigBytes = getRandomBytes(42);
BdfList m = BdfList.of(POST.getInt(), body, sigBytes); BdfList m = BdfList.of(POST.getInt(), body, sigBytes);
BdfList signed = BdfList.of(b.getId(), message.getTimestamp(), body); BdfList signed = BdfList.of(b.getId(), message.getTimestamp(), body);
@@ -118,7 +111,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
BdfDictionary result = BdfDictionary result =
validator.validateMessage(message, group, m).getDictionary(); validator.validateMessage(message, group, m).getDictionary();
assertEquals(authorDict, result.getDictionary(KEY_AUTHOR)); assertEquals(authorList, result.getList(KEY_AUTHOR));
assertFalse(result.getBoolean(KEY_READ)); assertFalse(result.getBoolean(KEY_READ));
assertEquals(rssFeed, result.getBoolean(KEY_RSS_FEED)); assertEquals(rssFeed, result.getBoolean(KEY_RSS_FEED));
context.assertIsSatisfied(); context.assertIsSatisfied();
@@ -130,7 +123,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
BdfList content = BdfList.of(null, null, body); BdfList content = BdfList.of(null, null, body);
BdfList m = BdfList.of(POST.getInt(), content, null); BdfList m = BdfList.of(POST.getInt(), content, null);
validator.validateMessage(message, group, m).getDictionary(); validator.validateMessage(message, group, m);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
@@ -139,7 +132,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
BdfList content = BdfList.of(null, null, body, null); BdfList content = BdfList.of(null, null, body, null);
BdfList m = BdfList.of(POST.getInt(), content, null); BdfList m = BdfList.of(POST.getInt(), content, null);
validator.validateMessage(message, group, m).getDictionary(); validator.validateMessage(message, group, m);
} }
@Test @Test
@@ -147,9 +140,9 @@ public class BlogPostValidatorTest extends BriarTestCase {
throws IOException, GeneralSecurityException { throws IOException, GeneralSecurityException {
// comment, parent_original_id, parent_id, signature // comment, parent_original_id, parent_id, signature
String comment = "This is a blog comment"; String comment = "This is a blog comment";
MessageId pOriginalId = new MessageId(TestUtils.getRandomId()); MessageId pOriginalId = new MessageId(getRandomId());
MessageId currentId = new MessageId(TestUtils.getRandomId()); MessageId currentId = new MessageId(getRandomId());
byte[] sigBytes = TestUtils.getRandomBytes(42); byte[] sigBytes = getRandomBytes(42);
BdfList m = BdfList.of(COMMENT.getInt(), comment, pOriginalId, BdfList m = BdfList.of(COMMENT.getInt(), comment, pOriginalId,
currentId, sigBytes); currentId, sigBytes);
@@ -160,7 +153,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
validator.validateMessage(message, group, m).getDictionary(); validator.validateMessage(message, group, m).getDictionary();
assertEquals(comment, result.getString(KEY_COMMENT)); assertEquals(comment, result.getString(KEY_COMMENT));
assertEquals(authorDict, result.getDictionary(KEY_AUTHOR)); assertEquals(authorList, result.getList(KEY_AUTHOR));
assertEquals(pOriginalId.getBytes(), assertEquals(pOriginalId.getBytes(),
result.getRaw(KEY_ORIGINAL_PARENT_MSG_ID)); result.getRaw(KEY_ORIGINAL_PARENT_MSG_ID));
assertEquals(currentId.getBytes(), result.getRaw(KEY_PARENT_MSG_ID)); assertEquals(currentId.getBytes(), result.getRaw(KEY_PARENT_MSG_ID));
@@ -172,9 +165,9 @@ public class BlogPostValidatorTest extends BriarTestCase {
public void testValidateProperEmptyBlogComment() public void testValidateProperEmptyBlogComment()
throws IOException, GeneralSecurityException { throws IOException, GeneralSecurityException {
// comment, parent_original_id, signature, parent_current_id // comment, parent_original_id, signature, parent_current_id
MessageId originalId = new MessageId(TestUtils.getRandomId()); MessageId originalId = new MessageId(getRandomId());
MessageId currentId = new MessageId(TestUtils.getRandomId()); MessageId currentId = new MessageId(getRandomId());
byte[] sigBytes = TestUtils.getRandomBytes(42); byte[] sigBytes = getRandomBytes(42);
BdfList m = BdfList.of(COMMENT.getInt(), null, originalId, currentId, BdfList m = BdfList.of(COMMENT.getInt(), null, originalId, currentId,
sigBytes); sigBytes);
@@ -203,7 +196,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
private void testValidateProperWrappedPost(Blog b, boolean rssFeed) private void testValidateProperWrappedPost(Blog b, boolean rssFeed)
throws IOException, GeneralSecurityException { throws IOException, GeneralSecurityException {
// group descriptor, timestamp, content, signature // group descriptor, timestamp, content, signature
byte[] sigBytes = TestUtils.getRandomBytes(42); byte[] sigBytes = getRandomBytes(42);
BdfList m = BdfList.of(WRAPPED_POST.getInt(), descriptor, BdfList m = BdfList.of(WRAPPED_POST.getInt(), descriptor,
message.getTimestamp(), body, sigBytes); message.getTimestamp(), body, sigBytes);
@@ -211,7 +204,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
expectCrypto(b, SIGNING_LABEL_POST, signed, sigBytes); expectCrypto(b, SIGNING_LABEL_POST, signed, sigBytes);
BdfList originalList = BdfList.of(POST.getInt(), body, sigBytes); BdfList originalList = BdfList.of(POST.getInt(), body, sigBytes);
byte[] originalBody = TestUtils.getRandomBytes(42); byte[] originalBody = getRandomBytes(42);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(groupFactory).createGroup(CLIENT_ID, CLIENT_VERSION, oneOf(groupFactory).createGroup(CLIENT_ID, CLIENT_VERSION,
@@ -230,7 +223,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
BdfDictionary result = BdfDictionary result =
validator.validateMessage(message, group, m).getDictionary(); validator.validateMessage(message, group, m).getDictionary();
assertEquals(authorDict, result.getDictionary(KEY_AUTHOR)); assertEquals(authorList, result.getList(KEY_AUTHOR));
assertEquals(rssFeed, result.getBoolean(KEY_RSS_FEED)); assertEquals(rssFeed, result.getBoolean(KEY_RSS_FEED));
context.assertIsSatisfied(); context.assertIsSatisfied();
} }
@@ -241,10 +234,10 @@ public class BlogPostValidatorTest extends BriarTestCase {
// group descriptor, timestamp, comment, parent_original_id, signature, // group descriptor, timestamp, comment, parent_original_id, signature,
// parent_current_id // parent_current_id
String comment = "This is another comment"; String comment = "This is another comment";
MessageId originalId = new MessageId(TestUtils.getRandomId()); MessageId originalId = new MessageId(getRandomId());
MessageId oldId = new MessageId(TestUtils.getRandomId()); MessageId oldId = new MessageId(getRandomId());
byte[] sigBytes = TestUtils.getRandomBytes(42); byte[] sigBytes = getRandomBytes(42);
MessageId currentId = new MessageId(TestUtils.getRandomId()); MessageId currentId = new MessageId(getRandomId());
BdfList m = BdfList.of(WRAPPED_COMMENT.getInt(), descriptor, BdfList m = BdfList.of(WRAPPED_COMMENT.getInt(), descriptor,
message.getTimestamp(), comment, originalId, oldId, sigBytes, message.getTimestamp(), comment, originalId, oldId, sigBytes,
currentId); currentId);
@@ -255,7 +248,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
BdfList originalList = BdfList.of(COMMENT.getInt(), comment, BdfList originalList = BdfList.of(COMMENT.getInt(), comment,
originalId, oldId, sigBytes); originalId, oldId, sigBytes);
byte[] originalBody = TestUtils.getRandomBytes(42); byte[] originalBody = getRandomBytes(42);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(groupFactory).createGroup(CLIENT_ID, CLIENT_VERSION, oneOf(groupFactory).createGroup(CLIENT_ID, CLIENT_VERSION,
@@ -273,7 +266,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
validator.validateMessage(message, group, m).getDictionary(); validator.validateMessage(message, group, m).getDictionary();
assertEquals(comment, result.getString(KEY_COMMENT)); assertEquals(comment, result.getString(KEY_COMMENT));
assertEquals(authorDict, result.getDictionary(KEY_AUTHOR)); assertEquals(authorList, result.getList(KEY_AUTHOR));
assertEquals( assertEquals(
message.getId().getBytes(), result.getRaw(KEY_ORIGINAL_MSG_ID)); message.getId().getBytes(), result.getRaw(KEY_ORIGINAL_MSG_ID));
assertEquals(currentId.getBytes(), result.getRaw(KEY_PARENT_MSG_ID)); assertEquals(currentId.getBytes(), result.getRaw(KEY_PARENT_MSG_ID));
@@ -285,6 +278,8 @@ public class BlogPostValidatorTest extends BriarTestCase {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(blogFactory).parseBlog(group); oneOf(blogFactory).parseBlog(group);
will(returnValue(b)); will(returnValue(b));
oneOf(clientHelper).toList(b.getAuthor());
will(returnValue(authorList));
oneOf(clientHelper) oneOf(clientHelper)
.verifySignature(label, sig, author.getPublicKey(), signed); .verifySignature(label, sig, author.getPublicKey(), signed);
}}); }});

View File

@@ -10,7 +10,6 @@ import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
@@ -38,6 +37,7 @@ import javax.net.SocketFactory;
import okhttp3.Dns; import okhttp3.Dns;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEEDS; import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEEDS;
@@ -66,10 +66,7 @@ public class FeedManagerImplTest extends BrambleMockTestCase {
private final GroupId blogGroupId = new GroupId(getRandomId()); private final GroupId blogGroupId = new GroupId(getRandomId());
private final Group blogGroup = private final Group blogGroup =
new Group(blogGroupId, BlogManager.CLIENT_ID, getRandomBytes(42)); new Group(blogGroupId, BlogManager.CLIENT_ID, getRandomBytes(42));
private final AuthorId authorId = new AuthorId(getRandomId()); private final LocalAuthor localAuthor = getLocalAuthor();
private final LocalAuthor localAuthor =
new LocalAuthor(authorId, "author", getRandomBytes(2),
getRandomBytes(2), 0);
private final Blog blog = new Blog(blogGroup, localAuthor, true); private final Blog blog = new Blog(blogGroup, localAuthor, true);
private final Feed feed = private final Feed feed =
new Feed("http://example.org", blog, localAuthor, 0); new Feed("http://example.org", blog, localAuthor, 0);

View File

@@ -6,21 +6,24 @@ import org.briarproject.bramble.api.client.BdfMessageContext;
import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.sync.InvalidMessageException; import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.test.ValidatorTestCase; import org.briarproject.bramble.test.ValidatorTestCase;
import org.briarproject.bramble.util.StringUtils;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.junit.Test; import org.junit.Test;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.Collection; import java.util.Collection;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.blog.BlogConstants.KEY_READ;
import static org.briarproject.briar.api.forum.ForumConstants.KEY_AUTHOR;
import static org.briarproject.briar.api.forum.ForumConstants.KEY_PARENT;
import static org.briarproject.briar.api.forum.ForumConstants.KEY_TIMESTAMP;
import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH; import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
import static org.briarproject.briar.api.forum.ForumPostFactory.SIGNING_LABEL_POST; import static org.briarproject.briar.api.forum.ForumPostFactory.SIGNING_LABEL_POST;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
@@ -29,229 +32,101 @@ import static org.junit.Assert.assertFalse;
public class ForumPostValidatorTest extends ValidatorTestCase { public class ForumPostValidatorTest extends ValidatorTestCase {
private final MessageId parentId = new MessageId(TestUtils.getRandomId()); private final MessageId parentId = new MessageId(getRandomId());
private final String authorName = private final String content = getRandomString(MAX_FORUM_POST_BODY_LENGTH);
StringUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH); private final byte[] signature = getRandomBytes(MAX_SIGNATURE_LENGTH);
private final byte[] authorPublicKey = private final Author author = getAuthor();
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH); private final String authorName = author.getName();
private final BdfList authorList = BdfList.of(authorName, authorPublicKey); private final byte[] authorPublicKey = author.getPublicKey();
private final String content = private final BdfList authorList = BdfList.of(author.getFormatVersion(),
StringUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH); authorName, authorPublicKey);
private final byte[] signature =
TestUtils.getRandomBytes(MAX_SIGNATURE_LENGTH);
private final AuthorId authorId = new AuthorId(TestUtils.getRandomId());
private final Author author =
new Author(authorId, authorName, authorPublicKey);
private final BdfList signedWithParent = BdfList.of(groupId, timestamp, private final BdfList signedWithParent = BdfList.of(groupId, timestamp,
parentId.getBytes(), authorList, content); parentId.getBytes(), authorList, content);
private final BdfList signedWithoutParent = BdfList.of(groupId, timestamp, private final BdfList signedWithoutParent = BdfList.of(groupId, timestamp,
null, authorList, content); null, authorList, content);
private final ForumPostValidator v = new ForumPostValidator(clientHelper,
metadataEncoder, clock);
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooShortBody() throws Exception { public void testRejectsTooShortBody() throws Exception {
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(parentId, authorList, content)); BdfList.of(parentId, authorList, content));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongBody() throws Exception { public void testRejectsTooLongBody() throws Exception {
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(parentId, authorList, content, signature, 123)); BdfList.of(parentId, authorList, content, signature, 123));
} }
@Test @Test
public void testAcceptsNullParentId() throws Exception { public void testAcceptsNullParentId() throws Exception {
expectCreateAuthor();
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
will(returnValue(author));
oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature, oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature,
authorPublicKey, signedWithoutParent); authorPublicKey, signedWithoutParent);
}}); }});
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext messageContext = v.validateMessage(message, group,
BdfList.of(null, authorList, content, signature)); BdfList.of(null, authorList, content, signature));
assertExpectedContext(messageContext, false, authorName); assertExpectedContext(messageContext, false);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNonRawParentId() throws Exception { public void testRejectsNonRawParentId() throws Exception {
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(123, authorList, content, signature)); BdfList.of(123, authorList, content, signature));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooShortParentId() throws Exception { public void testRejectsTooShortParentId() throws Exception {
byte[] invalidParentId = TestUtils.getRandomBytes(UniqueId.LENGTH - 1); byte[] invalidParentId = getRandomBytes(UniqueId.LENGTH - 1);
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(invalidParentId, authorList, content, signature)); BdfList.of(invalidParentId, authorList, content, signature));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongParentId() throws Exception { public void testRejectsTooLongParentId() throws Exception {
byte[] invalidParentId = TestUtils.getRandomBytes(UniqueId.LENGTH + 1); byte[] invalidParentId = getRandomBytes(UniqueId.LENGTH + 1);
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(invalidParentId, authorList, content, signature)); BdfList.of(invalidParentId, authorList, content, signature));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNullAuthorList() throws Exception { public void testRejectsNullAuthorList() throws Exception {
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(parentId, null, content, signature)); BdfList.of(parentId, null, content, signature));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNonListAuthorList() throws Exception { public void testRejectsNonListAuthorList() throws Exception {
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(parentId, 123, content, signature)); BdfList.of(parentId, 123, content, signature));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooShortAuthorList() throws Exception { public void testRejectsInvalidAuthor() throws Exception {
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group,
BdfList.of(parentId, new BdfList(), content, signature));
}
@Test(expected = FormatException.class)
public void testRejectsTooLongAuthorList() throws Exception {
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group,
BdfList.of(parentId, BdfList.of(1, 2, 3), content, signature));
}
@Test(expected = FormatException.class)
public void testRejectsNullAuthorName() throws Exception {
BdfList invalidAuthorList = BdfList.of(null, authorPublicKey);
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group,
BdfList.of(parentId, invalidAuthorList, content, signature));
}
@Test(expected = FormatException.class)
public void testRejectsNonStringAuthorName() throws Exception {
BdfList invalidAuthorList = BdfList.of(123, authorPublicKey);
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group,
BdfList.of(parentId, invalidAuthorList, content, signature));
}
@Test(expected = FormatException.class)
public void testRejectsTooShortAuthorName() throws Exception {
BdfList invalidAuthorList = BdfList.of("", authorPublicKey);
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group,
BdfList.of(parentId, invalidAuthorList, content, signature));
}
@Test
public void testAcceptsMinLengthAuthorName() throws Exception {
String shortAuthorName = StringUtils.getRandomString(1);
BdfList shortNameAuthorList =
BdfList.of(shortAuthorName, authorPublicKey);
Author shortNameAuthor =
new Author(authorId, shortAuthorName, authorPublicKey);
BdfList signedWithShortNameAuthor = BdfList.of(groupId, timestamp,
parentId.getBytes(), shortNameAuthorList, content);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(authorFactory).createAuthor(shortAuthorName, authorPublicKey); oneOf(clientHelper).parseAndValidateAuthor(authorList);
will(returnValue(shortNameAuthor)); will(throwException(new FormatException()));
oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature,
authorPublicKey, signedWithShortNameAuthor);
}}); }});
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
BdfMessageContext messageContext = v.validateMessage(message, group,
BdfList.of(parentId, shortNameAuthorList, content, signature));
assertExpectedContext(messageContext, true, shortAuthorName);
}
@Test(expected = FormatException.class)
public void testRejectsTooLongAuthorName() throws Exception {
String invalidAuthorName =
StringUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH + 1);
BdfList invalidAuthorList =
BdfList.of(invalidAuthorName, authorPublicKey);
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(parentId, invalidAuthorList, content, signature)); BdfList.of(parentId, authorList, content, signature));
}
@Test(expected = FormatException.class)
public void testRejectsNullAuthorPublicKey() throws Exception {
BdfList invalidAuthorList = BdfList.of(authorName, null);
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group,
BdfList.of(parentId, invalidAuthorList, content, signature));
}
@Test(expected = FormatException.class)
public void testRejectsNonRawAuthorPublicKey() throws Exception {
BdfList invalidAuthorList = BdfList.of(authorName, 123);
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group,
BdfList.of(parentId, invalidAuthorList, content, signature));
}
@Test(expected = FormatException.class)
public void testRejectsTooLongAuthorPublicKey() throws Exception {
byte[] invalidAuthorPublicKey =
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1);
BdfList invalidAuthorList =
BdfList.of(authorName, invalidAuthorPublicKey);
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group,
BdfList.of(parentId, invalidAuthorList, content, signature));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNullContent() throws Exception { public void testRejectsNullContent() throws Exception {
context.checking(new Expectations() {{ expectCreateAuthor();
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
will(returnValue(author));
}});
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(parentId, authorList, null, signature)); BdfList.of(parentId, authorList, null, signature));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNonStringContent() throws Exception { public void testRejectsNonStringContent() throws Exception {
context.checking(new Expectations() {{ expectCreateAuthor();
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
will(returnValue(author));
}});
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(parentId, authorList, 123, signature)); BdfList.of(parentId, authorList, 123, signature));
} }
@@ -262,74 +137,49 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
BdfList signedWithShortContent = BdfList.of(groupId, timestamp, BdfList signedWithShortContent = BdfList.of(groupId, timestamp,
parentId.getBytes(), authorList, shortContent); parentId.getBytes(), authorList, shortContent);
expectCreateAuthor();
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
will(returnValue(author));
oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature, oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature,
authorPublicKey, signedWithShortContent); authorPublicKey, signedWithShortContent);
}}); }});
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext messageContext = v.validateMessage(message, group,
BdfList.of(parentId, authorList, shortContent, signature)); BdfList.of(parentId, authorList, shortContent, signature));
assertExpectedContext(messageContext, true, authorName); assertExpectedContext(messageContext, true);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongContent() throws Exception { public void testRejectsTooLongContent() throws Exception {
String invalidContent = String invalidContent = getRandomString(MAX_FORUM_POST_BODY_LENGTH + 1);
StringUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH + 1);
context.checking(new Expectations() {{ expectCreateAuthor();
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
will(returnValue(author));
}});
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(parentId, authorList, invalidContent, signature)); BdfList.of(parentId, authorList, invalidContent, signature));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNullSignature() throws Exception { public void testRejectsNullSignature() throws Exception {
context.checking(new Expectations() {{ expectCreateAuthor();
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
will(returnValue(author));
}});
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(parentId, authorList, content, null)); BdfList.of(parentId, authorList, content, null));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNonRawSignature() throws Exception { public void testRejectsNonRawSignature() throws Exception {
context.checking(new Expectations() {{ expectCreateAuthor();
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
will(returnValue(author));
}});
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(parentId, authorList, content, 123)); BdfList.of(parentId, authorList, content, 123));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongSignature() throws Exception { public void testRejectsTooLongSignature() throws Exception {
byte[] invalidSignature = byte[] invalidSignature = getRandomBytes(MAX_SIGNATURE_LENGTH + 1);
TestUtils.getRandomBytes(MAX_SIGNATURE_LENGTH + 1);
context.checking(new Expectations() {{ expectCreateAuthor();
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
will(returnValue(author));
}});
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(parentId, authorList, content, invalidSignature)); BdfList.of(parentId, authorList, content, invalidSignature));
} }
@@ -337,16 +187,13 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsIfVerifyingSignatureThrowsFormatException() public void testRejectsIfVerifyingSignatureThrowsFormatException()
throws Exception { throws Exception {
expectCreateAuthor();
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
will(returnValue(author));
oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature, oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature,
authorPublicKey, signedWithParent); authorPublicKey, signedWithParent);
will(throwException(new FormatException())); will(throwException(new FormatException()));
}}); }});
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(parentId, authorList, content, signature)); BdfList.of(parentId, authorList, content, signature));
} }
@@ -354,39 +201,39 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
@Test(expected = InvalidMessageException.class) @Test(expected = InvalidMessageException.class)
public void testRejectsIfVerifyingSignatureThrowsGeneralSecurityException() public void testRejectsIfVerifyingSignatureThrowsGeneralSecurityException()
throws Exception { throws Exception {
expectCreateAuthor();
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
will(returnValue(author));
oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature, oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature,
authorPublicKey, signedWithParent); authorPublicKey, signedWithParent);
will(throwException(new GeneralSecurityException())); will(throwException(new GeneralSecurityException()));
}}); }});
ForumPostValidator v = new ForumPostValidator(authorFactory,
clientHelper, metadataEncoder, clock);
v.validateMessage(message, group, v.validateMessage(message, group,
BdfList.of(parentId, authorList, content, signature)); BdfList.of(parentId, authorList, content, signature));
} }
private void expectCreateAuthor() throws Exception {
context.checking(new Expectations() {{
oneOf(clientHelper).parseAndValidateAuthor(authorList);
will(returnValue(author));
}});
}
private void assertExpectedContext(BdfMessageContext messageContext, private void assertExpectedContext(BdfMessageContext messageContext,
boolean hasParent, String authorName) throws FormatException { boolean hasParent) throws FormatException {
BdfDictionary meta = messageContext.getDictionary(); BdfDictionary meta = messageContext.getDictionary();
Collection<MessageId> dependencies = messageContext.getDependencies(); Collection<MessageId> dependencies = messageContext.getDependencies();
if (hasParent) { if (hasParent) {
assertEquals(4, meta.size()); assertEquals(4, meta.size());
assertArrayEquals(parentId.getBytes(), meta.getRaw("parent")); assertArrayEquals(parentId.getBytes(), meta.getRaw(KEY_PARENT));
assertEquals(1, dependencies.size()); assertEquals(1, dependencies.size());
assertEquals(parentId, dependencies.iterator().next()); assertEquals(parentId, dependencies.iterator().next());
} else { } else {
assertEquals(3, meta.size()); assertEquals(3, meta.size());
assertEquals(0, dependencies.size()); assertEquals(0, dependencies.size());
} }
assertEquals(timestamp, meta.getLong("timestamp").longValue()); assertEquals(timestamp, meta.getLong(KEY_TIMESTAMP).longValue());
assertFalse(meta.getBoolean("read")); assertFalse(meta.getBoolean(KEY_READ));
BdfDictionary authorMeta = meta.getDictionary("author"); assertEquals(authorList, meta.getList(KEY_AUTHOR));
assertEquals(3, authorMeta.size());
assertArrayEquals(authorId.getBytes(), authorMeta.getRaw("id"));
assertEquals(authorName, authorMeta.getString("name"));
assertArrayEquals(authorPublicKey, authorMeta.getRaw("publicKey"));
} }
} }

View File

@@ -25,7 +25,6 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.briar.api.client.SessionId; import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.api.introduction.IntroduceeProtocolState; import org.briarproject.briar.api.introduction.IntroduceeProtocolState;
import org.briarproject.briar.test.BriarTestCase; import org.briarproject.briar.test.BriarTestCase;
@@ -40,6 +39,10 @@ import java.security.SecureRandom;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.briar.api.introduction.IntroduceeProtocolState.AWAIT_REQUEST; import static org.briarproject.briar.api.introduction.IntroduceeProtocolState.AWAIT_REQUEST;
import static org.briarproject.briar.api.introduction.IntroductionConstants.ACCEPT; import static org.briarproject.briar.api.introduction.IntroductionConstants.ACCEPT;
import static org.briarproject.briar.api.introduction.IntroductionConstants.ADDED_CONTACT_ID; import static org.briarproject.briar.api.introduction.IntroductionConstants.ADDED_CONTACT_ID;
@@ -125,47 +128,41 @@ public class IntroduceeManagerTest extends BriarTestCase {
authorFactory, contactManager, identityManager, authorFactory, contactManager, identityManager,
introductionGroupFactory); introductionGroupFactory);
AuthorId authorId0 = new AuthorId(TestUtils.getRandomId()); Author author0 = getAuthor();
Author author0 = new Author(authorId0, "Introducer", AuthorId localAuthorId = new AuthorId(getRandomId());
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH));
AuthorId localAuthorId = new AuthorId(TestUtils.getRandomId());
ContactId contactId0 = new ContactId(234); ContactId contactId0 = new ContactId(234);
introducer = introducer =
new Contact(contactId0, author0, localAuthorId, true, true); new Contact(contactId0, author0, localAuthorId, true, true);
AuthorId authorId1 = new AuthorId(TestUtils.getRandomId()); Author author1 = getAuthor();
Author author1 = new Author(authorId1, "Introducee1", AuthorId localAuthorId1 = new AuthorId(getRandomId());
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH));
AuthorId localAuthorId1 = new AuthorId(TestUtils.getRandomId());
ContactId contactId1 = new ContactId(234); ContactId contactId1 = new ContactId(234);
introducee1 = introducee1 =
new Contact(contactId1, author1, localAuthorId1, true, true); new Contact(contactId1, author1, localAuthorId1, true, true);
AuthorId authorId2 = new AuthorId(TestUtils.getRandomId()); Author author2 = getAuthor();
Author author2 = new Author(authorId2, "Introducee2",
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH));
ContactId contactId2 = new ContactId(235); ContactId contactId2 = new ContactId(235);
introducee2 = introducee2 =
new Contact(contactId2, author2, localAuthorId, true, true); new Contact(contactId2, author2, localAuthorId, true, true);
ClientId clientId = IntroductionManagerImpl.CLIENT_ID; ClientId clientId = IntroductionManagerImpl.CLIENT_ID;
localGroup1 = new Group(new GroupId(TestUtils.getRandomId()), localGroup1 = new Group(new GroupId(getRandomId()),
clientId, new byte[0]); clientId, new byte[0]);
introductionGroup1 = new Group(new GroupId(TestUtils.getRandomId()), introductionGroup1 = new Group(new GroupId(getRandomId()),
clientId, new byte[0]); clientId, new byte[0]);
sessionId = new SessionId(TestUtils.getRandomId()); sessionId = new SessionId(getRandomId());
localStateMessage = new Message( localStateMessage = new Message(
new MessageId(TestUtils.getRandomId()), new MessageId(getRandomId()),
localGroup1.getId(), localGroup1.getId(),
time, time,
TestUtils.getRandomBytes(MESSAGE_HEADER_LENGTH + 1) getRandomBytes(MESSAGE_HEADER_LENGTH + 1)
); );
message1 = new Message( message1 = new Message(
new MessageId(TestUtils.getRandomId()), new MessageId(getRandomId()),
introductionGroup1.getId(), introductionGroup1.getId(),
time, time,
TestUtils.getRandomBytes(MESSAGE_HEADER_LENGTH + 1) getRandomBytes(MESSAGE_HEADER_LENGTH + 1)
); );
txn = new Transaction(null, false); txn = new Transaction(null, false);
@@ -218,7 +215,7 @@ public class IntroduceeManagerTest extends BriarTestCase {
// turn request message into a response // turn request message into a response
msg.put(ACCEPT, true); msg.put(ACCEPT, true);
msg.put(TIME, time); msg.put(TIME, time);
msg.put(E_PUBLIC_KEY, TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH)); msg.put(E_PUBLIC_KEY, getRandomBytes(MAX_PUBLIC_KEY_LENGTH));
msg.put(TRANSPORT, new BdfDictionary()); msg.put(TRANSPORT, new BdfDictionary());
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -251,13 +248,13 @@ public class IntroduceeManagerTest extends BriarTestCase {
// prepare state for incoming ACK // prepare state for incoming ACK
state.put(STATE, IntroduceeProtocolState.AWAIT_ACK.ordinal()); state.put(STATE, IntroduceeProtocolState.AWAIT_ACK.ordinal());
state.put(ADDED_CONTACT_ID, 2); state.put(ADDED_CONTACT_ID, 2);
byte[] nonce = TestUtils.getRandomBytes(42); byte[] nonce = getRandomBytes(42);
state.put(NONCE, nonce); state.put(NONCE, nonce);
state.put(PUBLIC_KEY, introducee2.getAuthor().getPublicKey()); state.put(PUBLIC_KEY, introducee2.getAuthor().getPublicKey());
// create incoming ACK message // create incoming ACK message
byte[] mac = TestUtils.getRandomBytes(MAC_LENGTH); byte[] mac = getRandomBytes(MAC_LENGTH);
byte[] sig = TestUtils.getRandomBytes(MAX_SIGNATURE_LENGTH); byte[] sig = getRandomBytes(MAX_SIGNATURE_LENGTH);
BdfDictionary ack = BdfDictionary.of( BdfDictionary ack = BdfDictionary.of(
new BdfEntry(TYPE, TYPE_ACK), new BdfEntry(TYPE, TYPE_ACK),
new BdfEntry(SESSION_ID, sessionId), new BdfEntry(SESSION_ID, sessionId),
@@ -288,8 +285,8 @@ public class IntroduceeManagerTest extends BriarTestCase {
throws FormatException, DbException, GeneralSecurityException { throws FormatException, DbException, GeneralSecurityException {
byte[] publicKeyBytes = introducee2.getAuthor().getPublicKey(); byte[] publicKeyBytes = introducee2.getAuthor().getPublicKey();
byte[] nonce = TestUtils.getRandomBytes(MAC_LENGTH); byte[] nonce = getRandomBytes(MAC_LENGTH);
byte[] sig = TestUtils.getRandomBytes(MAC_LENGTH); byte[] sig = getRandomBytes(MAC_LENGTH);
BdfDictionary state = new BdfDictionary(); BdfDictionary state = new BdfDictionary();
state.put(PUBLIC_KEY, publicKeyBytes); state.put(PUBLIC_KEY, publicKeyBytes);
@@ -311,10 +308,9 @@ public class IntroduceeManagerTest extends BriarTestCase {
byte[] publicKeyBytes = introducee2.getAuthor().getPublicKey(); byte[] publicKeyBytes = introducee2.getAuthor().getPublicKey();
BdfDictionary tp = BdfDictionary.of(new BdfEntry("fake", "fake")); BdfDictionary tp = BdfDictionary.of(new BdfEntry("fake", "fake"));
byte[] ePublicKeyBytes = byte[] ePublicKeyBytes = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH); byte[] mac = getRandomBytes(MAC_LENGTH);
byte[] mac = TestUtils.getRandomBytes(MAC_LENGTH); SecretKey macKey = getSecretKey();
SecretKey macKey = TestUtils.getSecretKey();
// move state to where it would be after an ACK arrived // move state to where it would be after an ACK arrived
BdfDictionary state = new BdfDictionary(); BdfDictionary state = new BdfDictionary();
@@ -325,7 +321,7 @@ public class IntroduceeManagerTest extends BriarTestCase {
state.put(MAC, mac); state.put(MAC, mac);
state.put(MAC_KEY, macKey.getBytes()); state.put(MAC_KEY, macKey.getBytes());
byte[] signBytes = TestUtils.getRandomBytes(42); byte[] signBytes = getRandomBytes(42);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(clientHelper).toByteArray( oneOf(clientHelper).toByteArray(
BdfList.of(publicKeyBytes, ePublicKeyBytes, tp, time)); BdfList.of(publicKeyBytes, ePublicKeyBytes, tp, time));
@@ -348,7 +344,7 @@ public class IntroduceeManagerTest extends BriarTestCase {
oneOf(cryptoComponent).mac(with(MAC_LABEL), oneOf(cryptoComponent).mac(with(MAC_LABEL),
with(samePropertyValuesAs(macKey)), with(samePropertyValuesAs(macKey)),
with(array(equal(signBytes)))); with(array(equal(signBytes))));
will(returnValue(TestUtils.getRandomBytes(MAC_LENGTH))); will(returnValue(getRandomBytes(MAC_LENGTH)));
}}); }});
try { try {
introduceeManager.verifyMac(state); introduceeManager.verifyMac(state);

View File

@@ -18,7 +18,6 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.briar.test.BriarTestCase; import org.briarproject.briar.test.BriarTestCase;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.Mockery; import org.jmock.Mockery;
@@ -27,7 +26,9 @@ import org.junit.Test;
import java.security.SecureRandom; import java.security.SecureRandom;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.briar.api.introduction.IntroducerProtocolState.AWAIT_RESPONSES; import static org.briarproject.briar.api.introduction.IntroducerProtocolState.AWAIT_RESPONSES;
import static org.briarproject.briar.api.introduction.IntroducerProtocolState.PREPARE_REQUESTS; import static org.briarproject.briar.api.introduction.IntroducerProtocolState.PREPARE_REQUESTS;
import static org.briarproject.briar.api.introduction.IntroductionConstants.AUTHOR_ID_1; import static org.briarproject.briar.api.introduction.IntroductionConstants.AUTHOR_ID_1;
@@ -80,27 +81,23 @@ public class IntroducerManagerTest extends BriarTestCase {
new IntroducerManager(messageSender, clientHelper, clock, new IntroducerManager(messageSender, clientHelper, clock,
cryptoComponent, introductionGroupFactory); cryptoComponent, introductionGroupFactory);
AuthorId authorId1 = new AuthorId(TestUtils.getRandomId()); Author author1 = getAuthor();
Author author1 = new Author(authorId1, "Introducee1", AuthorId localAuthorId1 = new AuthorId(getRandomId());
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH));
AuthorId localAuthorId1 = new AuthorId(TestUtils.getRandomId());
ContactId contactId1 = new ContactId(234); ContactId contactId1 = new ContactId(234);
introducee1 = introducee1 =
new Contact(contactId1, author1, localAuthorId1, true, true); new Contact(contactId1, author1, localAuthorId1, true, true);
AuthorId authorId2 = new AuthorId(TestUtils.getRandomId()); Author author2 = getAuthor();
Author author2 = new Author(authorId2, "Introducee2", AuthorId localAuthorId2 = new AuthorId(getRandomId());
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH));
AuthorId localAuthorId2 = new AuthorId(TestUtils.getRandomId());
ContactId contactId2 = new ContactId(235); ContactId contactId2 = new ContactId(235);
introducee2 = introducee2 =
new Contact(contactId2, author2, localAuthorId2, true, true); new Contact(contactId2, author2, localAuthorId2, true, true);
localGroup0 = new Group(new GroupId(TestUtils.getRandomId()), localGroup0 = new Group(new GroupId(getRandomId()),
getClientId(), new byte[0]); getClientId(), new byte[0]);
introductionGroup1 = new Group(new GroupId(TestUtils.getRandomId()), introductionGroup1 = new Group(new GroupId(getRandomId()),
getClientId(), new byte[0]); getClientId(), new byte[0]);
introductionGroup2 = new Group(new GroupId(TestUtils.getRandomId()), introductionGroup2 = new Group(new GroupId(getRandomId()),
getClientId(), new byte[0]); getClientId(), new byte[0]);
context.assertIsSatisfied(); context.assertIsSatisfied();
@@ -113,8 +110,8 @@ public class IntroducerManagerTest extends BriarTestCase {
context.setImposteriser(ClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
SecureRandom secureRandom = context.mock(SecureRandom.class); SecureRandom secureRandom = context.mock(SecureRandom.class);
Bytes salt = new Bytes(new byte[64]); Bytes salt = new Bytes(new byte[64]);
Message msg = new Message(new MessageId(TestUtils.getRandomId()), Message msg = new Message(new MessageId(getRandomId()),
localGroup0.getId(), time, TestUtils.getRandomBytes(64)); localGroup0.getId(), time, getRandomBytes(64));
BdfDictionary state = new BdfDictionary(); BdfDictionary state = new BdfDictionary();
state.put(SESSION_ID, msg.getId()); state.put(SESSION_ID, msg.getId());
state.put(STORAGE_ID, msg.getId()); state.put(STORAGE_ID, msg.getId());

View File

@@ -26,8 +26,6 @@ import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.TestDatabaseModule; import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.client.SessionId; import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.api.introduction.IntroductionManager; import org.briarproject.briar.api.introduction.IntroductionManager;
import org.briarproject.briar.api.introduction.IntroductionMessage; import org.briarproject.briar.api.introduction.IntroductionMessage;
@@ -55,6 +53,8 @@ import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.test.TestPluginConfigModule.TRANSPORT_ID; import static org.briarproject.bramble.test.TestPluginConfigModule.TRANSPORT_ID;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.client.MessageQueueManager.QUEUE_STATE_KEY; import static org.briarproject.briar.api.client.MessageQueueManager.QUEUE_STATE_KEY;
import static org.briarproject.briar.api.introduction.IntroductionConstants.ALICE_MAC_KEY_LABEL; import static org.briarproject.briar.api.introduction.IntroductionConstants.ALICE_MAC_KEY_LABEL;
import static org.briarproject.briar.api.introduction.IntroductionConstants.ALICE_NONCE_LABEL; import static org.briarproject.briar.api.introduction.IntroductionConstants.ALICE_NONCE_LABEL;
@@ -485,9 +485,8 @@ public class IntroductionIntegrationTest
new BdfEntry(TYPE, TYPE_REQUEST), new BdfEntry(TYPE, TYPE_REQUEST),
new BdfEntry(SESSION_ID, sessionId), new BdfEntry(SESSION_ID, sessionId),
new BdfEntry(GROUP_ID, group.getId()), new BdfEntry(GROUP_ID, group.getId()),
new BdfEntry(NAME, StringUtils.getRandomString(42)), new BdfEntry(NAME, getRandomString(42)),
new BdfEntry(PUBLIC_KEY, new BdfEntry(PUBLIC_KEY, getRandomBytes(MAX_PUBLIC_KEY_LENGTH))
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH))
); );
// reset request received state // reset request received state

View File

@@ -19,8 +19,6 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.MessageStatus; import org.briarproject.bramble.api.sync.MessageStatus;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.client.MessageTracker; import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.client.SessionId; import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.test.BriarTestCase; import org.briarproject.briar.test.BriarTestCase;
@@ -33,8 +31,11 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID_1; import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID_1;
import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID_2; import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID_2;
import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE; import static org.briarproject.briar.api.introduction.IntroductionConstants.ROLE;
@@ -55,7 +56,7 @@ public class IntroductionManagerImplTest extends BriarTestCase {
private final ClientHelper clientHelper; private final ClientHelper clientHelper;
private final MessageTracker messageTracker; private final MessageTracker messageTracker;
private final IntroductionGroupFactory introductionGroupFactory; private final IntroductionGroupFactory introductionGroupFactory;
private final SessionId sessionId = new SessionId(TestUtils.getRandomId()); private final SessionId sessionId = new SessionId(getRandomId());
private final MessageId storageId = new MessageId(sessionId.getBytes()); private final MessageId storageId = new MessageId(sessionId.getBytes());
private final long time = 42L; private final long time = 42L;
private final Contact introducee1; private final Contact introducee1;
@@ -66,33 +67,29 @@ public class IntroductionManagerImplTest extends BriarTestCase {
private Transaction txn; private Transaction txn;
public IntroductionManagerImplTest() { public IntroductionManagerImplTest() {
AuthorId authorId1 = new AuthorId(TestUtils.getRandomId()); Author author1 = getAuthor();
Author author1 = new Author(authorId1, "Introducee1", AuthorId localAuthorId1 = new AuthorId(getRandomId());
new byte[MAX_PUBLIC_KEY_LENGTH]);
AuthorId localAuthorId1 = new AuthorId(TestUtils.getRandomId());
ContactId contactId1 = new ContactId(234); ContactId contactId1 = new ContactId(234);
introducee1 = introducee1 =
new Contact(contactId1, author1, localAuthorId1, true, true); new Contact(contactId1, author1, localAuthorId1, true, true);
AuthorId authorId2 = new AuthorId(TestUtils.getRandomId()); Author author2 = getAuthor();
Author author2 = new Author(authorId2, "Introducee2", AuthorId localAuthorId2 = new AuthorId(getRandomId());
new byte[MAX_PUBLIC_KEY_LENGTH]);
AuthorId localAuthorId2 = new AuthorId(TestUtils.getRandomId());
ContactId contactId2 = new ContactId(235); ContactId contactId2 = new ContactId(235);
introducee2 = introducee2 =
new Contact(contactId2, author2, localAuthorId2, true, true); new Contact(contactId2, author2, localAuthorId2, true, true);
ClientId clientId = new ClientId(StringUtils.getRandomString(5)); ClientId clientId = new ClientId(getRandomString(5));
introductionGroup1 = new Group(new GroupId(TestUtils.getRandomId()), introductionGroup1 = new Group(new GroupId(getRandomId()),
clientId, new byte[0]); clientId, new byte[0]);
introductionGroup2 = new Group(new GroupId(TestUtils.getRandomId()), introductionGroup2 = new Group(new GroupId(getRandomId()),
clientId, new byte[0]); clientId, new byte[0]);
message1 = new Message( message1 = new Message(
new MessageId(TestUtils.getRandomId()), new MessageId(getRandomId()),
introductionGroup1.getId(), introductionGroup1.getId(),
time, time,
TestUtils.getRandomBytes(MESSAGE_HEADER_LENGTH + 1) getRandomBytes(MESSAGE_HEADER_LENGTH + 1)
); );
// mock ALL THE THINGS!!! // mock ALL THE THINGS!!!

View File

@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry; import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataEncoder; import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.sync.ClientId; import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
@@ -14,20 +15,20 @@ import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.system.SystemClock; import org.briarproject.bramble.system.SystemClock;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.client.SessionId; import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.test.BriarTestCase; import org.briarproject.briar.test.BriarTestCase;
import org.jmock.Mockery; import org.jmock.Mockery;
import org.junit.Test; import org.junit.Test;
import java.io.IOException;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH; import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.introduction.IntroductionConstants.ACCEPT; import static org.briarproject.briar.api.introduction.IntroductionConstants.ACCEPT;
import static org.briarproject.briar.api.introduction.IntroductionConstants.E_PUBLIC_KEY; import static org.briarproject.briar.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID; import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID;
@@ -59,14 +60,14 @@ public class IntroductionValidatorTest extends BriarTestCase {
private final Clock clock = new SystemClock(); private final Clock clock = new SystemClock();
public IntroductionValidatorTest() { public IntroductionValidatorTest() {
GroupId groupId = new GroupId(TestUtils.getRandomId()); GroupId groupId = new GroupId(getRandomId());
ClientId clientId = new ClientId(StringUtils.getRandomString(5)); ClientId clientId = new ClientId(getRandomString(5));
byte[] descriptor = TestUtils.getRandomBytes(12); byte[] descriptor = getRandomBytes(12);
group = new Group(groupId, clientId, descriptor); group = new Group(groupId, clientId, descriptor);
MessageId messageId = new MessageId(TestUtils.getRandomId()); MessageId messageId = new MessageId(getRandomId());
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
byte[] raw = TestUtils.getRandomBytes(123); byte[] raw = getRandomBytes(123);
message = new Message(messageId, group.getId(), timestamp, raw); message = new Message(messageId, group.getId(), timestamp, raw);
@@ -82,20 +83,17 @@ public class IntroductionValidatorTest extends BriarTestCase {
// //
@Test @Test
public void testValidateProperIntroductionRequest() throws IOException { public void testValidateProperIntroductionRequest() throws Exception {
byte[] sessionId = TestUtils.getRandomId(); byte[] sessionId = getRandomId();
String name = StringUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH); String name = getRandomString(MAX_AUTHOR_NAME_LENGTH);
byte[] publicKey = byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH); String text = getRandomString(MAX_INTRODUCTION_MESSAGE_LENGTH);
String text =
StringUtils.getRandomString(MAX_INTRODUCTION_MESSAGE_LENGTH);
BdfList body = BdfList.of(TYPE_REQUEST, sessionId, BdfList body = BdfList.of(TYPE_REQUEST, sessionId,
name, publicKey, text); name, publicKey, text);
BdfDictionary result = BdfDictionary result =
validator.validateMessage(message, group, body) validator.validateMessage(message, group, body).getDictionary();
.getDictionary();
assertEquals(Long.valueOf(TYPE_REQUEST), result.getLong(TYPE)); assertEquals(Long.valueOf(TYPE_REQUEST), result.getLong(TYPE));
assertEquals(sessionId, result.getRaw(SESSION_ID)); assertEquals(sessionId, result.getRaw(SESSION_ID));
@@ -106,7 +104,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testValidateIntroductionRequestWithNoName() throws IOException { public void testValidateIntroductionRequestWithNoName() throws Exception {
BdfDictionary msg = getValidIntroductionRequest(); BdfDictionary msg = getValidIntroductionRequest();
// no NAME is message // no NAME is message
@@ -118,8 +116,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testValidateIntroductionRequestWithLongName() public void testValidateIntroductionRequestWithLongName() throws Exception {
throws IOException {
// too long NAME in message // too long NAME in message
BdfDictionary msg = getValidIntroductionRequest(); BdfDictionary msg = getValidIntroductionRequest();
msg.put(NAME, msg.get(NAME) + "x"); msg.put(NAME, msg.get(NAME) + "x");
@@ -132,7 +129,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testValidateIntroductionRequestWithWrongType() public void testValidateIntroductionRequestWithWrongType()
throws IOException { throws Exception {
// wrong message type // wrong message type
BdfDictionary msg = getValidIntroductionRequest(); BdfDictionary msg = getValidIntroductionRequest();
msg.put(TYPE, 324234); msg.put(TYPE, 324234);
@@ -143,17 +140,16 @@ public class IntroductionValidatorTest extends BriarTestCase {
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
private BdfDictionary getValidIntroductionRequest() throws FormatException { private BdfDictionary getValidIntroductionRequest() throws Exception {
byte[] sessionId = TestUtils.getRandomId(); byte[] sessionId = getRandomId();
String name = StringUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH); Author author = getAuthor();
byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH); String text = getRandomString(MAX_MESSAGE_BODY_LENGTH);
String text = StringUtils.getRandomString(MAX_MESSAGE_BODY_LENGTH);
BdfDictionary msg = new BdfDictionary(); BdfDictionary msg = new BdfDictionary();
msg.put(TYPE, TYPE_REQUEST); msg.put(TYPE, TYPE_REQUEST);
msg.put(SESSION_ID, sessionId); msg.put(SESSION_ID, sessionId);
msg.put(NAME, name); msg.put(NAME, author.getName());
msg.put(PUBLIC_KEY, publicKey); msg.put(PUBLIC_KEY, author.getPublicKey());
msg.put(MSG, text); msg.put(MSG, text);
return msg; return msg;
@@ -164,16 +160,16 @@ public class IntroductionValidatorTest extends BriarTestCase {
// //
@Test @Test
public void testValidateIntroductionAcceptResponse() throws IOException { public void testValidateIntroductionAcceptResponse() throws Exception {
byte[] groupId = TestUtils.getRandomId(); byte[] groupId = getRandomId();
byte[] sessionId = TestUtils.getRandomId(); byte[] sessionId = getRandomId();
long time = clock.currentTimeMillis(); long time = clock.currentTimeMillis();
byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH); byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
String transportId = StringUtils String transportId =
.getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH); getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH);
BdfDictionary tProps = BdfDictionary.of( BdfDictionary tProps = BdfDictionary.of(
new BdfEntry(StringUtils.getRandomString(MAX_PROPERTY_LENGTH), new BdfEntry(getRandomString(MAX_PROPERTY_LENGTH),
StringUtils.getRandomString(MAX_PROPERTY_LENGTH)) getRandomString(MAX_PROPERTY_LENGTH))
); );
BdfDictionary tp = BdfDictionary.of( BdfDictionary tp = BdfDictionary.of(
new BdfEntry(transportId, tProps) new BdfEntry(transportId, tProps)
@@ -204,8 +200,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
} }
@Test @Test
public void testValidateIntroductionDeclineResponse() public void testValidateIntroductionDeclineResponse() throws Exception {
throws IOException {
BdfDictionary msg = getValidIntroductionResponse(false); BdfDictionary msg = getValidIntroductionResponse(false);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID), BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
msg.getBoolean(ACCEPT)); msg.getBoolean(ACCEPT));
@@ -219,7 +214,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testValidateIntroductionResponseWithoutAccept() public void testValidateIntroductionResponseWithoutAccept()
throws IOException { throws Exception {
BdfDictionary msg = getValidIntroductionResponse(false); BdfDictionary msg = getValidIntroductionResponse(false);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID)); BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID));
@@ -228,11 +223,11 @@ public class IntroductionValidatorTest extends BriarTestCase {
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testValidateIntroductionResponseWithBrokenTp() public void testValidateIntroductionResponseWithBrokenTp()
throws IOException { throws Exception {
BdfDictionary msg = getValidIntroductionResponse(true); BdfDictionary msg = getValidIntroductionResponse(true);
BdfDictionary tp = msg.getDictionary(TRANSPORT); BdfDictionary tp = msg.getDictionary(TRANSPORT);
tp.put(StringUtils tp.put(
.getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH), "X"); getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH), "X");
msg.put(TRANSPORT, tp); msg.put(TRANSPORT, tp);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID), BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
@@ -244,7 +239,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testValidateIntroductionResponseWithoutPublicKey() public void testValidateIntroductionResponseWithoutPublicKey()
throws IOException { throws Exception {
BdfDictionary msg = getValidIntroductionResponse(true); BdfDictionary msg = getValidIntroductionResponse(true);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID), BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
@@ -255,17 +250,17 @@ public class IntroductionValidatorTest extends BriarTestCase {
} }
private BdfDictionary getValidIntroductionResponse(boolean accept) private BdfDictionary getValidIntroductionResponse(boolean accept)
throws FormatException { throws Exception {
byte[] groupId = TestUtils.getRandomId(); byte[] groupId = getRandomId();
byte[] sessionId = TestUtils.getRandomId(); byte[] sessionId = getRandomId();
long time = clock.currentTimeMillis(); long time = clock.currentTimeMillis();
byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH); byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
String transportId = StringUtils String transportId =
.getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH); getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH);
BdfDictionary tProps = BdfDictionary.of( BdfDictionary tProps = BdfDictionary.of(
new BdfEntry(StringUtils.getRandomString(MAX_PROPERTY_LENGTH), new BdfEntry(getRandomString(MAX_PROPERTY_LENGTH),
StringUtils.getRandomString(MAX_PROPERTY_LENGTH)) getRandomString(MAX_PROPERTY_LENGTH))
); );
BdfDictionary tp = BdfDictionary.of( BdfDictionary tp = BdfDictionary.of(
new BdfEntry(transportId, tProps) new BdfEntry(transportId, tProps)
@@ -290,10 +285,10 @@ public class IntroductionValidatorTest extends BriarTestCase {
// //
@Test @Test
public void testValidateProperIntroductionAck() throws IOException { public void testValidateProperIntroductionAck() throws Exception {
byte[] sessionId = TestUtils.getRandomId(); byte[] sessionId = getRandomId();
byte[] mac = TestUtils.getRandomBytes(MAC_LENGTH); byte[] mac = getRandomBytes(MAC_LENGTH);
byte[] sig = TestUtils.getRandomBytes(MAX_SIGNATURE_LENGTH); byte[] sig = getRandomBytes(MAX_SIGNATURE_LENGTH);
BdfList body = BdfList.of(TYPE_ACK, sessionId, mac, sig); BdfList body = BdfList.of(TYPE_ACK, sessionId, mac, sig);
BdfDictionary result = BdfDictionary result =
@@ -307,11 +302,11 @@ public class IntroductionValidatorTest extends BriarTestCase {
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testValidateTooLongIntroductionAck() throws IOException { public void testValidateTooLongIntroductionAck() throws Exception {
BdfDictionary msg = BdfDictionary.of( BdfDictionary msg = BdfDictionary.of(
new BdfEntry(TYPE, TYPE_ACK), new BdfEntry(TYPE, TYPE_ACK),
new BdfEntry(SESSION_ID, TestUtils.getRandomId()), new BdfEntry(SESSION_ID, getRandomId()),
new BdfEntry("garbage", StringUtils.getRandomString(255)) new BdfEntry("garbage", getRandomString(255))
); );
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID), BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
msg.getString("garbage")); msg.getString("garbage"));
@@ -321,7 +316,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testValidateIntroductionAckWithLongSessionId() public void testValidateIntroductionAckWithLongSessionId()
throws IOException { throws Exception {
BdfDictionary msg = BdfDictionary.of( BdfDictionary msg = BdfDictionary.of(
new BdfEntry(TYPE, TYPE_ACK), new BdfEntry(TYPE, TYPE_ACK),
new BdfEntry(SESSION_ID, new byte[SessionId.LENGTH + 1]) new BdfEntry(SESSION_ID, new byte[SessionId.LENGTH + 1])
@@ -336,8 +331,8 @@ public class IntroductionValidatorTest extends BriarTestCase {
// //
@Test @Test
public void testValidateProperIntroductionAbort() throws IOException { public void testValidateProperIntroductionAbort() throws Exception {
byte[] sessionId = TestUtils.getRandomId(); byte[] sessionId = getRandomId();
BdfDictionary msg = new BdfDictionary(); BdfDictionary msg = new BdfDictionary();
msg.put(TYPE, TYPE_ABORT); msg.put(TYPE, TYPE_ABORT);
@@ -354,11 +349,11 @@ public class IntroductionValidatorTest extends BriarTestCase {
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testValidateTooLongIntroductionAbort() throws IOException { public void testValidateTooLongIntroductionAbort() throws Exception {
BdfDictionary msg = BdfDictionary.of( BdfDictionary msg = BdfDictionary.of(
new BdfEntry(TYPE, TYPE_ABORT), new BdfEntry(TYPE, TYPE_ABORT),
new BdfEntry(SESSION_ID, TestUtils.getRandomId()), new BdfEntry(SESSION_ID, getRandomId()),
new BdfEntry("garbage", StringUtils.getRandomString(255)) new BdfEntry("garbage", getRandomString(255))
); );
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID), BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
msg.getString("garbage")); msg.getString("garbage"));

View File

@@ -8,9 +8,6 @@ import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.system.SystemModule; import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.forum.ForumConstants;
import org.briarproject.briar.api.forum.ForumPost; import org.briarproject.briar.api.forum.ForumPost;
import org.briarproject.briar.api.forum.ForumPostFactory; import org.briarproject.briar.api.forum.ForumPostFactory;
import org.briarproject.briar.api.messaging.PrivateMessage; import org.briarproject.briar.api.messaging.PrivateMessage;
@@ -22,8 +19,9 @@ import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_RECORD_PAYLOAD_LENGTH; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_RECORD_PAYLOAD_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH; import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH; import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@@ -47,12 +45,11 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
} }
@Test @Test
public void testPrivateMessageFitsIntoPacket() throws Exception { public void testPrivateMessageFitsIntoRecord() throws Exception {
// Create a maximum-length private message // Create a maximum-length private message
GroupId groupId = new GroupId(getRandomId()); GroupId groupId = new GroupId(getRandomId());
long timestamp = Long.MAX_VALUE; long timestamp = Long.MAX_VALUE;
String body = String body = getRandomString(MAX_PRIVATE_MESSAGE_BODY_LENGTH);
StringUtils.fromUtf8(new byte[MAX_PRIVATE_MESSAGE_BODY_LENGTH]);
PrivateMessage message = privateMessageFactory.createPrivateMessage( PrivateMessage message = privateMessageFactory.createPrivateMessage(
groupId, timestamp, body); groupId, timestamp, body);
// Check the size of the serialised message // Check the size of the serialised message
@@ -63,27 +60,25 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
} }
@Test @Test
public void testForumPostFitsIntoPacket() throws Exception { public void testForumPostFitsIntoRecord() throws Exception {
// Create a maximum-length author // Create a maximum-length author
String authorName = StringUtils.getRandomString( int formatVersion = Integer.MAX_VALUE;
MAX_AUTHOR_NAME_LENGTH); String authorName = getRandomString(MAX_AUTHOR_NAME_LENGTH);
byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH]; byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
PrivateKey privateKey = crypto.generateSignatureKeyPair().getPrivate(); PrivateKey privateKey = crypto.generateSignatureKeyPair().getPrivate();
LocalAuthor author = authorFactory LocalAuthor author = authorFactory.createLocalAuthor(formatVersion,
.createLocalAuthor(authorName, authorPublic, authorName, authorPublic, privateKey.getEncoded());
privateKey.getEncoded());
// Create a maximum-length forum post // Create a maximum-length forum post
GroupId groupId = new GroupId(getRandomId()); GroupId groupId = new GroupId(getRandomId());
long timestamp = Long.MAX_VALUE; long timestamp = Long.MAX_VALUE;
MessageId parent = new MessageId(getRandomId()); MessageId parent = new MessageId(getRandomId());
String body = StringUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH); String body = getRandomString(MAX_FORUM_POST_BODY_LENGTH);
ForumPost post = forumPostFactory.createPost(groupId, ForumPost post = forumPostFactory.createPost(groupId,
timestamp, parent, author, body); timestamp, parent, author, body);
// Check the size of the serialised message // Check the size of the serialised message
int length = post.getMessage().getRaw().length; int length = post.getMessage().getRaw().length;
assertTrue(length > UniqueId.LENGTH + 8 + UniqueId.LENGTH assertTrue(length > UniqueId.LENGTH + 8 + UniqueId.LENGTH + 4
+ MAX_AUTHOR_NAME_LENGTH + MAX_PUBLIC_KEY_LENGTH + MAX_AUTHOR_NAME_LENGTH + MAX_PUBLIC_KEY_LENGTH
+ ForumConstants.MAX_CONTENT_TYPE_LENGTH
+ MAX_FORUM_POST_BODY_LENGTH); + MAX_FORUM_POST_BODY_LENGTH);
assertTrue(length <= MAX_RECORD_PAYLOAD_LENGTH); assertTrue(length <= MAX_RECORD_PAYLOAD_LENGTH);
} }

View File

@@ -5,8 +5,6 @@ import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener; import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
@@ -36,10 +34,12 @@ import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH; import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
import static org.briarproject.bramble.test.TestPluginConfigModule.MAX_LATENCY; import static org.briarproject.bramble.test.TestPluginConfigModule.MAX_LATENCY;
import static org.briarproject.bramble.test.TestPluginConfigModule.TRANSPORT_ID; import static org.briarproject.bramble.test.TestPluginConfigModule.TRANSPORT_ID;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
@@ -47,16 +47,13 @@ import static org.junit.Assert.assertTrue;
public class SimplexMessagingIntegrationTest extends BriarTestCase { public class SimplexMessagingIntegrationTest extends BriarTestCase {
private final static String ALICE = "Alice"; private final File testDir = getTestDirectory();
private final static String BOB = "Bob";
private final File testDir = TestUtils.getTestDirectory();
private final File aliceDir = new File(testDir, "alice"); private final File aliceDir = new File(testDir, "alice");
private final File bobDir = new File(testDir, "bob"); private final File bobDir = new File(testDir, "bob");
private final SecretKey master = TestUtils.getSecretKey(); private final SecretKey master = getSecretKey();
private final long timestamp = System.currentTimeMillis(); private final long timestamp = System.currentTimeMillis();
private final AuthorId aliceId = new AuthorId(TestUtils.getRandomId()); private final LocalAuthor aliceAuthor = getLocalAuthor();
private final AuthorId bobId = new AuthorId(TestUtils.getRandomId()); private final LocalAuthor bobAuthor = getLocalAuthor();
private SimplexMessagingIntegrationTestComponent alice, bob; private SimplexMessagingIntegrationTestComponent alice, bob;
@@ -95,12 +92,8 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
lifecycleManager.startServices(null); lifecycleManager.startServices(null);
lifecycleManager.waitForStartup(); lifecycleManager.waitForStartup();
// Add an identity for Alice // Add an identity for Alice
LocalAuthor aliceAuthor = new LocalAuthor(aliceId, "Alice",
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp);
identityManager.registerLocalAuthor(aliceAuthor); identityManager.registerLocalAuthor(aliceAuthor);
// Add Bob as a contact // Add Bob as a contact
Author bobAuthor = new Author(bobId, BOB,
new byte[MAX_PUBLIC_KEY_LENGTH]);
ContactId contactId = contactManager.addContact(bobAuthor, ContactId contactId = contactManager.addContact(bobAuthor,
aliceAuthor.getId(), master, timestamp, true, true, true); aliceAuthor.getId(), master, timestamp, true, true, true);
@@ -146,12 +139,8 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
lifecycleManager.startServices(null); lifecycleManager.startServices(null);
lifecycleManager.waitForStartup(); lifecycleManager.waitForStartup();
// Add an identity for Bob // Add an identity for Bob
LocalAuthor bobAuthor = new LocalAuthor(bobId, BOB,
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp);
identityManager.registerLocalAuthor(bobAuthor); identityManager.registerLocalAuthor(bobAuthor);
// Add Alice as a contact // Add Alice as a contact
Author aliceAuthor = new Author(aliceId, ALICE,
new byte[MAX_PUBLIC_KEY_LENGTH]);
ContactId contactId = contactManager.addContact(aliceAuthor, ContactId contactId = contactManager.addContact(aliceAuthor,
bobAuthor.getId(), master, timestamp, false, true, true); bobAuthor.getId(), master, timestamp, false, true, true);
// Set up an event listener // Set up an event listener

View File

@@ -5,7 +5,6 @@ import org.briarproject.bramble.api.client.BdfMessageContext;
import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.sync.InvalidMessageException; import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.ValidatorTestCase; import org.briarproject.bramble.test.ValidatorTestCase;
@@ -21,9 +20,8 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.briarproject.bramble.util.StringUtils.getRandomString;
@@ -36,9 +34,7 @@ import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH; import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE; import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG; import static org.briarproject.briar.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_ID; import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_NAME;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_PARENT_MSG_ID; import static org.briarproject.briar.privategroup.GroupConstants.KEY_PARENT_MSG_ID;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_PREVIOUS_MSG_ID; import static org.briarproject.briar.privategroup.GroupConstants.KEY_PREVIOUS_MSG_ID;
import static org.briarproject.briar.privategroup.GroupConstants.KEY_READ; import static org.briarproject.briar.privategroup.GroupConstants.KEY_READ;
@@ -56,285 +52,334 @@ public class GroupMessageValidatorTest extends ValidatorTestCase {
private final GroupInvitationFactory groupInvitationFactory = private final GroupInvitationFactory groupInvitationFactory =
context.mock(GroupInvitationFactory.class); context.mock(GroupInvitationFactory.class);
private final String creatorName = getRandomString(MAX_AUTHOR_NAME_LENGTH); private final Author member = getAuthor();
private final String memberName = getRandomString(MAX_AUTHOR_NAME_LENGTH); private final BdfList memberList = BdfList.of(
private final byte[] creatorKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH); member.getFormatVersion(),
private final byte[] memberKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH); member.getName(),
member.getPublicKey()
);
private final byte[] memberSignature = getRandomBytes(MAX_SIGNATURE_LENGTH);
private final Author creator = getAuthor();
private final BdfList creatorList = BdfList.of(
creator.getFormatVersion(),
creator.getName(),
creator.getPublicKey()
);
private final byte[] creatorSignature = private final byte[] creatorSignature =
getRandomBytes(MAX_SIGNATURE_LENGTH); getRandomBytes(MAX_SIGNATURE_LENGTH);
private final byte[] signature = getRandomBytes(MAX_SIGNATURE_LENGTH); private final long inviteTimestamp = message.getTimestamp() - 1;
private final Author member = private final BdfList invite =
new Author(new AuthorId(getRandomId()), memberName, memberKey); BdfList.of(inviteTimestamp, creatorSignature);
private final Author creator =
new Author(new AuthorId(getRandomId()), creatorName, creatorKey);
private final long inviteTimestamp = 42L;
private final PrivateGroup privateGroup = new PrivateGroup(group, private final PrivateGroup privateGroup = new PrivateGroup(group,
getRandomString(MAX_GROUP_NAME_LENGTH), creator, getRandomString(MAX_GROUP_NAME_LENGTH), creator,
getRandomBytes(GROUP_SALT_LENGTH)); getRandomBytes(GROUP_SALT_LENGTH));
private final BdfList token = BdfList.of("token"); private final BdfList token = new BdfList();
private final MessageId parentId = new MessageId(getRandomId()); private final MessageId parentId = new MessageId(getRandomId());
private final MessageId previousMsgId = new MessageId(getRandomId()); private final MessageId previousMsgId = new MessageId(getRandomId());
private final String postContent = private final String content = getRandomString(MAX_GROUP_POST_BODY_LENGTH);
getRandomString(MAX_GROUP_POST_BODY_LENGTH);
private final GroupMessageValidator validator = private final GroupMessageValidator validator =
new GroupMessageValidator(privateGroupFactory, clientHelper, new GroupMessageValidator(privateGroupFactory, clientHelper,
metadataEncoder, clock, authorFactory, metadataEncoder, clock, groupInvitationFactory);
groupInvitationFactory);
// JOIN message // JOIN message
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooShortJoinMessage() throws Exception { public void testRejectsTooShortJoinMessage() throws Exception {
BdfList body = BdfList.of(JOIN.getInt(), creatorName, creatorKey, null); BdfList body = BdfList.of(JOIN.getInt(), memberList, invite);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongJoinMessage() throws Exception { public void testRejectsTooLongJoinMessage() throws Exception {
expectCreateAuthor(creator); expectParseAuthor(memberList, member);
BdfList body = BdfList.of(JOIN.getInt(), creatorName, creatorKey, null, BdfList body = BdfList.of(JOIN.getInt(), memberList, invite,
signature, ""); memberSignature, "");
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsJoinWithTooShortMemberName() throws Exception { public void testRejectsJoinWithNullAuthor() throws Exception {
BdfList body = BdfList.of(JOIN.getInt(), "", memberKey, null, BdfList body = BdfList.of(JOIN.getInt(), null, invite, memberSignature);
signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsJoinMessageWithTooLongMemberName() throws Exception { public void testRejectsJoinWithNonListAuthor() throws Exception {
BdfList body = BdfList.of(JOIN.getInt(), BdfList body = BdfList.of(JOIN.getInt(), 123, invite, memberSignature);
getRandomString(MAX_AUTHOR_NAME_LENGTH + 1), memberKey, null,
signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsJoinMessageWithNullMemberName() throws Exception { public void testRejectsJoinWithInvalidAuthor() throws Exception {
BdfList body = BdfList.of(JOIN.getInt(), null, memberKey, null, expectRejectAuthor(memberList);
signature); BdfList body = BdfList.of(JOIN.getInt(), memberList, invite,
validator.validateMessage(message, group, body); memberSignature);
}
@Test(expected = FormatException.class)
public void testRejectsJoinMessageWithNonStringMemberName() throws Exception {
BdfList body = BdfList.of(JOIN.getInt(), getRandomBytes(5), memberKey,
null, signature);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsJoinWithTooShortMemberKey() throws Exception {
BdfList body = BdfList.of(JOIN.getInt(), memberName, new byte[0], null,
signature);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsJoinWithTooLongMemberKey() throws Exception {
BdfList body = BdfList.of(JOIN.getInt(), memberName,
getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1), null, signature);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsJoinWithNoullMemberKey() throws Exception {
BdfList body = BdfList.of(JOIN.getInt(), memberName, null, null,
signature);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsJoinWithNonRawMemberKey() throws Exception {
BdfList body = BdfList.of(JOIN.getInt(), memberName, "not raw", null,
signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsJoinWithNonListInvitation() throws Exception { public void testRejectsJoinWithNonListInvitation() throws Exception {
expectCreateAuthor(creator); expectParseAuthor(memberList, member);
expectParsePrivateGroup(); BdfList body = BdfList.of(JOIN.getInt(), memberList, "not a list",
BdfList body = BdfList.of(JOIN.getInt(), creatorName, creatorKey, memberSignature);
"not a list", signature); validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsCreatorJoinWithTooShortMemberSignature()
throws Exception {
expectParseAuthor(creatorList, creator);
BdfList body = BdfList.of(JOIN.getInt(), creatorList, invite,
new byte[0]);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsCreatorJoinWithTooLongMemberSignature()
throws Exception {
expectParseAuthor(creatorList, creator);
BdfList body = BdfList.of(JOIN.getInt(), creatorList, invite,
getRandomBytes(MAX_SIGNATURE_LENGTH + 1));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsCreatorJoinWithNullMemberSignature()
throws Exception {
expectParseAuthor(creatorList, creator);
BdfList body = BdfList.of(JOIN.getInt(), creatorList, invite, null);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsCreatorJoinWithNonRawMemberSignature()
throws Exception {
expectParseAuthor(creatorList, creator);
BdfList body = BdfList.of(JOIN.getInt(), creatorList, invite,
"not raw");
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsCreatorJoinWithInvalidMemberSignature()
throws Exception {
expectCreatorJoinMessage(false);
BdfList body = BdfList.of(JOIN.getInt(), creatorList, null,
memberSignature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test @Test
public void testAcceptsCreatorJoin() throws Exception { public void testAcceptsCreatorJoin() throws Exception {
expectJoinMessage(creator, null, true, true); expectCreatorJoinMessage(true);
BdfList body = BdfList.of(JOIN.getInt(), creatorName, creatorKey, BdfList body = BdfList.of(JOIN.getInt(), creatorList, null,
null, signature); memberSignature);
BdfMessageContext messageContext = BdfMessageContext messageContext =
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
assertExpectedMessageContext(messageContext, JOIN, creator, assertExpectedMessageContext(messageContext, JOIN, creatorList,
Collections.emptyList()); Collections.emptyList());
assertTrue(messageContext.getDictionary() assertTrue(messageContext.getDictionary()
.getBoolean(KEY_INITIAL_JOIN_MSG)); .getBoolean(KEY_INITIAL_JOIN_MSG));
} }
@Test(expected = InvalidMessageException.class) @Test(expected = FormatException.class)
public void testRejectsMemberJoinWithNullInvitation() throws Exception { public void testRejectsMemberJoinWithNullInvitation() throws Exception {
expectCreateAuthor(member); expectParseAuthor(memberList, member);
expectParsePrivateGroup(); expectParsePrivateGroup();
BdfList body = BdfList.of(JOIN.getInt(), memberName, memberKey, null, BdfList body = BdfList.of(JOIN.getInt(), memberList, null,
signature); memberSignature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMemberJoinWithTooShortInvitation() throws Exception { public void testRejectsMemberJoinWithTooShortInvitation() throws Exception {
BdfList invite = BdfList.of(inviteTimestamp); BdfList invalidInvite = BdfList.of(inviteTimestamp);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
expectParsePrivateGroup(); expectParsePrivateGroup();
BdfList body = BdfList.of(JOIN.getInt(), memberName, memberKey, invite, BdfList body = BdfList.of(JOIN.getInt(), memberList, invalidInvite,
signature); memberSignature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMemberJoinWithTooLongInvitation() throws Exception { public void testRejectsMemberJoinWithTooLongInvitation() throws Exception {
BdfList invite = BdfList.of(inviteTimestamp, creatorSignature, ""); BdfList invalidInvite =
expectCreateAuthor(member); BdfList.of(inviteTimestamp, creatorSignature, "");
expectParseAuthor(memberList, member);
expectParsePrivateGroup(); expectParsePrivateGroup();
BdfList body = BdfList.of(JOIN.getInt(), memberName, memberKey, invite, BdfList body = BdfList.of(JOIN.getInt(), memberList, invalidInvite,
signature); memberSignature);
validator.validateMessage(message, group, body);
}
@Test(expected = InvalidMessageException.class)
public void testRejectsMemberJoinWithEqualInvitationTime()
throws Exception {
BdfList invite = BdfList.of(message.getTimestamp(), creatorSignature);
expectCreateAuthor(member);
expectParsePrivateGroup();
BdfList body = BdfList.of(JOIN.getInt(), memberName, memberKey, invite,
signature);
validator.validateMessage(message, group, body);
}
@Test(expected = InvalidMessageException.class)
public void testRejectsMemberJoinWithLaterInvitationTime()
throws Exception {
BdfList invite = BdfList.of(message.getTimestamp() + 1,
creatorSignature);
expectCreateAuthor(member);
expectParsePrivateGroup();
BdfList body = BdfList.of(JOIN.getInt(), memberName, memberKey, invite,
signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMemberJoinWithNullInvitationTime() public void testRejectsMemberJoinWithEqualInvitationTime()
throws Exception { throws Exception {
BdfList invite = BdfList.of(null, creatorSignature); BdfList invalidInvite =
expectCreateAuthor(member); BdfList.of(message.getTimestamp(), creatorSignature);
expectParseAuthor(memberList, member);
expectParsePrivateGroup(); expectParsePrivateGroup();
BdfList body = BdfList.of(JOIN.getInt(), memberName, memberKey, invite, BdfList body = BdfList.of(JOIN.getInt(), memberList, invalidInvite,
signature); memberSignature);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsMemberJoinWithLaterInvitationTime()
throws Exception {
BdfList invalidInvite =
BdfList.of(message.getTimestamp() + 1, creatorSignature);
expectParseAuthor(memberList, member);
expectParsePrivateGroup();
BdfList body = BdfList.of(JOIN.getInt(), memberList, invalidInvite,
memberSignature);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsMemberJoinWithNullInvitationTime() throws Exception {
BdfList invalidInvite = BdfList.of(null, creatorSignature);
expectParseAuthor(memberList, member);
expectParsePrivateGroup();
BdfList body = BdfList.of(JOIN.getInt(), memberList, invalidInvite,
memberSignature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMemberJoinWithNonLongInvitationTime() public void testRejectsMemberJoinWithNonLongInvitationTime()
throws Exception { throws Exception {
BdfList invite = BdfList.of("not long", creatorSignature); BdfList invalidInvite = BdfList.of("not long", creatorSignature);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
expectParsePrivateGroup(); expectParsePrivateGroup();
BdfList body = BdfList.of(JOIN.getInt(), memberName, memberKey, invite, BdfList body = BdfList.of(JOIN.getInt(), memberList, invalidInvite,
signature); memberSignature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMemberJoinWithTooShortCreatorSignature() public void testRejectsMemberJoinWithTooShortCreatorSignature()
throws Exception { throws Exception {
BdfList invite = BdfList.of(inviteTimestamp, new byte[0]); BdfList invalidInvite = BdfList.of(inviteTimestamp, new byte[0]);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
expectParsePrivateGroup(); expectParsePrivateGroup();
BdfList body = BdfList.of(JOIN.getInt(), memberName, memberKey, invite, BdfList body = BdfList.of(JOIN.getInt(), memberList, invalidInvite,
signature); memberSignature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsJoinWithTooLongCreatorSignature() public void testRejectsMemberJoinWithTooLongCreatorSignature()
throws Exception { throws Exception {
BdfList invite = BdfList.of(inviteTimestamp, BdfList invalidInvite = BdfList.of(inviteTimestamp,
getRandomBytes(MAX_SIGNATURE_LENGTH + 1)); getRandomBytes(MAX_SIGNATURE_LENGTH + 1));
expectCreateAuthor(member); expectParseAuthor(memberList, member);
expectParsePrivateGroup(); expectParsePrivateGroup();
BdfList body = BdfList.of(JOIN.getInt(), memberName, memberKey, invite, BdfList body = BdfList.of(JOIN.getInt(), memberList, invalidInvite,
signature); memberSignature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMemberJoinWithNullCreatorSignature() public void testRejectsMemberJoinWithNullCreatorSignature()
throws Exception { throws Exception {
BdfList invite = BdfList.of(inviteTimestamp, null); BdfList invalidInvite = BdfList.of(inviteTimestamp, null);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
expectParsePrivateGroup(); expectParsePrivateGroup();
BdfList body = BdfList.of(JOIN.getInt(), memberName, memberKey, invite, BdfList body = BdfList.of(JOIN.getInt(), memberList, invalidInvite,
signature); memberSignature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsMemberJoinWithNonRawCreatorSignature() public void testRejectsMemberJoinWithNonRawCreatorSignature()
throws Exception { throws Exception {
BdfList invite = BdfList.of(inviteTimestamp, "not raw"); BdfList invalidInvite = BdfList.of(inviteTimestamp, "not raw");
expectCreateAuthor(member); expectParseAuthor(memberList, member);
expectParsePrivateGroup(); expectParsePrivateGroup();
BdfList body = BdfList.of(JOIN.getInt(), memberName, memberKey, invite, BdfList body = BdfList.of(JOIN.getInt(), memberList, invalidInvite,
signature); memberSignature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = InvalidMessageException.class) @Test(expected = FormatException.class)
public void testRejectsMemberJoinWithInvalidCreatorSignature() public void testRejectsMemberJoinWithInvalidCreatorSignature()
throws Exception { throws Exception {
BdfList invite = BdfList.of(inviteTimestamp, creatorSignature); expectMemberJoinMessage(false, true);
expectJoinMessage(member, invite, false, true); BdfList body = BdfList.of(JOIN.getInt(), memberList, invite,
BdfList body = BdfList.of(JOIN.getInt(), memberName, memberKey, invite, memberSignature);
signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = InvalidMessageException.class) @Test(expected = FormatException.class)
public void testRejectsMemberJoinWithTooShortMemberSignature()
throws Exception {
expectParseAuthor(memberList, member);
BdfList body = BdfList.of(JOIN.getInt(), memberList, invite,
new byte[0]);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsMemberJoinWithTooLongMemberSignature()
throws Exception {
expectParseAuthor(memberList, member);
BdfList body = BdfList.of(JOIN.getInt(), memberList, invite,
getRandomBytes(MAX_SIGNATURE_LENGTH + 1));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsMemberJoinWithNullMemberSignature()
throws Exception {
expectParseAuthor(memberList, member);
BdfList body = BdfList.of(JOIN.getInt(), memberList, invite, null);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsMemberJoinWithNonRawMemberSignature()
throws Exception {
expectParseAuthor(memberList, member);
BdfList body = BdfList.of(JOIN.getInt(), memberList, invite, "not raw");
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsMemberJoinWithInvalidMemberSignature() public void testRejectsMemberJoinWithInvalidMemberSignature()
throws Exception { throws Exception {
BdfList invite = BdfList.of(inviteTimestamp, creatorSignature); expectMemberJoinMessage(true, false);
expectJoinMessage(member, invite, true, false); BdfList body = BdfList.of(JOIN.getInt(), memberList, invite,
BdfList body = BdfList.of(JOIN.getInt(), memberName, memberKey, invite, memberSignature);
signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test @Test
public void testAcceptsMemberJoin() throws Exception { public void testAcceptsMemberJoin() throws Exception {
BdfList invite = BdfList.of(inviteTimestamp, creatorSignature); expectMemberJoinMessage(true, true);
expectJoinMessage(member, invite, true, true); BdfList body = BdfList.of(JOIN.getInt(), memberList, invite,
BdfList body = BdfList.of(JOIN.getInt(), memberName, memberKey, invite, memberSignature);
signature);
BdfMessageContext messageContext = BdfMessageContext messageContext =
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
assertExpectedMessageContext(messageContext, JOIN, member, assertExpectedMessageContext(messageContext, JOIN, memberList,
Collections.emptyList()); Collections.emptyList());
assertFalse(messageContext.getDictionary() assertFalse(messageContext.getDictionary()
.getBoolean(KEY_INITIAL_JOIN_MSG)); .getBoolean(KEY_INITIAL_JOIN_MSG));
} }
private void expectCreateAuthor(Author member) { private void expectParseAuthor(BdfList authorList, Author author)
throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(authorFactory).createAuthor(member.getName(), oneOf(clientHelper).parseAndValidateAuthor(authorList);
member.getPublicKey()); will(returnValue(author));
will(returnValue(member)); }});
}
private void expectRejectAuthor(BdfList authorList) throws Exception {
context.checking(new Expectations() {{
oneOf(clientHelper).parseAndValidateAuthor(authorList);
will(throwException(new FormatException()));
}}); }});
} }
@@ -345,26 +390,46 @@ public class GroupMessageValidatorTest extends ValidatorTestCase {
}}); }});
} }
private void expectJoinMessage(Author member, BdfList invite, private void expectCreatorJoinMessage(boolean memberSigValid)
boolean creatorSigValid, boolean memberSigValid) throws Exception { throws Exception {
BdfList signed = BdfList.of(group.getId(), message.getTimestamp(), BdfList signed = BdfList.of(
JOIN.getInt(), member.getName(), member.getPublicKey(), invite); group.getId(),
expectCreateAuthor(member); message.getTimestamp(),
creatorList,
null
);
expectParseAuthor(creatorList, creator);
expectParsePrivateGroup(); expectParsePrivateGroup();
context.checking(new Expectations() {{ context.checking(new Expectations() {{
if (invite != null) { oneOf(clientHelper).verifySignature(SIGNING_LABEL_JOIN,
oneOf(groupInvitationFactory).createInviteToken(creator.getId(), memberSignature, creator.getPublicKey(), signed);
member.getId(), privateGroup.getId(), inviteTimestamp); if (!memberSigValid)
will(returnValue(token)); will(throwException(new GeneralSecurityException()));
oneOf(clientHelper).verifySignature(SIGNING_LABEL_INVITE, }});
creatorSignature, creatorKey, token); }
if (!memberSigValid)
will(throwException(new GeneralSecurityException())); private void expectMemberJoinMessage(boolean creatorSigValid,
} boolean memberSigValid) throws Exception {
if (memberSigValid) { BdfList signed = BdfList.of(
group.getId(),
message.getTimestamp(),
memberList,
invite
);
expectParseAuthor(memberList, member);
expectParsePrivateGroup();
context.checking(new Expectations() {{
oneOf(groupInvitationFactory).createInviteToken(creator.getId(),
member.getId(), privateGroup.getId(), inviteTimestamp);
will(returnValue(token));
oneOf(clientHelper).verifySignature(SIGNING_LABEL_INVITE,
creatorSignature, creator.getPublicKey(), token);
if (!creatorSigValid) {
will(throwException(new GeneralSecurityException()));
} else {
oneOf(clientHelper).verifySignature(SIGNING_LABEL_JOIN, oneOf(clientHelper).verifySignature(SIGNING_LABEL_JOIN,
signature, member.getPublicKey(), signed); memberSignature, member.getPublicKey(), signed);
if (!creatorSigValid) if (!memberSigValid)
will(throwException(new GeneralSecurityException())); will(throwException(new GeneralSecurityException()));
} }
}}); }});
@@ -374,219 +439,181 @@ public class GroupMessageValidatorTest extends ValidatorTestCase {
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooShortPost() throws Exception { public void testRejectsTooShortPost() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, previousMsgId, postContent); previousMsgId, content);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongPost() throws Exception { public void testRejectsTooLongPost() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, previousMsgId, postContent, signature, ""); previousMsgId, content, memberSignature, "");
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithTooShortMemberName() throws Exception { public void testRejectsPostWithNullAuthor() throws Exception {
BdfList body = BdfList.of(POST.getInt(), "", memberKey, parentId, BdfList body = BdfList.of(POST.getInt(), null, parentId, previousMsgId,
previousMsgId, postContent, signature); content, memberSignature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithTooLongMemberName() throws Exception { public void testRejectsPostWithNonListAuthor() throws Exception {
BdfList body = BdfList.of(POST.getInt(), BdfList body = BdfList.of(POST.getInt(), 123, parentId, previousMsgId,
getRandomString(MAX_AUTHOR_NAME_LENGTH + 1), memberKey, content, memberSignature);
parentId, previousMsgId, postContent, signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithNullMemberName() throws Exception { public void testRejectsPostWithInvalidAuthor() throws Exception {
BdfList body = BdfList.of(POST.getInt(), null, memberKey, expectRejectAuthor(memberList);
parentId, previousMsgId, postContent, signature); BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
validator.validateMessage(message, group, body); previousMsgId, content, memberSignature);
}
@Test(expected = FormatException.class)
public void testRejectsPostWithNonStringMemberName() throws Exception {
BdfList body = BdfList.of(POST.getInt(), getRandomBytes(5), memberKey,
parentId, previousMsgId, postContent, signature);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsPostWithTooShortMemberKey() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, new byte[0],
parentId, previousMsgId, postContent, signature);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsPostWithTooLongMemberKey() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName,
getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1), parentId,
previousMsgId, postContent, signature);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsPostWithNullMemberKey() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, null,
parentId, previousMsgId, postContent, signature);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsPostWithNonRawMemberKey() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, "not raw",
parentId, previousMsgId, postContent, signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithTooShortParentId() throws Exception { public void testRejectsPostWithTooShortParentId() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList,
getRandomBytes(MessageId.LENGTH - 1), previousMsgId, getRandomBytes(MessageId.LENGTH - 1), previousMsgId, content,
postContent, signature); memberSignature);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithTooLongParentId() throws Exception { public void testRejectsPostWithTooLongParentId() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList,
getRandomBytes(MessageId.LENGTH + 1), previousMsgId, getRandomBytes(MessageId.LENGTH + 1), previousMsgId, content,
postContent, signature); memberSignature);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithNonRawParentId() throws Exception { public void testRejectsPostWithNonRawParentId() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, "not raw",
"not raw", previousMsgId, postContent, signature); previousMsgId, content, memberSignature);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithTooShortPreviousMsgId() throws Exception { public void testRejectsPostWithTooShortPreviousMsgId() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, getRandomBytes(MessageId.LENGTH - 1), postContent, getRandomBytes(MessageId.LENGTH - 1), content, memberSignature);
signature); expectParseAuthor(memberList, member);
expectCreateAuthor(member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithTooLongPreviousMsgId() throws Exception { public void testRejectsPostWithTooLongPreviousMsgId() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, getRandomBytes(MessageId.LENGTH + 1), postContent, getRandomBytes(MessageId.LENGTH + 1), content, memberSignature);
signature); expectParseAuthor(memberList, member);
expectCreateAuthor(member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithNullPreviousMsgId() throws Exception { public void testRejectsPostWithNullPreviousMsgId() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId, null,
parentId, null, postContent, signature); content, memberSignature);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithNonRawPreviousMsgId() throws Exception { public void testRejectsPostWithNonRawPreviousMsgId() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, "not raw", postContent, signature); "not raw", content, memberSignature);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithTooShortContent() throws Exception { public void testRejectsPostWithTooShortContent() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, previousMsgId, "", signature); previousMsgId, "", memberSignature);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithTooLongContent() throws Exception { public void testRejectsPostWithTooLongContent() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, previousMsgId, previousMsgId, getRandomString(MAX_GROUP_POST_BODY_LENGTH + 1),
getRandomString(MAX_GROUP_POST_BODY_LENGTH + 1), signature); memberSignature);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithNullContent() throws Exception { public void testRejectsPostWithNullContent() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, previousMsgId, null, signature); previousMsgId, null, memberSignature);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithNonStringContent() throws Exception { public void testRejectsPostWithNonStringContent() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, previousMsgId, getRandomBytes(5), signature); previousMsgId, getRandomBytes(5), memberSignature);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithTooShortSignature() throws Exception { public void testRejectsPostWithTooShortSignature() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, previousMsgId, postContent, new byte[0]); previousMsgId, content, new byte[0]);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithTooLongSignature() throws Exception { public void testRejectsPostWithTooLongSignature() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, previousMsgId, postContent, previousMsgId, content,
getRandomBytes(MAX_SIGNATURE_LENGTH + 1)); getRandomBytes(MAX_SIGNATURE_LENGTH + 1));
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithNullSignature() throws Exception { public void testRejectsPostWithNullSignature() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, previousMsgId, postContent,null); previousMsgId, content, null);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithNonRawSignature() throws Exception { public void testRejectsPostWithNonRawSignature() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, previousMsgId, postContent, "not raw"); previousMsgId, content, "not raw");
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = InvalidMessageException.class) @Test(expected = FormatException.class)
public void testRejectsPostWithInvalidSignature() throws Exception { public void testRejectsPostWithInvalidSignature() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, previousMsgId, postContent, signature); previousMsgId, content, memberSignature);
expectPostMessage(member, parentId, false); expectPostMessage(parentId, false);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test @Test
public void testAcceptsPost() throws Exception { public void testAcceptsPost() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, BdfList body = BdfList.of(POST.getInt(), memberList, parentId,
parentId, previousMsgId, postContent, signature); previousMsgId, content, memberSignature);
expectPostMessage(member, parentId, true); expectPostMessage(parentId, true);
BdfMessageContext messageContext = BdfMessageContext messageContext =
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
assertExpectedMessageContext(messageContext, POST, member, assertExpectedMessageContext(messageContext, POST, memberList,
Arrays.asList(parentId, previousMsgId)); Arrays.asList(parentId, previousMsgId));
assertArrayEquals(previousMsgId.getBytes(), assertArrayEquals(previousMsgId.getBytes(),
messageContext.getDictionary().getRaw(KEY_PREVIOUS_MSG_ID)); messageContext.getDictionary().getRaw(KEY_PREVIOUS_MSG_ID));
@@ -596,12 +623,12 @@ public class GroupMessageValidatorTest extends ValidatorTestCase {
@Test @Test
public void testAcceptsTopLevelPost() throws Exception { public void testAcceptsTopLevelPost() throws Exception {
BdfList body = BdfList.of(POST.getInt(), memberName, memberKey, null, BdfList body = BdfList.of(POST.getInt(), memberList, null,
previousMsgId, postContent, signature); previousMsgId, content, memberSignature);
expectPostMessage(member, null, true); expectPostMessage(null, true);
BdfMessageContext messageContext = BdfMessageContext messageContext =
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
assertExpectedMessageContext(messageContext, POST, member, assertExpectedMessageContext(messageContext, POST, memberList,
Collections.singletonList(previousMsgId)); Collections.singletonList(previousMsgId));
assertArrayEquals(previousMsgId.getBytes(), assertArrayEquals(previousMsgId.getBytes(),
messageContext.getDictionary().getRaw(KEY_PREVIOUS_MSG_ID)); messageContext.getDictionary().getRaw(KEY_PREVIOUS_MSG_ID));
@@ -609,39 +636,42 @@ public class GroupMessageValidatorTest extends ValidatorTestCase {
messageContext.getDictionary().containsKey(KEY_PARENT_MSG_ID)); messageContext.getDictionary().containsKey(KEY_PARENT_MSG_ID));
} }
private void expectPostMessage(Author member, MessageId parentId, private void expectPostMessage(MessageId parentId, boolean sigValid)
boolean sigValid) throws Exception { throws Exception {
BdfList signed = BdfList.of(group.getId(), message.getTimestamp(), BdfList signed = BdfList.of(
POST.getInt(), member.getName(), member.getPublicKey(), group.getId(),
message.getTimestamp(),
memberList,
parentId == null ? null : parentId.getBytes(), parentId == null ? null : parentId.getBytes(),
previousMsgId.getBytes(), postContent); previousMsgId.getBytes(),
expectCreateAuthor(member); content
);
expectParseAuthor(memberList, member);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST, signature, oneOf(clientHelper).verifySignature(SIGNING_LABEL_POST,
member.getPublicKey(), signed); memberSignature, member.getPublicKey(), signed);
if (!sigValid) will(throwException(new GeneralSecurityException())); if (!sigValid)
will(throwException(new GeneralSecurityException()));
}}); }});
} }
private void assertExpectedMessageContext(BdfMessageContext c, private void assertExpectedMessageContext(BdfMessageContext c,
MessageType type, Author member, MessageType type, BdfList member,
Collection<MessageId> dependencies) throws FormatException { Collection<MessageId> dependencies) throws FormatException {
BdfDictionary d = c.getDictionary(); BdfDictionary d = c.getDictionary();
assertEquals(type.getInt(), d.getLong(KEY_TYPE).intValue()); assertEquals(type.getInt(), d.getLong(KEY_TYPE).intValue());
assertEquals(message.getTimestamp(), assertEquals(message.getTimestamp(),
d.getLong(KEY_TIMESTAMP).longValue()); d.getLong(KEY_TIMESTAMP).longValue());
assertFalse(d.getBoolean(KEY_READ)); assertFalse(d.getBoolean(KEY_READ));
assertEquals(member.getId().getBytes(), d.getRaw(KEY_MEMBER_ID)); assertEquals(member, d.getList(KEY_MEMBER));
assertEquals(member.getName(), d.getString(KEY_MEMBER_NAME));
assertEquals(member.getPublicKey(), d.getRaw(KEY_MEMBER_PUBLIC_KEY));
assertEquals(dependencies, c.getDependencies()); assertEquals(dependencies, c.getDependencies());
} }
@Test(expected = InvalidMessageException.class) @Test(expected = InvalidMessageException.class)
public void testRejectsMessageWithUnknownType() throws Exception { public void testRejectsMessageWithUnknownType() throws Exception {
BdfList body = BdfList.of(POST.getInt() + 1, memberName, memberKey, BdfList body = BdfList.of(POST.getInt() + 1, memberList,
parentId, previousMsgId, postContent, signature); parentId, previousMsgId, content, memberSignature);
expectCreateAuthor(member); expectParseAuthor(memberList, member);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
} }

View File

@@ -23,8 +23,14 @@ import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
import org.briarproject.briar.api.privategroup.PrivateGroupManager; import org.briarproject.briar.api.privategroup.PrivateGroupManager;
import org.jmock.Expectations; import org.jmock.Expectations;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID; import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID; import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_CONTACT_ID;
import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT; import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT;
@@ -59,14 +65,13 @@ public abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
protected final GroupId contactGroupId = new GroupId(getRandomId()); protected final GroupId contactGroupId = new GroupId(getRandomId());
protected final GroupId privateGroupId = new GroupId(getRandomId()); protected final GroupId privateGroupId = new GroupId(getRandomId());
protected final Group privateGroupGroup = protected final Group privateGroupGroup =
new Group(privateGroupId, CLIENT_ID, getRandomBytes(5)); new Group(privateGroupId, CLIENT_ID, getRandomBytes(123));
private final AuthorId authorId = new AuthorId(getRandomId()); protected final Author author = getAuthor();
protected final Author author =
new Author(authorId, "Author", getRandomBytes(12));
protected final PrivateGroup privateGroup = protected final PrivateGroup privateGroup =
new PrivateGroup(privateGroupGroup, "Private Group", author, new PrivateGroup(privateGroupGroup,
getRandomBytes(8)); getRandomString(MAX_GROUP_NAME_LENGTH), author,
protected final byte[] signature = getRandomBytes(42); getRandomBytes(GROUP_SALT_LENGTH));
protected final byte[] signature = getRandomBytes(MAX_SIGNATURE_LENGTH);
protected final MessageId lastLocalMessageId = new MessageId(getRandomId()); protected final MessageId lastLocalMessageId = new MessageId(getRandomId());
protected final MessageId lastRemoteMessageId = protected final MessageId lastRemoteMessageId =
new MessageId(getRandomId()); new MessageId(getRandomId());
@@ -74,20 +79,19 @@ public abstract class AbstractProtocolEngineTest extends BrambleMockTestCase {
protected final long inviteTimestamp = 6L; protected final long inviteTimestamp = 6L;
protected final long messageTimestamp = inviteTimestamp + 1; protected final long messageTimestamp = inviteTimestamp + 1;
protected final MessageId messageId = new MessageId(getRandomId()); protected final MessageId messageId = new MessageId(getRandomId());
protected final Message message = protected final Message message = new Message(messageId, contactGroupId,
new Message(messageId, contactGroupId, messageTimestamp, messageTimestamp, getRandomBytes(42));
getRandomBytes(42));
private final BdfDictionary meta = private final BdfDictionary meta =
BdfDictionary.of(new BdfEntry("me", "ta")); BdfDictionary.of(new BdfEntry("me", "ta"));
protected final ContactId contactId = new ContactId(5); protected final ContactId contactId = new ContactId(5);
protected final Contact contact = protected final Contact contact = new Contact(contactId, author,
new Contact(contactId, author, new AuthorId(getRandomId()), true, new AuthorId(getRandomId()), true, true);
true);
protected final InviteMessage inviteMessage = protected final InviteMessage inviteMessage =
new InviteMessage(new MessageId(getRandomId()), contactGroupId, new InviteMessage(new MessageId(getRandomId()), contactGroupId,
privateGroupId, 0L, privateGroup.getName(), privateGroupId, 0L, privateGroup.getName(),
privateGroup.getCreator(), privateGroup.getSalt(), "msg", privateGroup.getCreator(), privateGroup.getSalt(),
getRandomString(MAX_GROUP_INVITATION_MSG_LENGTH),
signature); signature);
protected final JoinMessage joinMessage = protected final JoinMessage joinMessage =
new JoinMessage(new MessageId(getRandomId()), contactGroupId, new JoinMessage(new MessageId(getRandomId()), contactGroupId,

View File

@@ -4,10 +4,8 @@ import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.UniqueId; import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.client.BdfMessageContext; import org.briarproject.bramble.api.client.BdfMessageContext;
import org.briarproject.bramble.api.data.BdfDictionary; 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.BdfList;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.ValidatorTestCase; import org.briarproject.bramble.test.ValidatorTestCase;
@@ -18,9 +16,8 @@ import org.junit.Test;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.briarproject.bramble.util.StringUtils.getRandomString;
@@ -42,194 +39,149 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase {
private final MessageEncoder messageEncoder = private final MessageEncoder messageEncoder =
context.mock(MessageEncoder.class); context.mock(MessageEncoder.class);
private final Author creator = getAuthor();
private final BdfList creatorList = BdfList.of(
creator.getFormatVersion(),
creator.getName(),
creator.getPublicKey()
);
private final String groupName = getRandomString(MAX_GROUP_NAME_LENGTH); private final String groupName = getRandomString(MAX_GROUP_NAME_LENGTH);
private final String creatorName = getRandomString(MAX_AUTHOR_NAME_LENGTH);
private final byte[] creatorKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
private final Author creator =
new Author(new AuthorId(getRandomId()), creatorName, creatorKey);
private final byte[] salt = getRandomBytes(GROUP_SALT_LENGTH); private final byte[] salt = getRandomBytes(GROUP_SALT_LENGTH);
private final PrivateGroup privateGroup = private final String content =
new PrivateGroup(group, groupName, creator, salt);
private final String inviteText =
getRandomString(MAX_GROUP_INVITATION_MSG_LENGTH); getRandomString(MAX_GROUP_INVITATION_MSG_LENGTH);
private final byte[] signature = getRandomBytes(MAX_SIGNATURE_LENGTH); private final byte[] signature = getRandomBytes(MAX_SIGNATURE_LENGTH);
private final BdfDictionary meta = private final PrivateGroup privateGroup =
BdfDictionary.of(new BdfEntry("meta", "data")); new PrivateGroup(group, groupName, creator, salt);
private final BdfDictionary meta = new BdfDictionary();
private final MessageId previousMessageId = new MessageId(getRandomId()); private final MessageId previousMessageId = new MessageId(getRandomId());
private final GroupInvitationValidator validator = private final GroupInvitationValidator validator =
new GroupInvitationValidator(clientHelper, metadataEncoder, new GroupInvitationValidator(clientHelper, metadataEncoder,
clock, authorFactory, privateGroupFactory, messageEncoder); clock, privateGroupFactory, messageEncoder);
// INVITE Message // INVITE Message
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooShortInviteMessage() throws Exception { public void testRejectsTooShortInviteMessage() throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
creatorKey, salt, inviteText); salt, content);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongInviteMessage() throws Exception { public void testRejectsTooLongInviteMessage() throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
creatorKey, salt, inviteText, signature, ""); salt, content, signature, "");
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithTooShortGroupName() public void testRejectsInviteMessageWithTooShortGroupName()
throws Exception { throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), "", creatorName, BdfList body = BdfList.of(INVITE.getValue(), creatorList, "", salt,
creatorKey, salt, inviteText, signature); content, signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithTooLongGroupName() public void testRejectsInviteMessageWithTooLongGroupName()
throws Exception { throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), String tooLongName = getRandomString(MAX_GROUP_NAME_LENGTH + 1);
getRandomString(MAX_GROUP_NAME_LENGTH + 1), creatorName, BdfList body = BdfList.of(INVITE.getValue(), creatorList, tooLongName,
creatorKey, salt, inviteText, signature); salt, content, signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithNullGroupName() public void testRejectsInviteMessageWithNullGroupName() throws Exception {
throws Exception { BdfList body = BdfList.of(INVITE.getValue(), creatorList, null, salt,
BdfList body = BdfList.of(INVITE.getValue(), null, creatorName, content, signature);
creatorKey, salt, inviteText, signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithNonStringGroupName() public void testRejectsInviteMessageWithNonStringGroupName()
throws Exception { throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), getRandomBytes(5), BdfList body = BdfList.of(INVITE.getValue(), creatorList,
creatorName, creatorKey, salt, inviteText, signature); getRandomBytes(5), salt, content, signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithTooShortCreatorName() public void testRejectsInviteMessageWithNullCreator() throws Exception {
throws Exception { BdfList body = BdfList.of(INVITE.getValue(), null, groupName, salt,
BdfList body = BdfList.of(INVITE.getValue(), groupName, "", creatorKey, content, signature);
salt, inviteText, signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithTooLongCreatorName() public void testRejectsInviteMessageWithNonListCreator() throws Exception {
throws Exception { BdfList body = BdfList.of(INVITE.getValue(), 123, groupName, salt,
BdfList body = BdfList.of(INVITE.getValue(), groupName, content, signature);
getRandomString(MAX_AUTHOR_NAME_LENGTH + 1), creatorKey, salt,
inviteText, signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithNullCreatorName() public void testRejectsInviteMessageWithInvalidCreator() throws Exception {
throws Exception { context.checking(new Expectations() {{
BdfList body = BdfList.of(INVITE.getValue(), groupName, null, oneOf(clientHelper).parseAndValidateAuthor(creatorList);
creatorKey, salt, inviteText, signature); will(throwException(new FormatException()));
validator.validateMessage(message, group, body); }});
}
@Test(expected = FormatException.class) BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
public void testRejectsInviteMessageWithNonStringCreatorName() salt, content, signature);
throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName,
getRandomBytes(5), creatorKey, salt, inviteText, signature);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsInviteMessageWithTooShortCreatorKey()
throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName,
new byte[0], salt, inviteText, signature);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsInviteMessageWithTooLongCreatorKey()
throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName,
getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1), salt, inviteText,
signature);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsInviteMessageWithNullCreatorKey()
throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName,
null, salt, inviteText, signature);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsInviteMessageWithNonRawCreatorKey()
throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName,
"not raw", salt, inviteText, signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithTooShortGroupSalt() public void testRejectsInviteMessageWithTooShortGroupSalt()
throws Exception { throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
creatorKey, getRandomBytes(GROUP_SALT_LENGTH - 1), inviteText, getRandomBytes(GROUP_SALT_LENGTH - 1), content, signature);
signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithTooLongGroupSalt() public void testRejectsInviteMessageWithTooLongGroupSalt()
throws Exception { throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
creatorKey, getRandomBytes(GROUP_SALT_LENGTH + 1), inviteText, getRandomBytes(GROUP_SALT_LENGTH + 1), content, signature);
signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithNullGroupSalt() public void testRejectsInviteMessageWithNullGroupSalt() throws Exception {
throws Exception { BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, null, content, signature);
creatorKey, null, inviteText, signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithNonRawGroupSalt() public void testRejectsInviteMessageWithNonRawGroupSalt() throws Exception {
throws Exception { BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, "not raw", content, signature);
creatorKey, "not raw", inviteText, signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithTooShortContent() throws Exception { public void testRejectsInviteMessageWithTooShortContent() throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
creatorKey, salt, "", signature); salt, "", signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithTooLongContent() throws Exception { public void testRejectsInviteMessageWithTooLongContent() throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
creatorKey, salt, salt, getRandomString(MAX_GROUP_INVITATION_MSG_LENGTH + 1),
getRandomString(MAX_GROUP_INVITATION_MSG_LENGTH + 1),
signature); signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test @Test
public void testAcceptsInviteMessageWithNullContent() throws Exception { public void testAcceptsInviteMessageWithNullContent() throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
creatorKey, salt, null, signature); salt, null, signature);
expectInviteMessage(false); expectInviteMessage(false);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@@ -237,57 +189,54 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase {
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithNonStringContent() public void testRejectsInviteMessageWithNonStringContent()
throws Exception { throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
creatorKey, salt, getRandomBytes(5), signature); salt, getRandomBytes(5), signature);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithTooShortSignature() public void testRejectsInviteMessageWithTooShortSignature()
throws Exception { throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
creatorKey, salt, inviteText, new byte[0]); salt, content, new byte[0]);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithTooLongSignature() public void testRejectsInviteMessageWithTooLongSignature()
throws Exception { throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
creatorKey, salt, inviteText, salt, content, getRandomBytes(MAX_SIGNATURE_LENGTH + 1));
getRandomBytes(MAX_SIGNATURE_LENGTH + 1));
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithNullSignature() public void testRejectsInviteMessageWithNullSignature() throws Exception {
throws Exception { BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, salt, content, null);
creatorKey, salt, inviteText, null);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithNonRawSignature() public void testRejectsInviteMessageWithNonRawSignature() throws Exception {
throws Exception { BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, salt, content, "not raw");
creatorKey, salt, inviteText, "not raw");
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInviteMessageWithInvalidSignature() public void testRejectsInviteMessageWithInvalidSignature()
throws Exception { throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
creatorKey, salt, null, signature); salt, content, signature);
expectInviteMessage(true); expectInviteMessage(true);
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
} }
@Test @Test
public void testAcceptsValidInviteMessage() throws Exception { public void testAcceptsValidInviteMessage() throws Exception {
BdfList body = BdfList.of(INVITE.getValue(), groupName, creatorName, BdfList body = BdfList.of(INVITE.getValue(), creatorList, groupName,
creatorKey, salt, inviteText, signature); salt, content, signature);
expectInviteMessage(false); expectInviteMessage(false);
BdfMessageContext messageContext = BdfMessageContext messageContext =
validator.validateMessage(message, group, body); validator.validateMessage(message, group, body);
@@ -296,16 +245,19 @@ public class GroupInvitationValidatorTest extends ValidatorTestCase {
} }
private void expectInviteMessage(boolean exception) throws Exception { private void expectInviteMessage(boolean exception) throws Exception {
BdfList signed = BdfList.of(message.getTimestamp(), BdfList signed = BdfList.of(
message.getGroupId(), privateGroup.getId()); message.getTimestamp(),
message.getGroupId(),
privateGroup.getId()
);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(authorFactory).createAuthor(creatorName, creatorKey); oneOf(clientHelper).parseAndValidateAuthor(creatorList);
will(returnValue(creator)); will(returnValue(creator));
oneOf(privateGroupFactory).createPrivateGroup(groupName, creator, oneOf(privateGroupFactory).createPrivateGroup(groupName, creator,
salt); salt);
will(returnValue(privateGroup)); will(returnValue(privateGroup));
oneOf(clientHelper).verifySignature(SIGNING_LABEL_INVITE, signature, oneOf(clientHelper).verifySignature(SIGNING_LABEL_INVITE, signature,
creatorKey, signed); creator.getPublicKey(), signed);
if (exception) { if (exception) {
will(throwException(new GeneralSecurityException())); will(throwException(new GeneralSecurityException()));
} else { } else {

View File

@@ -4,7 +4,6 @@ import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry; import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.briar.api.client.ProtocolStateException; import org.briarproject.briar.api.client.ProtocolStateException;
@@ -18,8 +17,11 @@ import java.util.Map;
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
import static org.briarproject.briar.privategroup.invitation.InviteeState.ACCEPTED; import static org.briarproject.briar.privategroup.invitation.InviteeState.ACCEPTED;
import static org.briarproject.briar.privategroup.invitation.InviteeState.DISSOLVED; import static org.briarproject.briar.privategroup.invitation.InviteeState.DISSOLVED;
import static org.briarproject.briar.privategroup.invitation.InviteeState.ERROR; import static org.briarproject.briar.privategroup.invitation.InviteeState.ERROR;
@@ -39,9 +41,7 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest {
new InviteeProtocolEngine(db, clientHelper, privateGroupManager, new InviteeProtocolEngine(db, clientHelper, privateGroupManager,
privateGroupFactory, groupMessageFactory, identityManager, privateGroupFactory, groupMessageFactory, identityManager,
messageParser, messageEncoder, messageTracker, clock); messageParser, messageEncoder, messageTracker, clock);
private final LocalAuthor localAuthor = private final LocalAuthor localAuthor = getLocalAuthor();
new LocalAuthor(new AuthorId(getRandomId()), "Local Author",
getRandomBytes(12), getRandomBytes(12), 42L);
private InviteeSession getDefaultSession(InviteeState state) { private InviteeSession getDefaultSession(InviteeState state) {
return new InviteeSession(contactGroupId, privateGroupId, return new InviteeSession(contactGroupId, privateGroupId,
@@ -323,13 +323,12 @@ public class InviteeProtocolEngineTest extends AbstractProtocolEngineTest {
new InviteMessage(new MessageId(getRandomId()), contactGroupId, new InviteMessage(new MessageId(getRandomId()), contactGroupId,
privateGroupId, session.getInviteTimestamp() + 1, privateGroupId, session.getInviteTimestamp() + 1,
privateGroup.getName(), privateGroup.getCreator(), privateGroup.getName(), privateGroup.getCreator(),
privateGroup.getSalt(), "msg", signature); privateGroup.getSalt(),
Author notCreator = getRandomString(MAX_GROUP_INVITATION_MSG_LENGTH),
new Author(new AuthorId(getRandomId()), "Not Creator", signature);
getRandomBytes(5)); Author notCreator = getAuthor();
Contact notCreatorContact = Contact notCreatorContact = new Contact(contactId, notCreator,
new Contact(contactId, notCreator, localAuthor.getId(), true, localAuthor.getId(), true, true);
true);
expectGetContactId(); expectGetContactId();
context.checking(new Expectations() {{ context.checking(new Expectations() {{

View File

@@ -83,12 +83,10 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
MessageParser<Blog> messageParser = context.mock(MessageParser.class); MessageParser<Blog> messageParser = context.mock(MessageParser.class);
InvitationFactory<Blog, BlogInvitationResponse> invitationFactory = InvitationFactory<Blog, BlogInvitationResponse> invitationFactory =
context.mock(InvitationFactory.class); context.mock(InvitationFactory.class);
blogSharingManager = blogSharingManager = new BlogSharingManagerImpl(db, clientHelper,
new BlogSharingManagerImpl(db, clientHelper, metadataParser, metadataParser, messageParser, sessionEncoder, sessionParser,
messageParser, sessionEncoder, sessionParser, messageTracker, contactGroupFactory, engine, invitationFactory,
messageTracker, contactGroupFactory, identityManager, blogManager);
engine, invitationFactory, identityManager,
blogManager);
} }
@Test @Test
@@ -228,13 +226,11 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
private void expectPreShareShareable(Transaction txn, Contact contact, private void expectPreShareShareable(Transaction txn, Contact contact,
Blog blog, Map<MessageId, BdfDictionary> sessions) Blog blog, Map<MessageId, BdfDictionary> sessions)
throws Exception { throws Exception {
Group contactGroup = Group contactGroup = new Group(new GroupId(getRandomId()), CLIENT_ID,
new Group(new GroupId(getRandomId()), CLIENT_ID, getRandomBytes(42));
getRandomBytes(42));
BdfDictionary sessionDict = new BdfDictionary(); BdfDictionary sessionDict = new BdfDictionary();
Message message = Message message = new Message(new MessageId(getRandomId()),
new Message(new MessageId(getRandomId()), contactGroup.getId(), contactGroup.getId(), 42L, getRandomBytes(1337));
42L, getRandomBytes(1337));
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
CLIENT_VERSION, contact); CLIENT_VERSION, contact);
@@ -242,9 +238,8 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
oneOf(sessionParser) oneOf(sessionParser)
.getSessionQuery(new SessionId(blog.getId().getBytes())); .getSessionQuery(new SessionId(blog.getId().getBytes()));
will(returnValue(sessionDict)); will(returnValue(sessionDict));
oneOf(clientHelper) oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
.getMessageMetadataAsDictionary(txn, contactGroup.getId(), contactGroup.getId(), sessionDict);
sessionDict);
will(returnValue(sessions)); will(returnValue(sessions));
if (sessions.size() == 0) { if (sessions.size() == 0) {
oneOf(db).addGroup(txn, blog.getGroup()); oneOf(db).addGroup(txn, blog.getGroup());
@@ -277,9 +272,8 @@ public class BlogSharingManagerImplTest extends BrambleMockTestCase {
oneOf(sessionParser) oneOf(sessionParser)
.getSessionQuery(new SessionId(blog.getId().getBytes())); .getSessionQuery(new SessionId(blog.getId().getBytes()));
will(returnValue(sessionDict)); will(returnValue(sessionDict));
oneOf(clientHelper) oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
.getMessageMetadataAsDictionary(txn, contactGroup.getId(), contactGroup.getId(), sessionDict);
sessionDict);
will(returnValue(sessions)); will(returnValue(sessions));
if (sessions.size() == 1) { if (sessions.size() == 1) {
oneOf(sessionParser) oneOf(sessionParser)

View File

@@ -4,184 +4,130 @@ import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.BdfMessageContext; import org.briarproject.bramble.api.client.BdfMessageContext;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.blog.Blog; import org.briarproject.briar.api.blog.Blog;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.junit.Test; import org.junit.Test;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.test.TestUtils.getAuthor;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_NAME_LENGTH;
import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH; import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH;
import static org.briarproject.briar.sharing.MessageType.INVITE; import static org.briarproject.briar.sharing.MessageType.INVITE;
public class BlogSharingValidatorTest extends SharingValidatorTest { public class BlogSharingValidatorTest extends SharingValidatorTest {
private final AuthorId authorId = new AuthorId(getRandomId()); private final Author author = getAuthor();
private final String authorName = StringUtils.getRandomString(42);
private final byte[] publicKey =
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
private final Author author = new Author(authorId, authorName, publicKey);
private final Blog blog = new Blog(group, author, false); private final Blog blog = new Blog(group, author, false);
private final BdfList descriptor = BdfList.of(authorName, publicKey, false); private final BdfList authorList = BdfList.of(author.getFormatVersion(),
author.getName(), author.getPublicKey());
private final BdfList descriptor = BdfList.of(authorList, false);
private final String content = private final String content =
StringUtils.getRandomString(MAX_INVITATION_MESSAGE_LENGTH); getRandomString(MAX_INVITATION_MESSAGE_LENGTH);
@Override @Override
SharingValidator getValidator() { SharingValidator getValidator() {
return new BlogSharingValidator(messageEncoder, clientHelper, return new BlogSharingValidator(messageEncoder, clientHelper,
metadataEncoder, clock, blogFactory, authorFactory); metadataEncoder, clock, blogFactory);
} }
@Test @Test
public void testAcceptsInvitationWithContent() throws Exception { public void testAcceptsInvitationWithContent() throws Exception {
expectCreateBlog(authorName, publicKey); expectCreateBlog();
expectEncodeMetadata(INVITE); expectEncodeMetadata(INVITE);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext context = validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, descriptor, BdfList.of(INVITE.getValue(), previousMsgId, descriptor,
content)); content));
assertExpectedContext(messageContext, previousMsgId); assertExpectedContext(context, previousMsgId);
} }
@Test @Test
public void testAcceptsInvitationWithNullContent() throws Exception { public void testAcceptsInvitationWithNullContent() throws Exception {
expectCreateBlog(authorName, publicKey); expectCreateBlog();
expectEncodeMetadata(INVITE); expectEncodeMetadata(INVITE);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext context = validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, descriptor, null)); BdfList.of(INVITE.getValue(), previousMsgId, descriptor, null));
assertExpectedContext(messageContext, previousMsgId); assertExpectedContext(context, previousMsgId);
} }
@Test @Test
public void testAcceptsInvitationWithNullPreviousMsgId() throws Exception { public void testAcceptsInvitationWithNullPreviousMsgId() throws Exception {
expectCreateBlog(authorName, publicKey); expectCreateBlog();
expectEncodeMetadata(INVITE); expectEncodeMetadata(INVITE);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext context = validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), null, descriptor, null)); BdfList.of(INVITE.getValue(), null, descriptor, content));
assertExpectedContext(messageContext, null); assertExpectedContext(context, null);
}
@Test(expected = FormatException.class)
public void testRejectsNullBlogName() throws Exception {
BdfList invalidDescriptor = BdfList.of(null, publicKey, false);
v.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null));
}
@Test(expected = FormatException.class)
public void testRejectsNonStringBlogName() throws Exception {
BdfList invalidDescriptor = BdfList.of(123, publicKey, false);
v.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null));
}
@Test(expected = FormatException.class)
public void testRejectsTooShortBlogName() throws Exception {
BdfList invalidDescriptor = BdfList.of("", publicKey, false);
v.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null));
} }
@Test @Test
public void testAcceptsMinLengthBlogName() throws Exception { public void testAcceptsInvitationForRssBlog() throws Exception {
String shortBlogName = StringUtils.getRandomString(1); expectCreateRssBlog();
BdfList validDescriptor = BdfList.of(shortBlogName, publicKey, false);
expectCreateBlog(shortBlogName, publicKey);
expectEncodeMetadata(INVITE); expectEncodeMetadata(INVITE);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfList rssDescriptor = BdfList.of(authorList, true);
BdfList.of(INVITE.getValue(), previousMsgId, validDescriptor, BdfMessageContext context = validator.validateMessage(message, group,
null)); BdfList.of(INVITE.getValue(), previousMsgId, rssDescriptor,
assertExpectedContext(messageContext, previousMsgId); content));
assertExpectedContext(context, previousMsgId);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongBlogName() throws Exception { public void testRejectsNullAuthor() throws Exception {
String invalidBlogName = BdfList invalidDescriptor = BdfList.of(null, false);
StringUtils.getRandomString(MAX_BLOG_NAME_LENGTH + 1); validator.validateMessage(message, group,
BdfList invalidDescriptor =
BdfList.of(invalidBlogName, publicKey, false);
v.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor, BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null)); null));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNullPublicKey() throws Exception { public void testRejectsNonListAuthor() throws Exception {
BdfList invalidDescriptor = BdfList.of(authorName, null, false); BdfList invalidDescriptor = BdfList.of(123, false);
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor, BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null)); null));
} }
@Test(expected = FormatException.class)
public void testRejectsNonRawPublicKey() throws Exception {
BdfList invalidDescriptor = BdfList.of(authorName, 123, false);
v.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null));
}
@Test(expected = FormatException.class)
public void testRejectsTooLongPublicKey() throws Exception {
byte[] invalidKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH + 1);
BdfList invalidDescriptor = BdfList.of(authorName, invalidKey, false);
v.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null));
}
@Test
public void testAcceptsMinLengthPublicKey() throws Exception {
byte[] key = TestUtils.getRandomBytes(1);
BdfList validDescriptor = BdfList.of(authorName, key, false);
expectCreateBlog(authorName, key);
expectEncodeMetadata(INVITE);
BdfMessageContext messageContext = v.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, validDescriptor,
null));
assertExpectedContext(messageContext, previousMsgId);
}
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNonStringContent() throws Exception { public void testRejectsNonStringContent() throws Exception {
expectCreateBlog(authorName, publicKey); expectCreateBlog();
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, descriptor, BdfList.of(INVITE.getValue(), previousMsgId, descriptor,
123)); 123));
} }
@Test @Test
public void testAcceptsMinLengthContent() throws Exception { public void testAcceptsMinLengthContent() throws Exception {
expectCreateBlog(authorName, publicKey); String shortContent = getRandomString(1);
expectCreateBlog();
expectEncodeMetadata(INVITE); expectEncodeMetadata(INVITE);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext context = validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, descriptor, "1")); BdfList.of(INVITE.getValue(), previousMsgId, descriptor,
assertExpectedContext(messageContext, previousMsgId); shortContent));
assertExpectedContext(context, previousMsgId);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongContent() throws Exception { public void testRejectsTooLongContent() throws Exception {
String invalidContent = String invalidContent =
StringUtils.getRandomString(MAX_INVITATION_MESSAGE_LENGTH + 1); getRandomString(MAX_INVITATION_MESSAGE_LENGTH + 1);
expectCreateBlog(authorName, publicKey); expectCreateBlog();
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, descriptor, BdfList.of(INVITE.getValue(), previousMsgId, descriptor,
invalidContent)); invalidContent));
} }
private void expectCreateBlog(String name, byte[] key) { private void expectCreateBlog() throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(authorFactory).createAuthor(name, key); oneOf(clientHelper).parseAndValidateAuthor(authorList);
will(returnValue(author)); will(returnValue(author));
oneOf(blogFactory).createBlog(author); oneOf(blogFactory).createBlog(author);
will(returnValue(blog)); will(returnValue(blog));
}}); }});
} }
private void expectCreateRssBlog() throws Exception {
context.checking(new Expectations() {{
oneOf(clientHelper).parseAndValidateAuthor(authorList);
will(returnValue(author));
oneOf(blogFactory).createFeedBlog(author);
will(returnValue(blog));
}});
}
} }

View File

@@ -3,12 +3,12 @@ package org.briarproject.briar.sharing;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.BdfMessageContext; import org.briarproject.bramble.api.client.BdfMessageContext;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.forum.Forum; import org.briarproject.briar.api.forum.Forum;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.junit.Test; import org.junit.Test;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.briar.api.forum.ForumConstants.FORUM_SALT_LENGTH; import static org.briarproject.briar.api.forum.ForumConstants.FORUM_SALT_LENGTH;
import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH; import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH; import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH;
@@ -16,13 +16,12 @@ import static org.briarproject.briar.sharing.MessageType.INVITE;
public class ForumSharingValidatorTest extends SharingValidatorTest { public class ForumSharingValidatorTest extends SharingValidatorTest {
private final String forumName = private final String forumName = getRandomString(MAX_FORUM_NAME_LENGTH);
StringUtils.getRandomString(MAX_FORUM_NAME_LENGTH); private final byte[] salt = getRandomBytes(FORUM_SALT_LENGTH);
private final byte[] salt = TestUtils.getRandomBytes(FORUM_SALT_LENGTH);
private final Forum forum = new Forum(group, forumName, salt); private final Forum forum = new Forum(group, forumName, salt);
private final BdfList descriptor = BdfList.of(forumName, salt); private final BdfList descriptor = BdfList.of(forumName, salt);
private final String content = private final String content =
StringUtils.getRandomString(MAX_INVITATION_MESSAGE_LENGTH); getRandomString(MAX_INVITATION_MESSAGE_LENGTH);
@Override @Override
SharingValidator getValidator() { SharingValidator getValidator() {
@@ -34,34 +33,34 @@ public class ForumSharingValidatorTest extends SharingValidatorTest {
public void testAcceptsInvitationWithContent() throws Exception { public void testAcceptsInvitationWithContent() throws Exception {
expectCreateForum(forumName); expectCreateForum(forumName);
expectEncodeMetadata(INVITE); expectEncodeMetadata(INVITE);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext context = validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, descriptor, BdfList.of(INVITE.getValue(), previousMsgId, descriptor,
content)); content));
assertExpectedContext(messageContext, previousMsgId); assertExpectedContext(context, previousMsgId);
} }
@Test @Test
public void testAcceptsInvitationWithNullContent() throws Exception { public void testAcceptsInvitationWithNullContent() throws Exception {
expectCreateForum(forumName); expectCreateForum(forumName);
expectEncodeMetadata(INVITE); expectEncodeMetadata(INVITE);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext context = validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, descriptor, null)); BdfList.of(INVITE.getValue(), previousMsgId, descriptor, null));
assertExpectedContext(messageContext, previousMsgId); assertExpectedContext(context, previousMsgId);
} }
@Test @Test
public void testAcceptsInvitationWithNullPreviousMsgId() throws Exception { public void testAcceptsInvitationWithNullPreviousMsgId() throws Exception {
expectCreateForum(forumName); expectCreateForum(forumName);
expectEncodeMetadata(INVITE); expectEncodeMetadata(INVITE);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext context = validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), null, descriptor, null)); BdfList.of(INVITE.getValue(), null, descriptor, null));
assertExpectedContext(messageContext, null); assertExpectedContext(context, null);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNullForumName() throws Exception { public void testRejectsNullForumName() throws Exception {
BdfList invalidDescriptor = BdfList.of(null, salt); BdfList invalidDescriptor = BdfList.of(null, salt);
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor, BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null)); null));
} }
@@ -69,7 +68,7 @@ public class ForumSharingValidatorTest extends SharingValidatorTest {
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNonStringForumName() throws Exception { public void testRejectsNonStringForumName() throws Exception {
BdfList invalidDescriptor = BdfList.of(123, salt); BdfList invalidDescriptor = BdfList.of(123, salt);
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor, BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null)); null));
} }
@@ -77,29 +76,28 @@ public class ForumSharingValidatorTest extends SharingValidatorTest {
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooShortForumName() throws Exception { public void testRejectsTooShortForumName() throws Exception {
BdfList invalidDescriptor = BdfList.of("", salt); BdfList invalidDescriptor = BdfList.of("", salt);
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor, BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null)); null));
} }
@Test @Test
public void testAcceptsMinLengthForumName() throws Exception { public void testAcceptsMinLengthForumName() throws Exception {
String shortForumName = StringUtils.getRandomString(1); String shortForumName = getRandomString(1);
BdfList validDescriptor = BdfList.of(shortForumName, salt); BdfList validDescriptor = BdfList.of(shortForumName, salt);
expectCreateForum(shortForumName); expectCreateForum(shortForumName);
expectEncodeMetadata(INVITE); expectEncodeMetadata(INVITE);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext context = validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, validDescriptor, BdfList.of(INVITE.getValue(), previousMsgId, validDescriptor,
null)); null));
assertExpectedContext(messageContext, previousMsgId); assertExpectedContext(context, previousMsgId);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongForumName() throws Exception { public void testRejectsTooLongForumName() throws Exception {
String invalidForumName = String invalidForumName = getRandomString(MAX_FORUM_NAME_LENGTH + 1);
StringUtils.getRandomString(MAX_FORUM_NAME_LENGTH + 1);
BdfList invalidDescriptor = BdfList.of(invalidForumName, salt); BdfList invalidDescriptor = BdfList.of(invalidForumName, salt);
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor, BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null)); null));
} }
@@ -107,7 +105,7 @@ public class ForumSharingValidatorTest extends SharingValidatorTest {
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNullSalt() throws Exception { public void testRejectsNullSalt() throws Exception {
BdfList invalidDescriptor = BdfList.of(forumName, null); BdfList invalidDescriptor = BdfList.of(forumName, null);
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor, BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null)); null));
} }
@@ -115,25 +113,25 @@ public class ForumSharingValidatorTest extends SharingValidatorTest {
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNonRawSalt() throws Exception { public void testRejectsNonRawSalt() throws Exception {
BdfList invalidDescriptor = BdfList.of(forumName, 123); BdfList invalidDescriptor = BdfList.of(forumName, 123);
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor, BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null)); null));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooShortSalt() throws Exception { public void testRejectsTooShortSalt() throws Exception {
byte[] invalidSalt = TestUtils.getRandomBytes(FORUM_SALT_LENGTH - 1); byte[] invalidSalt = getRandomBytes(FORUM_SALT_LENGTH - 1);
BdfList invalidDescriptor = BdfList.of(forumName, invalidSalt); BdfList invalidDescriptor = BdfList.of(forumName, invalidSalt);
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor, BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null)); null));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongSalt() throws Exception { public void testRejectsTooLongSalt() throws Exception {
byte[] invalidSalt = TestUtils.getRandomBytes(FORUM_SALT_LENGTH + 1); byte[] invalidSalt = getRandomBytes(FORUM_SALT_LENGTH + 1);
BdfList invalidDescriptor = BdfList.of(forumName, invalidSalt); BdfList invalidDescriptor = BdfList.of(forumName, invalidSalt);
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor, BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
null)); null));
} }
@@ -141,26 +139,25 @@ public class ForumSharingValidatorTest extends SharingValidatorTest {
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNonStringContent() throws Exception { public void testRejectsNonStringContent() throws Exception {
expectCreateForum(forumName); expectCreateForum(forumName);
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, descriptor, BdfList.of(INVITE.getValue(), previousMsgId, descriptor, 123));
123));
} }
@Test @Test
public void testAcceptsMinLengthContent() throws Exception { public void testAcceptsMinLengthContent() throws Exception {
expectCreateForum(forumName); expectCreateForum(forumName);
expectEncodeMetadata(INVITE); expectEncodeMetadata(INVITE);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext context = validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, descriptor, "1")); BdfList.of(INVITE.getValue(), previousMsgId, descriptor, "1"));
assertExpectedContext(messageContext, previousMsgId); assertExpectedContext(context, previousMsgId);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongContent() throws Exception { public void testRejectsTooLongContent() throws Exception {
String invalidContent = String invalidContent =
StringUtils.getRandomString(MAX_INVITATION_MESSAGE_LENGTH + 1); getRandomString(MAX_INVITATION_MESSAGE_LENGTH + 1);
expectCreateForum(forumName); expectCreateForum(forumName);
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, descriptor, BdfList.of(INVITE.getValue(), previousMsgId, descriptor,
invalidContent)); invalidContent));
} }

View File

@@ -4,10 +4,8 @@ import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.UniqueId; import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.client.BdfMessageContext; import org.briarproject.bramble.api.client.BdfMessageContext;
import org.briarproject.bramble.api.data.BdfDictionary; 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.BdfList;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.test.ValidatorTestCase; import org.briarproject.bramble.test.ValidatorTestCase;
import org.briarproject.briar.api.blog.BlogFactory; import org.briarproject.briar.api.blog.BlogFactory;
import org.briarproject.briar.api.forum.ForumFactory; import org.briarproject.briar.api.forum.ForumFactory;
@@ -18,6 +16,7 @@ import java.util.Collection;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.briar.sharing.MessageType.ABORT; import static org.briarproject.briar.sharing.MessageType.ABORT;
import static org.briarproject.briar.sharing.MessageType.ACCEPT; import static org.briarproject.briar.sharing.MessageType.ACCEPT;
@@ -29,28 +28,26 @@ import static org.junit.Assert.assertTrue;
public abstract class SharingValidatorTest extends ValidatorTestCase { public abstract class SharingValidatorTest extends ValidatorTestCase {
protected final MessageEncoder messageEncoder = final MessageEncoder messageEncoder = context.mock(MessageEncoder.class);
context.mock(MessageEncoder.class); final ForumFactory forumFactory = context.mock(ForumFactory.class);
protected final ForumFactory forumFactory = final BlogFactory blogFactory = context.mock(BlogFactory.class);
context.mock(ForumFactory.class);
protected final BlogFactory blogFactory = context.mock(BlogFactory.class);
protected final SharingValidator v = getValidator();
protected final MessageId previousMsgId = new MessageId(getRandomId()); final SharingValidator validator = getValidator();
private final BdfDictionary meta =
BdfDictionary.of(new BdfEntry("meta", "data")); final MessageId previousMsgId = new MessageId(getRandomId());
private final BdfDictionary meta = new BdfDictionary();
abstract SharingValidator getValidator(); abstract SharingValidator getValidator();
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooShortBodyForInvitation() throws Exception { public void testRejectsTooShortBodyForInvitation() throws Exception {
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, descriptor)); BdfList.of(INVITE.getValue(), previousMsgId, descriptor));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongBodyForInvitation() throws Exception { public void testRejectsTooLongBodyForInvitation() throws Exception {
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(INVITE.getValue(), previousMsgId, descriptor, null, BdfList.of(INVITE.getValue(), previousMsgId, descriptor, null,
123)); 123));
} }
@@ -58,101 +55,101 @@ public abstract class SharingValidatorTest extends ValidatorTestCase {
@Test @Test
public void testAcceptsAccept() throws Exception { public void testAcceptsAccept() throws Exception {
expectEncodeMetadata(ACCEPT); expectEncodeMetadata(ACCEPT);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext context = validator.validateMessage(message, group,
BdfList.of(ACCEPT.getValue(), groupId, previousMsgId)); BdfList.of(ACCEPT.getValue(), groupId, previousMsgId));
assertExpectedContext(messageContext, previousMsgId); assertExpectedContext(context, previousMsgId);
} }
@Test @Test
public void testAcceptsDecline() throws Exception { public void testAcceptsDecline() throws Exception {
expectEncodeMetadata(DECLINE); expectEncodeMetadata(DECLINE);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext context = validator.validateMessage(message, group,
BdfList.of(DECLINE.getValue(), groupId, previousMsgId)); BdfList.of(DECLINE.getValue(), groupId, previousMsgId));
assertExpectedContext(messageContext, previousMsgId); assertExpectedContext(context, previousMsgId);
} }
@Test @Test
public void testAcceptsLeave() throws Exception { public void testAcceptsLeave() throws Exception {
expectEncodeMetadata(LEAVE); expectEncodeMetadata(LEAVE);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext context = validator.validateMessage(message, group,
BdfList.of(LEAVE.getValue(), groupId, previousMsgId)); BdfList.of(LEAVE.getValue(), groupId, previousMsgId));
assertExpectedContext(messageContext, previousMsgId); assertExpectedContext(context, previousMsgId);
} }
@Test @Test
public void testAcceptsAbort() throws Exception { public void testAcceptsAbort() throws Exception {
expectEncodeMetadata(ABORT); expectEncodeMetadata(ABORT);
BdfMessageContext messageContext = v.validateMessage(message, group, BdfMessageContext context = validator.validateMessage(message, group,
BdfList.of(ABORT.getValue(), groupId, previousMsgId)); BdfList.of(ABORT.getValue(), groupId, previousMsgId));
assertExpectedContext(messageContext, previousMsgId); assertExpectedContext(context, previousMsgId);
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNullMessageType() throws Exception { public void testRejectsNullMessageType() throws Exception {
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(null, groupId, previousMsgId)); BdfList.of(null, groupId, previousMsgId));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNonLongMessageType() throws Exception { public void testRejectsNonLongMessageType() throws Exception {
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of("", groupId, previousMsgId)); BdfList.of("", groupId, previousMsgId));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsInvalidMessageType() throws Exception { public void testRejectsInvalidMessageType() throws Exception {
int invalidMessageType = ABORT.getValue() + 1; int invalidMessageType = ABORT.getValue() + 1;
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(invalidMessageType, groupId, previousMsgId)); BdfList.of(invalidMessageType, groupId, previousMsgId));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNullSessionId() throws Exception { public void testRejectsNullSessionId() throws Exception {
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(ABORT.getValue(), null, previousMsgId)); BdfList.of(ABORT.getValue(), null, previousMsgId));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsNonRawSessionId() throws Exception { public void testRejectsNonRawSessionId() throws Exception {
v.validateMessage(message, group, BdfList.of(ABORT.getValue(), 123)); validator.validateMessage(message, group,
BdfList.of(ABORT.getValue(), 123));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooShortSessionId() throws Exception { public void testRejectsTooShortSessionId() throws Exception {
byte[] invalidGroupId = TestUtils.getRandomBytes(UniqueId.LENGTH - 1); byte[] invalidGroupId = getRandomBytes(UniqueId.LENGTH - 1);
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(ABORT.getValue(), invalidGroupId, previousMsgId)); BdfList.of(ABORT.getValue(), invalidGroupId, previousMsgId));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongSessionId() throws Exception { public void testRejectsTooLongSessionId() throws Exception {
byte[] invalidGroupId = TestUtils.getRandomBytes(UniqueId.LENGTH + 1); byte[] invalidGroupId = getRandomBytes(UniqueId.LENGTH + 1);
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(ABORT.getValue(), invalidGroupId, previousMsgId)); BdfList.of(ABORT.getValue(), invalidGroupId, previousMsgId));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooShortBodyForAbort() throws Exception { public void testRejectsTooShortBodyForAbort() throws Exception {
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(ABORT.getValue(), groupId)); BdfList.of(ABORT.getValue(), groupId));
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
public void testRejectsTooLongBodyForAbort() throws Exception { public void testRejectsTooLongBodyForAbort() throws Exception {
v.validateMessage(message, group, validator.validateMessage(message, group,
BdfList.of(ABORT.getValue(), groupId, previousMsgId, 123)); BdfList.of(ABORT.getValue(), groupId, previousMsgId, 123));
} }
protected void expectEncodeMetadata(MessageType type) { void expectEncodeMetadata(MessageType type) {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(messageEncoder) oneOf(messageEncoder).encodeMetadata(type, groupId, timestamp,
.encodeMetadata(type, groupId, timestamp, false, false, false, false, false, false, false);
false, false, false);
will(returnValue(meta)); will(returnValue(meta));
}}); }});
} }
protected void assertExpectedContext(BdfMessageContext messageContext, void assertExpectedContext(BdfMessageContext messageContext,
@Nullable MessageId previousMsgId) throws FormatException { @Nullable MessageId previousMsgId) throws FormatException {
Collection<MessageId> dependencies = messageContext.getDependencies(); Collection<MessageId> dependencies = messageContext.getDependencies();
if (previousMsgId == null) { if (previousMsgId == null) {

View File

@@ -30,7 +30,6 @@ import org.briarproject.bramble.lifecycle.LifecycleModule;
import org.briarproject.bramble.properties.PropertiesModule; import org.briarproject.bramble.properties.PropertiesModule;
import org.briarproject.bramble.sync.SyncModule; import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.system.SystemModule; import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestPluginConfigModule;
import org.briarproject.bramble.test.TestUtils; import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.transport.TransportModule; import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.briar.api.blog.BlogFactory; import org.briarproject.briar.api.blog.BlogFactory;
@@ -64,6 +63,7 @@ import static junit.framework.Assert.assertNotNull;
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED; import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID; import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING; import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
import static org.briarproject.bramble.test.TestPluginConfigModule.MAX_LATENCY;
import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@@ -328,7 +328,7 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
// Create an outgoing sync session // Create an outgoing sync session
SyncSession sessionFrom = SyncSession sessionFrom =
fromSync.createSimplexOutgoingSession(toId, TestPluginConfigModule.MAX_LATENCY, out); fromSync.createSimplexOutgoingSession(toId, MAX_LATENCY, out);
// Write whatever needs to be written // Write whatever needs to be written
sessionFrom.run(); sessionFrom.run();
out.close(); out.close();