mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 19:29:06 +01:00
Move encrypted key, account deletion into AccountManager.
This commit is contained in:
@@ -1,21 +1,140 @@
|
||||
package org.briarproject.bramble.account;
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
class AccountManagerImpl implements AccountManager {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(AccountManagerImpl.class.getName());
|
||||
|
||||
private static final String DB_KEY_FILENAME = "db.key";
|
||||
private static final String DB_KEY_BACKUP_FILENAME = "db.key.bak";
|
||||
|
||||
private final DatabaseConfig databaseConfig;
|
||||
private final File dbKeyFile, dbKeyBackupFile;
|
||||
|
||||
@Nullable
|
||||
private volatile SecretKey databaseKey = null;
|
||||
|
||||
@Inject
|
||||
AccountManagerImpl(DatabaseConfig databaseConfig) {
|
||||
this.databaseConfig = databaseConfig;
|
||||
File keyDir = databaseConfig.getDatabaseKeyDirectory();
|
||||
dbKeyFile = new File(keyDir, DB_KEY_FILENAME);
|
||||
dbKeyBackupFile = new File(keyDir, DB_KEY_BACKUP_FILENAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDatabaseKey() {
|
||||
return databaseConfig.getEncryptionKey() != null;
|
||||
return databaseKey != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public SecretKey getDatabaseKey() {
|
||||
return databaseKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDatabaseKey(SecretKey k) {
|
||||
databaseKey = k;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getEncryptedDatabaseKey() {
|
||||
String key = readDbKeyFromFile(dbKeyFile);
|
||||
if (key == null) {
|
||||
LOG.info("No database key in primary file");
|
||||
key = readDbKeyFromFile(dbKeyBackupFile);
|
||||
if (key == null) LOG.info("No database key in backup file");
|
||||
else LOG.warning("Found database key in backup file");
|
||||
} else {
|
||||
LOG.info("Found database key in primary file");
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String readDbKeyFromFile(File f) {
|
||||
if (!f.exists()) {
|
||||
LOG.info("Key file does not exist");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||
new FileInputStream(f), "UTF-8"));
|
||||
String key = reader.readLine();
|
||||
reader.close();
|
||||
return key;
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean storeEncryptedDatabaseKey(String hex) {
|
||||
LOG.info("Storing database key in file");
|
||||
// Create the directory if necessary
|
||||
if (databaseConfig.getDatabaseKeyDirectory().mkdirs())
|
||||
LOG.info("Created database key directory");
|
||||
// If only the backup file exists, rename it so we don't overwrite it
|
||||
if (dbKeyBackupFile.exists() && !dbKeyFile.exists()) {
|
||||
if (dbKeyBackupFile.renameTo(dbKeyFile))
|
||||
LOG.info("Renamed old backup");
|
||||
else LOG.warning("Failed to rename old backup");
|
||||
}
|
||||
try {
|
||||
// Write to the backup file
|
||||
writeDbKeyToFile(hex, dbKeyBackupFile);
|
||||
LOG.info("Stored database key in backup file");
|
||||
// Delete the old primary file, if it exists
|
||||
if (dbKeyFile.exists()) {
|
||||
if (dbKeyFile.delete()) LOG.info("Deleted primary file");
|
||||
else LOG.warning("Failed to delete primary file");
|
||||
}
|
||||
// The backup file becomes the new primary
|
||||
if (dbKeyBackupFile.renameTo(dbKeyFile)) {
|
||||
LOG.info("Renamed backup file to primary");
|
||||
} else {
|
||||
LOG.warning("Failed to rename backup file to primary");
|
||||
return false; // Don't overwrite our only copy
|
||||
}
|
||||
// Write a second copy to the backup file
|
||||
writeDbKeyToFile(hex, dbKeyBackupFile);
|
||||
LOG.info("Stored second copy of database key in backup file");
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDbKeyToFile(String key, File f) throws IOException {
|
||||
FileOutputStream out = new FileOutputStream(f);
|
||||
out.write(key.getBytes("UTF-8"));
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.briarproject.bramble.db;
|
||||
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DataTooNewException;
|
||||
import org.briarproject.bramble.api.db.DataTooOldException;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
@@ -48,7 +49,8 @@ interface Database<T> {
|
||||
* @throws DataTooOldException if the data uses an older schema than the
|
||||
* current code and cannot be migrated
|
||||
*/
|
||||
boolean open(@Nullable MigrationListener listener) throws DbException;
|
||||
boolean open(SecretKey key, @Nullable MigrationListener listener)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Prevents new transactions from starting, waits for all current
|
||||
@@ -641,7 +643,7 @@ interface Database<T> {
|
||||
* Marks the given transport keys as usable for outgoing streams.
|
||||
*/
|
||||
void setTransportKeysActive(T txn, TransportId t, KeySetId k)
|
||||
throws DbException;
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Updates the transmission count and expiry time of the given message
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.contact.event.ContactAddedEvent;
|
||||
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
||||
import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent;
|
||||
import org.briarproject.bramble.api.contact.event.ContactVerifiedEvent;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.ContactExistsException;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
@@ -103,9 +104,9 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(@Nullable MigrationListener listener)
|
||||
public boolean open(SecretKey key, @Nullable MigrationListener listener)
|
||||
throws DbException {
|
||||
boolean reopened = db.open(listener);
|
||||
boolean reopened = db.open(key, listener);
|
||||
shutdown.addShutdownHook(() -> {
|
||||
try {
|
||||
close();
|
||||
|
||||
@@ -32,6 +32,9 @@ class H2Database extends JdbcDatabase {
|
||||
private final DatabaseConfig config;
|
||||
private final String url;
|
||||
|
||||
@Nullable
|
||||
private volatile SecretKey key = null;
|
||||
|
||||
@Inject
|
||||
H2Database(DatabaseConfig config, Clock clock) {
|
||||
super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
|
||||
@@ -44,11 +47,12 @@ class H2Database extends JdbcDatabase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(@Nullable MigrationListener listener)
|
||||
public boolean open(SecretKey key, @Nullable MigrationListener listener)
|
||||
throws DbException {
|
||||
this.key = key;
|
||||
boolean reopen = config.databaseExists();
|
||||
if (!reopen) config.getDatabaseDirectory().mkdirs();
|
||||
super.open("org.h2.Driver", reopen, listener);
|
||||
super.open("org.h2.Driver", reopen, key, listener);
|
||||
return reopen;
|
||||
}
|
||||
|
||||
@@ -63,7 +67,7 @@ class H2Database extends JdbcDatabase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFreeSpace() throws DbException {
|
||||
public long getFreeSpace() {
|
||||
File dir = config.getDatabaseDirectory();
|
||||
long maxSize = config.getMaxSize();
|
||||
long free = dir.getFreeSpace();
|
||||
@@ -88,7 +92,7 @@ class H2Database extends JdbcDatabase {
|
||||
|
||||
@Override
|
||||
protected Connection createConnection() throws SQLException {
|
||||
SecretKey key = config.getEncryptionKey();
|
||||
SecretKey key = this.key;
|
||||
if (key == null) throw new IllegalStateException();
|
||||
Properties props = new Properties();
|
||||
props.setProperty("user", "user");
|
||||
|
||||
@@ -33,6 +33,9 @@ class HyperSqlDatabase extends JdbcDatabase {
|
||||
private final DatabaseConfig config;
|
||||
private final String url;
|
||||
|
||||
@Nullable
|
||||
private volatile SecretKey key = null;
|
||||
|
||||
@Inject
|
||||
HyperSqlDatabase(DatabaseConfig config, Clock clock) {
|
||||
super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
|
||||
@@ -46,10 +49,12 @@ class HyperSqlDatabase extends JdbcDatabase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(@Nullable MigrationListener listener) throws DbException {
|
||||
public boolean open(SecretKey key, @Nullable MigrationListener listener)
|
||||
throws DbException {
|
||||
this.key = key;
|
||||
boolean reopen = config.databaseExists();
|
||||
if (!reopen) config.getDatabaseDirectory().mkdirs();
|
||||
super.open("org.hsqldb.jdbc.JDBCDriver", reopen, listener);
|
||||
super.open("org.hsqldb.jdbc.JDBCDriver", reopen, key, listener);
|
||||
return reopen;
|
||||
}
|
||||
|
||||
@@ -93,7 +98,7 @@ class HyperSqlDatabase extends JdbcDatabase {
|
||||
|
||||
@Override
|
||||
protected Connection createConnection() throws SQLException {
|
||||
SecretKey key = config.getEncryptionKey();
|
||||
SecretKey key = this.key;
|
||||
if (key == null) throw new IllegalStateException();
|
||||
String hex = StringUtils.toHexString(key.getBytes());
|
||||
return DriverManager.getConnection(url + ";crypt_key=" + hex);
|
||||
|
||||
@@ -328,7 +328,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
protected void open(String driverClass, boolean reopen,
|
||||
protected void open(String driverClass, boolean reopen, SecretKey key,
|
||||
@Nullable MigrationListener listener) throws DbException {
|
||||
// Load the JDBC driver
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.briarproject.bramble.lifecycle;
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DataTooNewException;
|
||||
import org.briarproject.bramble.api.db.DataTooOldException;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
@@ -55,6 +57,7 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
||||
private final List<Service> services;
|
||||
private final List<Client> clients;
|
||||
private final List<ExecutorService> executors;
|
||||
private final AccountManager accountManager;
|
||||
private final IdentityManager identityManager;
|
||||
private final Semaphore startStopSemaphore = new Semaphore(1);
|
||||
private final CountDownLatch dbLatch = new CountDownLatch(1);
|
||||
@@ -65,9 +68,10 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
||||
|
||||
@Inject
|
||||
LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus,
|
||||
IdentityManager identityManager) {
|
||||
AccountManager accountManager, IdentityManager identityManager) {
|
||||
this.db = db;
|
||||
this.eventBus = eventBus;
|
||||
this.accountManager = accountManager;
|
||||
this.identityManager = identityManager;
|
||||
services = new CopyOnWriteArrayList<>();
|
||||
clients = new CopyOnWriteArrayList<>();
|
||||
@@ -104,7 +108,9 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
||||
LOG.info("Starting services");
|
||||
long start = now();
|
||||
|
||||
boolean reopened = db.open(this);
|
||||
SecretKey key = accountManager.getDatabaseKey();
|
||||
if (key == null) throw new IllegalStateException();
|
||||
boolean reopened = db.open(key, this);
|
||||
if (reopened) logDuration(LOG, "Reopening database", start);
|
||||
else logDuration(LOG, "Creating database", start);
|
||||
identityManager.storeLocalAuthor();
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
package org.briarproject.bramble.account;
|
||||
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
import org.jmock.Expectations;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
|
||||
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class AccountManagerImplTest extends BrambleMockTestCase {
|
||||
|
||||
private final DatabaseConfig databaseConfig =
|
||||
context.mock(DatabaseConfig.class);
|
||||
|
||||
private final byte[] encryptedKey = getRandomBytes(123);
|
||||
private final String encryptedKeyHex = toHexString(encryptedKey);
|
||||
private final String oldEncryptedKeyHex = toHexString(getRandomBytes(123));
|
||||
private final File testDir = getTestDirectory();
|
||||
private final File keyDir = new File(testDir, "key");
|
||||
private final File keyFile = new File(keyDir, "db.key");
|
||||
private final File keyBackupFile = new File(keyDir, "db.key.bak");
|
||||
|
||||
private AccountManagerImpl accountManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
context.checking(new Expectations() {{
|
||||
allowing(databaseConfig).getDatabaseKeyDirectory();
|
||||
will(returnValue(keyDir));
|
||||
}});
|
||||
accountManager = new AccountManagerImpl(databaseConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDbKeyIsLoadedFromPrimaryFile() throws Exception {
|
||||
assertFalse(keyFile.exists());
|
||||
assertFalse(keyBackupFile.exists());
|
||||
|
||||
storeDatabaseKey(keyFile, encryptedKeyHex);
|
||||
|
||||
assertTrue(keyFile.exists());
|
||||
assertFalse(keyBackupFile.exists());
|
||||
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||
|
||||
assertEquals(encryptedKeyHex, accountManager.getEncryptedDatabaseKey());
|
||||
|
||||
assertTrue(keyFile.exists());
|
||||
assertFalse(keyBackupFile.exists());
|
||||
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDbKeyIsLoadedFromBackupFile() throws Exception {
|
||||
assertFalse(keyFile.exists());
|
||||
assertFalse(keyBackupFile.exists());
|
||||
|
||||
storeDatabaseKey(keyBackupFile, encryptedKeyHex);
|
||||
|
||||
assertFalse(keyFile.exists());
|
||||
assertTrue(keyBackupFile.exists());
|
||||
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||
|
||||
assertEquals(encryptedKeyHex, accountManager.getEncryptedDatabaseKey());
|
||||
|
||||
assertFalse(keyFile.exists());
|
||||
assertTrue(keyBackupFile.exists());
|
||||
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDbKeyIsNullIfNotFound() {
|
||||
assertFalse(keyFile.exists());
|
||||
assertFalse(keyBackupFile.exists());
|
||||
|
||||
assertNull(accountManager.getEncryptedDatabaseKey());
|
||||
|
||||
assertFalse(keyFile.exists());
|
||||
assertFalse(keyBackupFile.exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoringDbKeyOverwritesPrimary() throws Exception {
|
||||
assertFalse(keyFile.exists());
|
||||
assertFalse(keyBackupFile.exists());
|
||||
|
||||
storeDatabaseKey(keyFile, oldEncryptedKeyHex);
|
||||
|
||||
assertTrue(keyFile.exists());
|
||||
assertFalse(keyBackupFile.exists());
|
||||
assertEquals(oldEncryptedKeyHex, loadDatabaseKey(keyFile));
|
||||
|
||||
assertTrue(accountManager.storeEncryptedDatabaseKey(encryptedKeyHex));
|
||||
|
||||
assertTrue(keyFile.exists());
|
||||
assertTrue(keyBackupFile.exists());
|
||||
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoringDbKeyOverwritesBackup() throws Exception {
|
||||
assertFalse(keyFile.exists());
|
||||
assertFalse(keyBackupFile.exists());
|
||||
|
||||
storeDatabaseKey(keyBackupFile, oldEncryptedKeyHex);
|
||||
|
||||
assertFalse(keyFile.exists());
|
||||
assertTrue(keyBackupFile.exists());
|
||||
assertEquals(oldEncryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||
|
||||
assertTrue(accountManager.storeEncryptedDatabaseKey(encryptedKeyHex));
|
||||
|
||||
assertTrue(keyFile.exists());
|
||||
assertTrue(keyBackupFile.exists());
|
||||
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
deleteTestDirectory(testDir);
|
||||
}
|
||||
|
||||
private void storeDatabaseKey(File f, String hex) throws IOException {
|
||||
f.getParentFile().mkdirs();
|
||||
FileOutputStream out = new FileOutputStream(f);
|
||||
out.write(hex.getBytes("UTF-8"));
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String loadDatabaseKey(File f) throws IOException {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||
new FileInputStream(f), "UTF-8"));
|
||||
String hex = reader.readLine();
|
||||
reader.close();
|
||||
return hex;
|
||||
}
|
||||
}
|
||||
@@ -89,6 +89,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
||||
context.mock(ShutdownManager.class);
|
||||
private final EventBus eventBus = context.mock(EventBus.class);
|
||||
|
||||
private final SecretKey key = getSecretKey();
|
||||
private final Object txn = new Object();
|
||||
private final ClientId clientId;
|
||||
private final int majorVersion;
|
||||
@@ -141,7 +142,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
||||
int shutdownHandle = 12345;
|
||||
context.checking(new Expectations() {{
|
||||
// open()
|
||||
oneOf(database).open(null);
|
||||
oneOf(database).open(key, null);
|
||||
will(returnValue(false));
|
||||
oneOf(shutdown).addShutdownHook(with(any(Runnable.class)));
|
||||
will(returnValue(shutdownHandle));
|
||||
@@ -208,7 +209,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
||||
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
||||
shutdown);
|
||||
|
||||
assertFalse(db.open(null));
|
||||
assertFalse(db.open(key, null));
|
||||
Transaction transaction = db.startTransaction(false);
|
||||
try {
|
||||
db.addLocalAuthor(transaction, localAuthor);
|
||||
@@ -1602,7 +1603,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
||||
MessageId messageId2 = new MessageId(getRandomId());
|
||||
context.checking(new Expectations() {{
|
||||
// open()
|
||||
oneOf(database).open(null);
|
||||
oneOf(database).open(key, null);
|
||||
will(returnValue(false));
|
||||
oneOf(shutdown).addShutdownHook(with(any(Runnable.class)));
|
||||
will(returnValue(shutdownHandle));
|
||||
@@ -1646,7 +1647,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
||||
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
||||
shutdown);
|
||||
|
||||
assertFalse(db.open(null));
|
||||
assertFalse(db.open(key, null));
|
||||
Transaction transaction = db.startTransaction(false);
|
||||
try {
|
||||
db.addLocalMessage(transaction, message, metadata, true);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.briarproject.bramble.db;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DataTooNewException;
|
||||
import org.briarproject.bramble.api.db.DataTooOldException;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
@@ -26,6 +27,7 @@ import static java.util.Collections.singletonList;
|
||||
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
||||
import static org.briarproject.bramble.db.DatabaseConstants.SCHEMA_VERSION_KEY;
|
||||
import static org.briarproject.bramble.db.JdbcDatabase.CODE_SCHEMA_VERSION;
|
||||
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -43,6 +45,7 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
|
||||
protected final DatabaseConfig config =
|
||||
new TestDatabaseConfig(testDir, 1024 * 1024);
|
||||
protected final SecretKey key = getSecretKey();
|
||||
protected final Clock clock = new SystemClock();
|
||||
|
||||
abstract Database<Connection> createDatabase(
|
||||
@@ -62,7 +65,7 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
public void testDoesNotRunMigrationsWhenCreatingDatabase()
|
||||
throws Exception {
|
||||
Database<Connection> db = createDatabase(singletonList(migration));
|
||||
assertFalse(db.open(null));
|
||||
assertFalse(db.open(key, null));
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
db.close();
|
||||
}
|
||||
@@ -72,14 +75,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
throws Exception {
|
||||
// Open the DB for the first time
|
||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||
assertFalse(db.open(null));
|
||||
assertFalse(db.open(key, null));
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
// Override the data schema version
|
||||
setDataSchemaVersion(db, -1);
|
||||
db.close();
|
||||
// Reopen the DB - an exception should be thrown
|
||||
db = createDatabase(asList(migration, migration1));
|
||||
db.open(null);
|
||||
db.open(key, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -87,12 +90,12 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
throws Exception {
|
||||
// Open the DB for the first time
|
||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||
assertFalse(db.open(null));
|
||||
assertFalse(db.open(key, null));
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
db.close();
|
||||
// Reopen the DB - migrations should not be run
|
||||
db = createDatabase(asList(migration, migration1));
|
||||
assertTrue(db.open(null));
|
||||
assertTrue(db.open(key, null));
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
db.close();
|
||||
}
|
||||
@@ -101,14 +104,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
public void testThrowsExceptionIfDataIsNewerThanCode() throws Exception {
|
||||
// Open the DB for the first time
|
||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||
assertFalse(db.open(null));
|
||||
assertFalse(db.open(key, null));
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
// Override the data schema version
|
||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION + 1);
|
||||
db.close();
|
||||
// Reopen the DB - an exception should be thrown
|
||||
db = createDatabase(asList(migration, migration1));
|
||||
db.open(null);
|
||||
db.open(key, null);
|
||||
}
|
||||
|
||||
@Test(expected = DataTooOldException.class)
|
||||
@@ -116,13 +119,13 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
throws Exception {
|
||||
// Open the DB for the first time
|
||||
Database<Connection> db = createDatabase(emptyList());
|
||||
assertFalse(db.open(null));
|
||||
assertFalse(db.open(key, null));
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 1);
|
||||
db.close();
|
||||
// Reopen the DB - an exception should be thrown
|
||||
db = createDatabase(emptyList());
|
||||
db.open(null);
|
||||
db.open(key, null);
|
||||
}
|
||||
|
||||
@Test(expected = DataTooOldException.class)
|
||||
@@ -141,14 +144,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
|
||||
// Open the DB for the first time
|
||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||
assertFalse(db.open(null));
|
||||
assertFalse(db.open(key, null));
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
// Override the data schema version
|
||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 3);
|
||||
db.close();
|
||||
// Reopen the DB - an exception should be thrown
|
||||
db = createDatabase(asList(migration, migration1));
|
||||
db.open(null);
|
||||
db.open(key, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -170,14 +173,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
|
||||
// Open the DB for the first time
|
||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||
assertFalse(db.open(null));
|
||||
assertFalse(db.open(key, null));
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
// Override the data schema version
|
||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 2);
|
||||
db.close();
|
||||
// Reopen the DB - the first migration should be run
|
||||
db = createDatabase(asList(migration, migration1));
|
||||
assertTrue(db.open(null));
|
||||
assertTrue(db.open(key, null));
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
db.close();
|
||||
}
|
||||
@@ -202,14 +205,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
||||
|
||||
// Open the DB for the first time
|
||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||
assertFalse(db.open(null));
|
||||
assertFalse(db.open(key, null));
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
// Override the data schema version
|
||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 2);
|
||||
db.close();
|
||||
// Reopen the DB - both migrations should be run
|
||||
db = createDatabase(asList(migration, migration1));
|
||||
assertTrue(db.open(null));
|
||||
assertTrue(db.open(key, null));
|
||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||
db.close();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.util.List;
|
||||
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
||||
import static org.briarproject.bramble.test.TestUtils.getMean;
|
||||
import static org.briarproject.bramble.test.TestUtils.getMedian;
|
||||
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||
import static org.briarproject.bramble.test.TestUtils.getStandardDeviation;
|
||||
import static org.briarproject.bramble.test.UTest.Z_CRITICAL_0_01;
|
||||
|
||||
@@ -71,7 +72,7 @@ public abstract class DatabasePerformanceComparisonTest
|
||||
throws DbException {
|
||||
Database<Connection> db = createDatabase(conditionA,
|
||||
new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock());
|
||||
db.open(null);
|
||||
db.open(getSecretKey(), null);
|
||||
return db;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.sql.Connection;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
||||
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||
|
||||
public abstract class DatabaseTraceTest extends DatabasePerformanceTest {
|
||||
|
||||
@@ -43,7 +44,7 @@ public abstract class DatabaseTraceTest extends DatabasePerformanceTest {
|
||||
private Database<Connection> openDatabase() throws DbException {
|
||||
Database<Connection> db = createDatabase(
|
||||
new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock());
|
||||
db.open(null);
|
||||
db.open(getSecretKey(), null);
|
||||
return db;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import java.util.List;
|
||||
public class H2MigrationTest extends DatabaseMigrationTest {
|
||||
|
||||
@Override
|
||||
Database<Connection> createDatabase(List<Migration<Connection>> migrations)
|
||||
throws Exception {
|
||||
Database<Connection> createDatabase(
|
||||
List<Migration<Connection>> migrations) {
|
||||
return new H2Database(config, clock) {
|
||||
@Override
|
||||
List<Migration<Connection>> getMigrations() {
|
||||
|
||||
@@ -64,6 +64,7 @@ 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.test.TestUtils.getSecretKey;
|
||||
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
|
||||
import static org.briarproject.bramble.test.TestUtils.getTransportId;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -79,7 +80,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
||||
private static final int ONE_MEGABYTE = 1024 * 1024;
|
||||
private static final int MAX_SIZE = 5 * ONE_MEGABYTE;
|
||||
|
||||
private final File testDir = TestUtils.getTestDirectory();
|
||||
private final SecretKey key = getSecretKey();
|
||||
private final File testDir = getTestDirectory();
|
||||
private final GroupId groupId;
|
||||
private final ClientId clientId;
|
||||
private final int majorVersion;
|
||||
@@ -96,7 +98,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
||||
private final KeySetId keySetId, keySetId1;
|
||||
private final Random random = new Random();
|
||||
|
||||
JdbcDatabaseTest() throws Exception {
|
||||
JdbcDatabaseTest() {
|
||||
clientId = getClientId();
|
||||
majorVersion = 123;
|
||||
group = getGroup(clientId, majorVersion);
|
||||
@@ -1819,7 +1821,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
||||
Database<Connection> db = createDatabase(
|
||||
new TestDatabaseConfig(testDir, MAX_SIZE), clock);
|
||||
if (!resume) TestUtils.deleteTestDirectory(testDir);
|
||||
db.open(null);
|
||||
db.open(key, null);
|
||||
return db;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.List;
|
||||
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
||||
import static org.briarproject.bramble.test.TestUtils.getMean;
|
||||
import static org.briarproject.bramble.test.TestUtils.getMedian;
|
||||
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||
import static org.briarproject.bramble.test.TestUtils.getStandardDeviation;
|
||||
|
||||
public abstract class SingleDatabasePerformanceTest
|
||||
@@ -40,7 +41,7 @@ public abstract class SingleDatabasePerformanceTest
|
||||
private Database<Connection> openDatabase() throws DbException {
|
||||
Database<Connection> db = createDatabase(
|
||||
new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock());
|
||||
db.open(null);
|
||||
db.open(getSecretKey(), null);
|
||||
return db;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.bramble.test;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@@ -11,7 +10,6 @@ public class TestDatabaseConfig implements DatabaseConfig {
|
||||
|
||||
private final File dbDir, keyDir;
|
||||
private final long maxSize;
|
||||
private volatile SecretKey key = new SecretKey(new byte[SecretKey.LENGTH]);
|
||||
|
||||
public TestDatabaseConfig(File testDir, long maxSize) {
|
||||
dbDir = new File(testDir, "db");
|
||||
@@ -36,16 +34,6 @@ public class TestDatabaseConfig implements DatabaseConfig {
|
||||
return keyDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEncryptionKey(SecretKey key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKey getEncryptionKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxSize() {
|
||||
return maxSize;
|
||||
|
||||
Reference in New Issue
Block a user