diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/account/AccountManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/account/AccountManager.java
index 4aa4fb2b5b34b34ebbc1156fdf40315a21b9fcb9..e1efc91dc8480589a98744ad96ccc647842c0112 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/account/AccountManager.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/account/AccountManager.java
@@ -1,6 +1,22 @@
 package org.briarproject.bramble.api.account;
 
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.Nullable;
+
+@NotNullByDefault
 public interface AccountManager {
 
 	boolean hasDatabaseKey();
+
+	@Nullable
+	SecretKey getDatabaseKey();
+
+	void setDatabaseKey(SecretKey k);
+
+	@Nullable
+	String getEncryptedDatabaseKey();
+
+	boolean storeEncryptedDatabaseKey(String hex);
 }
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
index 914b88a2e2d1db1a8bafa328850ca07dd80ed189..f4161cee44ef19c37a4604c5ad6c24a585e36f09 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java
@@ -2,6 +2,7 @@ package org.briarproject.bramble.api.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.identity.Author;
 import org.briarproject.bramble.api.identity.AuthorId;
 import org.briarproject.bramble.api.identity.LocalAuthor;
@@ -44,7 +45,8 @@ public interface DatabaseComponent {
 	 * @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;
 
 	/**
 	 * Waits for any open transactions to finish and closes the database.
@@ -267,7 +269,7 @@ public interface DatabaseComponent {
 	 * Read-only.
 	 */
 	Collection<MessageId> getMessageIds(Transaction txn, GroupId g)
-		throws DbException;
+			throws DbException;
 
 	/**
 	 * Returns the IDs of any messages that need to be validated.
@@ -487,7 +489,7 @@ public interface DatabaseComponent {
 	 * Removes the given transport keys from the database.
 	 */
 	void removeTransportKeys(Transaction txn, TransportId t, KeySetId k)
-		throws DbException;
+			throws DbException;
 
 	/**
 	 * Marks the given contact as verified.
@@ -534,7 +536,7 @@ public interface DatabaseComponent {
 	 * Marks the given transport keys as usable for outgoing streams.
 	 */
 	void setTransportKeysActive(Transaction txn, TransportId t, KeySetId k)
-		throws DbException;
+			throws DbException;
 
 	/**
 	 * Stores the given transport keys, deleting any keys they have replaced.
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java
index e431c15f2bc1621d8aef464e3c6929636861dd71..a9a95c47a2bdab6dcc1153725ee1000826723765 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java
@@ -1,12 +1,9 @@
 package org.briarproject.bramble.api.db;
 
-import org.briarproject.bramble.api.crypto.SecretKey;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.File;
 
-import javax.annotation.Nullable;
-
 @NotNullByDefault
 public interface DatabaseConfig {
 
@@ -16,10 +13,5 @@ public interface DatabaseConfig {
 
 	File getDatabaseKeyDirectory();
 
-	void setEncryptionKey(SecretKey key);
-
-	@Nullable
-	SecretKey getEncryptionKey();
-
 	long getMaxSize();
 }
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java
index dd4df479a3c27b6733cd1b55109421c97fca3fc5..cbc813d712728f70d5e165b14e0145ccf80ca0bc 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java
@@ -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();
 	}
 }
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
index 66e5cfcf6d72ec90eed0dffa4bbf56c51d38b071..796e4bbe40720e23a9e6ab98b8e5559fb4c4cd8d 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java
@@ -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
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
index f2e4de1c6fff7cbd3fbc6e92f52dead50c34b458..2913c783f4407344a04ab9e63d8b87bafbd2863f 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java
@@ -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();
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java
index 1c1983e6771a2cc174ebcbf68ede5879aab7569f..fd5be69056a57b2a3f13ca8c8476c015c4e958f1 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java
@@ -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");
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/HyperSqlDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/HyperSqlDatabase.java
index 6a87ededae7b862c992745f15ac5695f881a6cf0..0bfb66ea6eb2c00a2fe733f08032fc4bf62120d5 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/db/HyperSqlDatabase.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/HyperSqlDatabase.java
@@ -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);
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
index baa67a29ac6397c6c7e26b17a18feb455924c111..fd248f811e9b8c703ead29088b49317409792785 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java
@@ -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 {
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java
index b99ab31e1d33d7552f90c5668583c677a9373b5e..a2c4d7e3fcbbfa744021fcceca26b4046cad3f52 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java
@@ -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();
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/account/AccountManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/account/AccountManagerImplTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..7e1f6124df79e8e273e14f7135e0bf13cf1a9f5e
--- /dev/null
+++ b/bramble-core/src/test/java/org/briarproject/bramble/account/AccountManagerImplTest.java
@@ -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;
+	}
+}
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java
index e16e03da0dc51086f73c9c6ed45ee81483f8a3b1..676cac2e3708b0465afe2bc08ccaf3ff7a308988 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java
@@ -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);
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseMigrationTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseMigrationTest.java
index 89bdf8a4c1a8da94963bc41c7473be59b3f7c063..0740bdfc2301bff10330aba7dc99114936f0ace3 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseMigrationTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseMigrationTest.java
@@ -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();
 	}
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabasePerformanceComparisonTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabasePerformanceComparisonTest.java
index 1807d30dc33374654a740b4acb58336bee1f5b52..279d1b56e6e0ae44fdb1929a37154a7af6c854e9 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabasePerformanceComparisonTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabasePerformanceComparisonTest.java
@@ -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;
 	}
 
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseTraceTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseTraceTest.java
index f4e0daa19dedf3d6e0187a4aa1b7e8d181136906..2060ca71ec35807190e04518fe123e257fbc6a59 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseTraceTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseTraceTest.java
@@ -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;
 	}
 
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/H2MigrationTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/H2MigrationTest.java
index 6a868fd42fa9ff2098087fbf9aa5b5c9f3d346c9..29bdbfa5f5b962a427ffdeeef8f9f94429be8ca4 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/db/H2MigrationTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/db/H2MigrationTest.java
@@ -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() {
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java
index 2655e9ef7f571cdbcc80abb2a492e3b0e7c5bdcd..e88038258ad7007b909eb499cc5243eaee11d398 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java
@@ -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;
 	}
 
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/SingleDatabasePerformanceTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/SingleDatabasePerformanceTest.java
index 670c7cddb79746be691317387a0c779d0c6b5213..6256d39cd07c51d5ee2bba18983fdecef20f41c1 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/db/SingleDatabasePerformanceTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/db/SingleDatabasePerformanceTest.java
@@ -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;
 	}
 
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/TestDatabaseConfig.java b/bramble-core/src/test/java/org/briarproject/bramble/test/TestDatabaseConfig.java
index 7e5ad34e7dcd681754093163da3b3255f4c39bf6..89f68a30ea0b86e1d04c2039a5445a2d5b00a674 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/test/TestDatabaseConfig.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/test/TestDatabaseConfig.java
@@ -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;
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidDatabaseConfig.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidDatabaseConfig.java
index 1f21acdb0c3e3532bcc1b2707f0ac1f03c47f4be..9aa2ac6ae02163c43101a945bf15bba78f1eae43 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/AndroidDatabaseConfig.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidDatabaseConfig.java
@@ -1,14 +1,11 @@
 package org.briarproject.briar.android;
 
-import org.briarproject.bramble.api.crypto.SecretKey;
 import org.briarproject.bramble.api.db.DatabaseConfig;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 
 import java.io.File;
 import java.util.logging.Logger;
 
-import javax.annotation.Nullable;
-
 import static java.util.logging.Level.INFO;
 
 @NotNullByDefault
@@ -19,9 +16,6 @@ class AndroidDatabaseConfig implements DatabaseConfig {
 
 	private final File dbDir, keyDir;
 
-	@Nullable
-	private volatile SecretKey key = null;
-
 	AndroidDatabaseConfig(File dbDir, File keyDir) {
 		this.dbDir = dbDir;
 		this.keyDir = keyDir;
@@ -62,21 +56,6 @@ class AndroidDatabaseConfig implements DatabaseConfig {
 		return keyDir;
 	}
 
-	@Override
-	public void setEncryptionKey(SecretKey key) {
-		LOG.info("Setting database key");
-		this.key = key;
-	}
-
-	@Override
-	@Nullable
-	public SecretKey getEncryptionKey() {
-		SecretKey key = this.key;
-		if (LOG.isLoggable(INFO))
-			LOG.info("Database key has been set: " + (key != null));
-		return key;
-	}
-
 	@Override
 	public long getMaxSize() {
 		return Long.MAX_VALUE;
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java
index cb0d2c3c3f996a40dd6ad0a8c570c243c9b07685..1f730537115a2a30fb1aebc8a7249102928161ed 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java
@@ -9,20 +9,11 @@ import org.briarproject.bramble.api.db.DatabaseConfig;
 import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
 import org.briarproject.bramble.util.AndroidUtils;
 
-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;
-
 @NotNullByDefault
 public class ConfigControllerImpl implements ConfigController {
 
@@ -30,12 +21,9 @@ public class ConfigControllerImpl implements ConfigController {
 			Logger.getLogger(ConfigControllerImpl.class.getName());
 
 	private static final String PREF_DB_KEY = "key";
-	private static final String DB_KEY_FILENAME = "db.key";
-	private static final String DB_KEY_BACKUP_FILENAME = "db.key.bak";
 
 	private final SharedPreferences briarPrefs;
-	private final File dbKeyFile, dbKeyBackupFile;
-	private final AccountManager accountManager;
+	protected final AccountManager accountManager;
 	protected final DatabaseConfig databaseConfig;
 
 	@Inject
@@ -44,16 +32,13 @@ public class ConfigControllerImpl implements ConfigController {
 		this.briarPrefs = briarPrefs;
 		this.accountManager = accountManager;
 		this.databaseConfig = databaseConfig;
-		File keyDir = databaseConfig.getDatabaseKeyDirectory();
-		dbKeyFile = new File(keyDir, DB_KEY_FILENAME);
-		dbKeyBackupFile = new File(keyDir, DB_KEY_BACKUP_FILENAME);
 	}
 
 	@Override
 	@Nullable
 	public String getEncryptedDatabaseKey() {
 		String key = getDatabaseKeyFromPreferences();
-		if (key == null) key = getDatabaseKeyFromFile();
+		if (key == null) key = accountManager.getEncryptedDatabaseKey();
 		else migrateDatabaseKeyToFile(key);
 		return key;
 	}
@@ -66,40 +51,8 @@ public class ConfigControllerImpl implements ConfigController {
 		return key;
 	}
 
-	@Nullable
-	private String getDatabaseKeyFromFile() {
-		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;
-		}
-	}
-
 	private void migrateDatabaseKeyToFile(String key) {
-		if (storeEncryptedDatabaseKey(key)) {
+		if (accountManager.storeEncryptedDatabaseKey(key)) {
 			if (briarPrefs.edit().remove(PREF_DB_KEY).commit())
 				LOG.info("Database key migrated to file");
 			else LOG.warning("Database key not removed from preferences");
@@ -110,47 +63,7 @@ public class ConfigControllerImpl implements ConfigController {
 
 	@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();
+		return accountManager.storeEncryptedDatabaseKey(hex);
 	}
 
 	@Override
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java
index ca9634502a7a58917826a9885e95aa9f3ba782e7..5a3cd5b8de72427e9a169ae6fd83ef285a89427f 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java
@@ -57,7 +57,7 @@ public class PasswordControllerImpl extends ConfigControllerImpl
 			if (key == null) {
 				resultHandler.onResult(false);
 			} else {
-				databaseConfig.setEncryptionKey(new SecretKey(key));
+				accountManager.setDatabaseKey(new SecretKey(key));
 				resultHandler.onResult(true);
 			}
 		});
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java
index 30d039849c191699854e43090a981d89a3870af2..a2395d894900ec0e6437a3d5813ad268460f4ec0 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java
@@ -115,7 +115,7 @@ public class SetupControllerImpl extends PasswordControllerImpl
 			SecretKey key = crypto.generateSecretKey();
 			String hex = encryptDatabaseKey(key, password);
 			storeEncryptedDatabaseKey(hex);
-			databaseConfig.setEncryptionKey(key);
+			accountManager.setDatabaseKey(key);
 			resultHandler.onResult(null);
 		});
 	}
diff --git a/briar-android/src/test/java/org/briarproject/briar/android/TestDatabaseKeyUtils.java b/briar-android/src/test/java/org/briarproject/briar/android/TestDatabaseKeyUtils.java
deleted file mode 100644
index 0e9173105fa19f99747e91c4c68d25fbb2bd2138..0000000000000000000000000000000000000000
--- a/briar-android/src/test/java/org/briarproject/briar/android/TestDatabaseKeyUtils.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.briarproject.briar.android;
-
-import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-
-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.assertTrue;
-
-@NotNullByDefault
-public class TestDatabaseKeyUtils {
-
-	public static 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
-	public static 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;
-	}
-}
diff --git a/briar-android/src/test/java/org/briarproject/briar/android/controller/ConfigControllerImplTest.java b/briar-android/src/test/java/org/briarproject/briar/android/controller/ConfigControllerImplTest.java
index d8e4445c29a57d0ccd171e40e1e70658a5199a8a..06f1165ab96a045b71a6f27c3809c7c68eb5a1c2 100644
--- a/briar-android/src/test/java/org/briarproject/briar/android/controller/ConfigControllerImplTest.java
+++ b/briar-android/src/test/java/org/briarproject/briar/android/controller/ConfigControllerImplTest.java
@@ -7,21 +7,11 @@ import org.briarproject.bramble.api.account.AccountManager;
 import org.briarproject.bramble.api.db.DatabaseConfig;
 import org.briarproject.bramble.test.BrambleMockTestCase;
 import org.jmock.Expectations;
-import org.junit.After;
 import org.junit.Test;
 
-import java.io.File;
-
 import static junit.framework.Assert.assertEquals;
-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.briarproject.briar.android.TestDatabaseKeyUtils.loadDatabaseKey;
-import static org.briarproject.briar.android.TestDatabaseKeyUtils.storeDatabaseKey;
 
 public class ConfigControllerImplTest extends BrambleMockTestCase {
 
@@ -33,21 +23,15 @@ public class ConfigControllerImplTest extends BrambleMockTestCase {
 			context.mock(DatabaseConfig.class);
 	private final Editor editor = context.mock(Editor.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 final String encryptedKeyHex = toHexString(getRandomBytes(123));
 
 	@Test
-	public void testDbKeyIsMigratedFromPreferencesToFile() throws Exception {
+	public void testDbKeyIsMigratedFromPreferencesToFile() {
 		context.checking(new Expectations() {{
 			oneOf(prefs).getString("key", null);
 			will(returnValue(encryptedKeyHex));
-			allowing(databaseConfig).getDatabaseKeyDirectory();
-			will(returnValue(keyDir));
+			oneOf(accountManager).storeEncryptedDatabaseKey(encryptedKeyHex);
+			will(returnValue(true));
 			oneOf(prefs).edit();
 			will(returnValue(editor));
 			oneOf(editor).remove("key");
@@ -56,153 +40,10 @@ public class ConfigControllerImplTest extends BrambleMockTestCase {
 			will(returnValue(true));
 		}});
 
-		assertFalse(keyFile.exists());
-		assertFalse(keyBackupFile.exists());
-
-		ConfigControllerImpl c = new ConfigControllerImpl(prefs, accountManager,
-				databaseConfig);
-
-		assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey());
-
-		assertTrue(keyFile.exists());
-		assertTrue(keyBackupFile.exists());
-		assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
-		assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
-	}
-
-	@Test
-	public void testDbKeyIsLoadedFromPrimaryFile() throws Exception {
-		context.checking(new Expectations() {{
-			oneOf(prefs).getString("key", null);
-			will(returnValue(null));
-			allowing(databaseConfig).getDatabaseKeyDirectory();
-			will(returnValue(keyDir));
-		}});
-
-		assertFalse(keyFile.exists());
-		assertFalse(keyBackupFile.exists());
-
-		storeDatabaseKey(keyFile, encryptedKeyHex);
-
-		assertTrue(keyFile.exists());
-		assertFalse(keyBackupFile.exists());
-		assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
-
-		ConfigControllerImpl c = new ConfigControllerImpl(prefs, accountManager,
-				databaseConfig);
-
-		assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey());
-
-		assertTrue(keyFile.exists());
-		assertFalse(keyBackupFile.exists());
-		assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
-	}
-
-	@Test
-	public void testDbKeyIsLoadedFromBackupFile() throws Exception {
-		context.checking(new Expectations() {{
-			oneOf(prefs).getString("key", null);
-			will(returnValue(null));
-			allowing(databaseConfig).getDatabaseKeyDirectory();
-			will(returnValue(keyDir));
-		}});
-
-		assertFalse(keyFile.exists());
-		assertFalse(keyBackupFile.exists());
-
-		storeDatabaseKey(keyBackupFile, encryptedKeyHex);
-
-		assertFalse(keyFile.exists());
-		assertTrue(keyBackupFile.exists());
-		assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
-
 		ConfigControllerImpl c = new ConfigControllerImpl(prefs, accountManager,
 				databaseConfig);
 
 		assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey());
-
-		assertFalse(keyFile.exists());
-		assertTrue(keyBackupFile.exists());
-		assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
 	}
 
-	@Test
-	public void testDbKeyIsNullIfNotFound() {
-		context.checking(new Expectations() {{
-			oneOf(prefs).getString("key", null);
-			will(returnValue(null));
-			allowing(databaseConfig).getDatabaseKeyDirectory();
-			will(returnValue(keyDir));
-		}});
-
-		assertFalse(keyFile.exists());
-		assertFalse(keyBackupFile.exists());
-
-		ConfigControllerImpl c = new ConfigControllerImpl(prefs, accountManager,
-				databaseConfig);
-
-		assertNull(c.getEncryptedDatabaseKey());
-
-		assertFalse(keyFile.exists());
-		assertFalse(keyBackupFile.exists());
-	}
-
-	@Test
-	public void testStoringDbKeyOverwritesPrimary() throws Exception {
-		context.checking(new Expectations() {{
-			allowing(databaseConfig).getDatabaseKeyDirectory();
-			will(returnValue(keyDir));
-		}});
-
-		assertFalse(keyFile.exists());
-		assertFalse(keyBackupFile.exists());
-
-		storeDatabaseKey(keyFile, oldEncryptedKeyHex);
-
-		assertTrue(keyFile.exists());
-		assertFalse(keyBackupFile.exists());
-		assertEquals(oldEncryptedKeyHex, loadDatabaseKey(keyFile));
-
-		ConfigController c = new ConfigControllerImpl(prefs, accountManager,
-				databaseConfig);
-
-		assertTrue(c.storeEncryptedDatabaseKey(encryptedKeyHex));
-
-		assertTrue(keyFile.exists());
-		assertTrue(keyBackupFile.exists());
-		assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
-		assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
-	}
-
-	@Test
-	public void testStoringDbKeyOverwritesBackup() throws Exception {
-		context.checking(new Expectations() {{
-			allowing(databaseConfig).getDatabaseKeyDirectory();
-			will(returnValue(keyDir));
-		}});
-
-		assertFalse(keyFile.exists());
-		assertFalse(keyBackupFile.exists());
-
-		storeDatabaseKey(keyBackupFile, oldEncryptedKeyHex);
-
-		assertFalse(keyFile.exists());
-		assertTrue(keyBackupFile.exists());
-		assertEquals(oldEncryptedKeyHex, loadDatabaseKey(keyBackupFile));
-
-		ConfigController c = new ConfigControllerImpl(prefs, accountManager,
-				databaseConfig);
-
-		assertTrue(c.storeEncryptedDatabaseKey(encryptedKeyHex));
-
-		assertTrue(keyFile.exists());
-		assertTrue(keyBackupFile.exists());
-		assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
-		assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
-	}
-
-	@After
-	public void tearDown() {
-		deleteTestDirectory(testDir);
-	}
 }
diff --git a/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordControllerImplTest.java b/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordControllerImplTest.java
index dcc2685b64d82f4dbbc6c77e4600b83eb7398891..9c64083cdabc5701cd20f106f43df8e520e35b50 100644
--- a/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordControllerImplTest.java
+++ b/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordControllerImplTest.java
@@ -9,23 +9,16 @@ import org.briarproject.bramble.api.db.DatabaseConfig;
 import org.briarproject.bramble.test.BrambleMockTestCase;
 import org.briarproject.bramble.test.ImmediateExecutor;
 import org.jmock.Expectations;
-import org.junit.After;
 import org.junit.Test;
 
-import java.io.File;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 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.getSecretKey;
-import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
 import static org.briarproject.bramble.util.StringUtils.toHexString;
-import static org.briarproject.briar.android.TestDatabaseKeyUtils.loadDatabaseKey;
-import static org.briarproject.briar.android.TestDatabaseKeyUtils.storeDatabaseKey;
 
 public class PasswordControllerImplTest extends BrambleMockTestCase {
 
@@ -46,32 +39,27 @@ public class PasswordControllerImplTest extends BrambleMockTestCase {
 	private final byte[] oldEncryptedKey = getRandomBytes(123);
 	private final byte[] newEncryptedKey = getRandomBytes(123);
 	private final byte[] key = getSecretKey().getBytes();
-	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 final String oldEncryptedKeyHex = toHexString(oldEncryptedKey);
+	private final String newEncryptedKeyHex = toHexString(newEncryptedKey);
 
 	@Test
-	public void testChangePasswordReturnsTrue() throws Exception {
+	public void testChangePasswordReturnsTrue() {
 		context.checking(new Expectations() {{
 			// Look up the encrypted DB key
 			oneOf(briarPrefs).getString("key", null);
 			will(returnValue(null));
-			allowing(databaseConfig).getDatabaseKeyDirectory();
-			will(returnValue(keyDir));
+			oneOf(accountManager).getEncryptedDatabaseKey();
+			will(returnValue(oldEncryptedKeyHex));
 			// Decrypt and re-encrypt the key
 			oneOf(crypto).decryptWithPassword(oldEncryptedKey, oldPassword);
 			will(returnValue(key));
 			oneOf(crypto).encryptWithPassword(key, newPassword);
 			will(returnValue(newEncryptedKey));
+			// Store the new key
+			oneOf(accountManager).storeEncryptedDatabaseKey(newEncryptedKeyHex);
+			will(returnValue(true));
 		}});
 
-		assertFalse(keyFile.exists());
-		assertFalse(keyBackupFile.exists());
-
-		storeDatabaseKey(keyFile, toHexString(oldEncryptedKey));
-		storeDatabaseKey(keyBackupFile, toHexString(oldEncryptedKey));
-
 		PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs,
 				accountManager, databaseConfig, cryptoExecutor, crypto,
 				estimator);
@@ -79,34 +67,21 @@ public class PasswordControllerImplTest extends BrambleMockTestCase {
 		AtomicBoolean capturedResult = new AtomicBoolean(false);
 		p.changePassword(oldPassword, newPassword, capturedResult::set);
 		assertTrue(capturedResult.get());
-
-		assertTrue(keyFile.exists());
-		assertTrue(keyBackupFile.exists());
-		assertEquals(toHexString(newEncryptedKey), loadDatabaseKey(keyFile));
-		assertEquals(toHexString(newEncryptedKey),
-				loadDatabaseKey(keyBackupFile));
 	}
 
 	@Test
-	public void testChangePasswordReturnsFalseIfOldPasswordIsWrong()
-			throws Exception {
+	public void testChangePasswordReturnsFalseIfOldPasswordIsWrong() {
 		context.checking(new Expectations() {{
 			// Look up the encrypted DB key
 			oneOf(briarPrefs).getString("key", null);
 			will(returnValue(null));
-			allowing(databaseConfig).getDatabaseKeyDirectory();
-			will(returnValue(keyDir));
+			oneOf(accountManager).getEncryptedDatabaseKey();
+			will(returnValue(oldEncryptedKeyHex));
 			// Try to decrypt the key - the password is wrong
 			oneOf(crypto).decryptWithPassword(oldEncryptedKey, oldPassword);
 			will(returnValue(null));
 		}});
 
-		assertFalse(keyFile.exists());
-		assertFalse(keyBackupFile.exists());
-
-		storeDatabaseKey(keyFile, toHexString(oldEncryptedKey));
-		storeDatabaseKey(keyBackupFile, toHexString(oldEncryptedKey));
-
 		PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs,
 				accountManager, databaseConfig, cryptoExecutor, crypto,
 				estimator);
@@ -114,16 +89,5 @@ public class PasswordControllerImplTest extends BrambleMockTestCase {
 		AtomicBoolean capturedResult = new AtomicBoolean(true);
 		p.changePassword(oldPassword, newPassword, capturedResult::set);
 		assertFalse(capturedResult.get());
-
-		assertTrue(keyFile.exists());
-		assertTrue(keyBackupFile.exists());
-		assertEquals(toHexString(oldEncryptedKey), loadDatabaseKey(keyFile));
-		assertEquals(toHexString(oldEncryptedKey),
-				loadDatabaseKey(keyBackupFile));
-	}
-
-	@After
-	public void tearDown() {
-		deleteTestDirectory(testDir);
 	}
 }
diff --git a/briar-android/src/test/java/org/briarproject/briar/android/login/SetupControllerImplTest.java b/briar-android/src/test/java/org/briarproject/briar/android/login/SetupControllerImplTest.java
index dd88251476c131674d7e663cd095d4e8cea6dc06..4671bb1c4741797511d4c02a8b4f0ededadc91f5 100644
--- a/briar-android/src/test/java/org/briarproject/briar/android/login/SetupControllerImplTest.java
+++ b/briar-android/src/test/java/org/briarproject/briar/android/login/SetupControllerImplTest.java
@@ -1,7 +1,6 @@
 package org.briarproject.briar.android.login;
 
 import android.content.SharedPreferences;
-import android.content.pm.ApplicationInfo;
 
 import org.briarproject.bramble.api.account.AccountManager;
 import org.briarproject.bramble.api.crypto.CryptoComponent;
@@ -14,25 +13,18 @@ import org.briarproject.bramble.test.BrambleMockTestCase;
 import org.briarproject.bramble.test.ImmediateExecutor;
 import org.jmock.Expectations;
 import org.jmock.lib.legacy.ClassImposteriser;
-import org.junit.After;
 import org.junit.Test;
 
-import java.io.File;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
-import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
 import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
 import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
 import static org.briarproject.bramble.test.TestUtils.getSecretKey;
-import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
 import static org.briarproject.bramble.util.StringUtils.getRandomString;
 import static org.briarproject.bramble.util.StringUtils.toHexString;
-import static org.briarproject.briar.android.TestDatabaseKeyUtils.loadDatabaseKey;
 
 public class SetupControllerImplTest extends BrambleMockTestCase {
 
@@ -55,11 +47,8 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
 	private final String password = "some.strong.pass";
 	private final LocalAuthor localAuthor = getLocalAuthor();
 	private final byte[] encryptedKey = getRandomBytes(123);
+	private final String encryptedKeyHex = toHexString(encryptedKey);
 	private final SecretKey key = getSecretKey();
-	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");
 
 	public SetupControllerImplTest() {
 		context.setImposteriser(ClassImposteriser.INSTANCE);
@@ -68,13 +57,8 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
 
 	@Test
 	@SuppressWarnings("ResultOfMethodCallIgnored")
-	public void testCreateAccount() throws Exception {
+	public void testCreateAccount() {
 		context.checking(new Expectations() {{
-			// Allow the contents of the data directory to be logged
-			allowing(setupActivity).getApplicationInfo();
-			will(returnValue(new ApplicationInfo() {{
-				dataDir = testDir.getAbsolutePath();
-			}}));
 			// Set the author name and password
 			oneOf(setupActivity).setAuthorName(authorName);
 			oneOf(setupActivity).setPassword(password);
@@ -94,15 +78,12 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
 			oneOf(crypto).encryptWithPassword(key.getBytes(), password);
 			will(returnValue(encryptedKey));
 			// Store the encrypted key
-			allowing(databaseConfig).getDatabaseKeyDirectory();
-			will(returnValue(keyDir));
-			// Attach the database key to the database config
-			oneOf(databaseConfig).setEncryptionKey(key);
+			oneOf(accountManager).storeEncryptedDatabaseKey(encryptedKeyHex);
+			will(returnValue(true));
+			// Pass the database key to the account manager
+			oneOf(accountManager).setDatabaseKey(key);
 		}});
 
-		assertFalse(keyFile.exists());
-		assertFalse(keyBackupFile.exists());
-
 		SetupControllerImpl s = new SetupControllerImpl(briarPrefs,
 				accountManager, databaseConfig, cryptoExecutor, crypto,
 				estimator, identityManager);
@@ -113,17 +94,5 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
 		s.setPassword(password);
 		s.createAccount(result -> called.set(true));
 		assertTrue(called.get());
-
-		assertTrue(keyFile.exists());
-		assertTrue(keyBackupFile.exists());
-		assertEquals(toHexString(encryptedKey),
-				loadDatabaseKey(keyFile));
-		assertEquals(toHexString(encryptedKey),
-				loadDatabaseKey(keyBackupFile));
-	}
-
-	@After
-	public void tearDown() {
-		deleteTestDirectory(testDir);
 	}
 }
diff --git a/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTest.java
index fec963b331277025640566dd563159e605a0f3d9..7aafa6ce4c47e09b7bd02ab66dcee5e5a9d3cc2a 100644
--- a/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTest.java
@@ -27,6 +27,7 @@ import org.junit.Test;
 import java.io.File;
 import java.util.Collection;
 
+import static org.briarproject.bramble.test.TestUtils.getSecretKey;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -53,6 +54,8 @@ public class FeedManagerIntegrationTest extends BriarTestCase {
 		LocalAuthor localAuthor = identityManager.createLocalAuthor("feedTest");
 		identityManager.registerLocalAuthor(localAuthor);
 
+		component.getAccountManager().setDatabaseKey(getSecretKey());
+
 		lifecycleManager = component.getLifecycleManager();
 		lifecycleManager.startServices();
 		lifecycleManager.waitForStartup();
diff --git a/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java
index 685eedacba48c4a6286667c47f0f053ad521cc45..3fc4a9ea623d20f97db61b681c3cf9b73b5bd86a 100644
--- a/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java
+++ b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java
@@ -1,5 +1,7 @@
 package org.briarproject.briar.feed;
 
+import org.briarproject.bramble.account.AccountModule;
+import org.briarproject.bramble.api.account.AccountManager;
 import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.lifecycle.LifecycleManager;
 import org.briarproject.bramble.client.ClientModule;
@@ -36,6 +38,7 @@ import dagger.Component;
 		TestSecureRandomModule.class,
 		TestSocksModule.class,
 		TestDnsModule.class,
+		AccountModule.class,
 		BriarClientModule.class,
 		ClientModule.class,
 		ContactModule.class,
@@ -79,6 +82,8 @@ interface FeedManagerIntegrationTestComponent {
 
 	IdentityManager getIdentityManager();
 
+	AccountManager getAccountManager();
+
 	LifecycleManager getLifecycleManager();
 
 	FeedManager getFeedManager();
diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java
index 108f4884967f809278a1ebfd0d26ca0defbc4c39..2da286b05feaad8ea0332a7e6c5fca22bd0b4ef3 100644
--- a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java
+++ b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java
@@ -1,5 +1,6 @@
 package org.briarproject.briar.introduction;
 
+import org.briarproject.bramble.account.AccountModule;
 import org.briarproject.bramble.client.ClientModule;
 import org.briarproject.bramble.contact.ContactModule;
 import org.briarproject.bramble.crypto.CryptoExecutorModule;
@@ -36,6 +37,7 @@ import dagger.Component;
 		TestDatabaseModule.class,
 		TestPluginConfigModule.class,
 		TestSecureRandomModule.class,
+		AccountModule.class,
 		BlogModule.class,
 		BriarClientModule.class,
 		ClientModule.class,
diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTest.java
index 5c8b0ca65a8b6c6ebe81a9dd749f6374eb67a517..c846c1c7326c66a6355d41e7603609a87f40625e 100644
--- a/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTest.java
@@ -100,6 +100,8 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
 
 	private ContactId setUp(SimplexMessagingIntegrationTestComponent device,
 			LocalAuthor local, Author remote, boolean alice) throws Exception {
+		// Create a database key
+		device.getAccountManager().setDatabaseKey(getSecretKey());
 		// Add an identity for the user
 		IdentityManager identityManager = device.getIdentityManager();
 		identityManager.registerLocalAuthor(local);
diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java
index 7dade1ed198f8223971bf55255ed03ecb2a79ff7..a5f9d9bc68ea780bad407c66f0ca566c26147e0a 100644
--- a/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java
+++ b/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java
@@ -1,5 +1,7 @@
 package org.briarproject.briar.messaging;
 
+import org.briarproject.bramble.account.AccountModule;
+import org.briarproject.bramble.api.account.AccountManager;
 import org.briarproject.bramble.api.contact.ContactManager;
 import org.briarproject.bramble.api.event.EventBus;
 import org.briarproject.bramble.api.identity.IdentityManager;
@@ -39,6 +41,7 @@ import dagger.Component;
 		TestDatabaseModule.class,
 		TestPluginConfigModule.class,
 		TestSecureRandomModule.class,
+		AccountModule.class,
 		BriarClientModule.class,
 		ClientModule.class,
 		ContactModule.class,
@@ -77,6 +80,8 @@ interface SimplexMessagingIntegrationTestComponent {
 
 	IdentityManager getIdentityManager();
 
+	AccountManager getAccountManager();
+
 	ContactManager getContactManager();
 
 	MessagingManager getMessagingManager();
diff --git a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java
index 9f2ecec4ad2c878bcd9ca65b62d14e5ed6a8e524..0e30fa8483d186aeb936bb3eb23f635a7040d895 100644
--- a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java
@@ -140,6 +140,9 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone
 		assertTrue(testDir.mkdirs());
 		createComponents();
 
+		c0.getAccountManager().setDatabaseKey(getSecretKey());
+		c1.getAccountManager().setDatabaseKey(getSecretKey());
+		c2.getAccountManager().setDatabaseKey(getSecretKey());
 		identityManager0 = c0.getIdentityManager();
 		identityManager1 = c1.getIdentityManager();
 		identityManager2 = c2.getIdentityManager();
diff --git a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTestComponent.java
index d55b06d00b2972fb8bfd2d81ac313bc3a4abcd46..70cc49fe00434d636029e03d6fd6e1b20f3b03ed 100644
--- a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTestComponent.java
+++ b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTestComponent.java
@@ -1,6 +1,7 @@
 package org.briarproject.briar.test;
 
 import org.briarproject.bramble.account.AccountModule;
+import org.briarproject.bramble.api.account.AccountManager;
 import org.briarproject.bramble.api.client.ClientHelper;
 import org.briarproject.bramble.api.contact.ContactManager;
 import org.briarproject.bramble.api.db.DatabaseComponent;
@@ -122,6 +123,8 @@ public interface BriarIntegrationTestComponent {
 
 	IdentityManager getIdentityManager();
 
+	AccountManager getAccountManager();
+
 	ClientHelper getClientHelper();
 
 	ContactManager getContactManager();