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 6a8aa19aa651dfbd6f6f08875b3c0a1dff9e3cf9..0be85eba93a8ab16a915e5574cc4b0329ea8112b 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 @@ -14,6 +14,8 @@ public interface DatabaseConfig { File getDatabaseDirectory(); + File getDatabaseKeyDirectory(); + void setEncryptionKey(SecretKey key); @Nullable 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 d6ee0325f70ff3fc03923d98ccabf92a6092ecfa..a830795f3dd4d28fecb7876df4965d543de1fb5c 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 @@ -9,25 +9,31 @@ import java.io.File; @NotNullByDefault public class TestDatabaseConfig implements DatabaseConfig { - private final File dir; + private final File dbDir, keyDir; private final long maxSize; private volatile SecretKey key = new SecretKey(new byte[SecretKey.LENGTH]); - public TestDatabaseConfig(File dir, long maxSize) { - this.dir = dir; + public TestDatabaseConfig(File testDir, long maxSize) { + dbDir = new File(testDir, "db"); + keyDir = new File(testDir, "key"); this.maxSize = maxSize; } @Override public boolean databaseExists() { - if (!dir.isDirectory()) return false; - File[] files = dir.listFiles(); + if (!dbDir.isDirectory()) return false; + File[] files = dbDir.listFiles(); return files != null && files.length > 0; } @Override public File getDatabaseDirectory() { - return dir; + return dbDir; + } + + @Override + public File getDatabaseKeyDirectory() { + return keyDir; } @Override 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 2fe5df11ae0ae6273bcf28b2be1fbeb3089ddd28..e92a356ee42f675fb8777cd1c4e361629d82367f 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 @@ -17,31 +17,32 @@ class AndroidDatabaseConfig implements DatabaseConfig { private static final Logger LOG = Logger.getLogger(AndroidDatabaseConfig.class.getName()); - private final File dir; + private final File dbDir, keyDir; @Nullable private volatile SecretKey key = null; @Nullable private volatile String nickname = null; - AndroidDatabaseConfig(File dir) { - this.dir = dir; + AndroidDatabaseConfig(File dbDir, File keyDir) { + this.dbDir = dbDir; + this.keyDir = keyDir; } @Override public boolean databaseExists() { // FIXME should not run on UiThread #620 - if (!dir.isDirectory()) { + if (!dbDir.isDirectory()) { if (LOG.isLoggable(INFO)) - LOG.info(dir.getAbsolutePath() + " is not a directory"); + LOG.info(dbDir.getAbsolutePath() + " is not a directory"); return false; } - File[] files = dir.listFiles(); + File[] files = dbDir.listFiles(); if (LOG.isLoggable(INFO)) { if (files == null) { - LOG.info("Could not list files in " + dir.getAbsolutePath()); + LOG.info("Could not list files in " + dbDir.getAbsolutePath()); } else { - LOG.info("Files in " + dir.getAbsolutePath() + ":"); + LOG.info("Files in " + dbDir.getAbsolutePath() + ":"); for (File f : files) LOG.info(f.getName()); } LOG.info("Database exists: " + (files != null && files.length > 0)); @@ -51,10 +52,16 @@ class AndroidDatabaseConfig implements DatabaseConfig { @Override public File getDatabaseDirectory() { - File dir = this.dir; if (LOG.isLoggable(INFO)) - LOG.info("Database directory: " + dir.getAbsolutePath()); - return dir; + LOG.info("Database directory: " + dbDir.getAbsolutePath()); + return dbDir; + } + + @Override + public File getDatabaseKeyDirectory() { + if (LOG.isLoggable(INFO)) + LOG.info("Database key directory: " + keyDir.getAbsolutePath()); + return keyDir; } @Override diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java index f8fdf0dfa23e4555c83985935dbaf1ecf1bace06..ed954e2414e1544cf18df754b7129f608c247893 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java @@ -87,11 +87,13 @@ public class AppModule { //FIXME: StrictMode StrictMode.ThreadPolicy tp = StrictMode.allowThreadDiskReads(); StrictMode.allowThreadDiskWrites(); - File dir = app.getApplicationContext().getDir("db", MODE_PRIVATE); + File dbDir = app.getApplicationContext().getDir("db", MODE_PRIVATE); + File keyDir = app.getApplicationContext().getDir("key", MODE_PRIVATE); StrictMode.setThreadPolicy(tp); @MethodsNotNullByDefault @ParametersNotNullByDefault - DatabaseConfig databaseConfig = new AndroidDatabaseConfig(dir); + DatabaseConfig databaseConfig = + new AndroidDatabaseConfig(dbDir, keyDir); return databaseConfig; } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigController.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigController.java index 07b32b0e2f53bf2bd6f65b6aa165aff1c39c1411..e19452a9ce134d3baedbfe0c8478726ee90da922 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigController.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigController.java @@ -12,7 +12,7 @@ public interface ConfigController { @Nullable String getEncryptedDatabaseKey(); - void storeEncryptedDatabaseKey(String hex); + boolean storeEncryptedDatabaseKey(String hex); void deleteAccount(Context ctx); 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 b1a4168129798e5a9a4c5f48200f5842b444ab74..937755ea0af733b987ae809e320c8d94e187955b 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 @@ -1,6 +1,5 @@ package org.briarproject.briar.android.controller; -import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; import android.support.v7.preference.PreferenceManager; @@ -9,12 +8,19 @@ 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.INFO; +import static java.util.logging.Level.WARNING; @NotNullByDefault public class ConfigControllerImpl implements ConfigController { @@ -23,6 +29,8 @@ 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; protected final DatabaseConfig databaseConfig; @@ -37,17 +45,101 @@ public class ConfigControllerImpl implements ConfigController { @Override @Nullable public String getEncryptedDatabaseKey() { + String key = getDatabaseKeyFromPreferences(); + if (key == null) key = getDatabaseKeyFromFile(); + else migrateDatabaseKeyToFile(key); + return key; + } + + @Nullable + private String getDatabaseKeyFromPreferences() { String key = briarPrefs.getString(PREF_DB_KEY, null); - if (LOG.isLoggable(INFO)) - LOG.info("Got database key from preferences: " + (key != null)); + if (key == null) LOG.info("No database key in preferences"); + else LOG.info("Found database key in preferences"); return key; } + @Nullable + private String getDatabaseKeyFromFile() { + String key = readDbKeyFromFile(getDbKeyFile()); + if (key == null) { + LOG.info("No database key in primary file"); + key = readDbKeyFromFile(getDbKeyBackupFile()); + 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) { + if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + return null; + } + } + + private File getDbKeyFile() { + return new File(databaseConfig.getDatabaseKeyDirectory(), + DB_KEY_FILENAME); + } + + private File getDbKeyBackupFile() { + return new File(databaseConfig.getDatabaseKeyDirectory(), + DB_KEY_BACKUP_FILENAME); + } + + private void migrateDatabaseKeyToFile(String key) { + if (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"); + } else { + LOG.warning("Database key not migrated to file"); + } + } + @Override - @SuppressLint("ApplySharedPref") - public void storeEncryptedDatabaseKey(String hex) { - LOG.info("Storing database key in preferences"); - briarPrefs.edit().putString(PREF_DB_KEY, hex).commit(); + public boolean storeEncryptedDatabaseKey(String hex) { + LOG.info("Storing database key in file"); + File dbKey = getDbKeyFile(); + File dbKeyBackup = getDbKeyBackupFile(); + try { + // Create the directory if necessary + if (databaseConfig.getDatabaseKeyDirectory().mkdirs()) + LOG.info("Created database key directory"); + // Write to the backup file + FileOutputStream out = new FileOutputStream(dbKeyBackup); + out.write(hex.getBytes("UTF-8")); + out.flush(); + out.close(); + LOG.info("Stored database key in backup file"); + // Delete the old key file, if it exists + if (dbKey.exists()) { + if (dbKey.delete()) LOG.info("Deleted primary file"); + else LOG.warning("Failed to delete primary file"); + } + // The backup file becomes the new key file + boolean renamed = dbKeyBackup.renameTo(dbKey); + if (renamed) LOG.info("Renamed backup file to primary"); + else LOG.warning("Failed to rename backup file to primary"); + return renamed; + } catch (IOException e) { + if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + return false; + } } @Override @@ -73,5 +165,4 @@ public class ConfigControllerImpl implements ConfigController { if (LOG.isLoggable(INFO)) LOG.info("Signed in: " + signedIn); return signedIn; } - } 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 d2c2e54f50e1e4048faa8a184efd0ffd0e2c9dec..1ecdef55b99ace7ad1ee33e4fe4bbf380e9a129c 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 @@ -72,8 +72,8 @@ public class PasswordControllerImpl extends ConfigControllerImpl } else { String hex = encryptDatabaseKey(new SecretKey(key), newPassword); - storeEncryptedDatabaseKey(hex); - resultHandler.onResult(true); + boolean stored = storeEncryptedDatabaseKey(hex); + resultHandler.onResult(stored); } }); } 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 new file mode 100644 index 0000000000000000000000000000000000000000..70d375be215025e0c1cb8d0ecaf0e8bbe151d78e --- /dev/null +++ b/briar-android/src/test/java/org/briarproject/briar/android/TestDatabaseKeyUtils.java @@ -0,0 +1,35 @@ +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 { + assertTrue(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/login/PasswordControllerImplTest.java b/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordControllerImplTest.java index 9807c09c39f5811a37fe3d699a51bb7fc904bb6d..27a15af86a94c56b4bb348ed1b23e104c2c89813 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 @@ -8,14 +8,23 @@ 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 { @@ -26,62 +35,84 @@ public class PasswordControllerImplTest extends BrambleMockTestCase { private final CryptoComponent crypto = context.mock(CryptoComponent.class); private final PasswordStrengthEstimator estimator = context.mock(PasswordStrengthEstimator.class); - private final SharedPreferences.Editor editor = - context.mock(SharedPreferences.Editor.class); private final Executor cryptoExecutor = new ImmediateExecutor(); private final String oldPassword = "some.old.pass"; private final String newPassword = "some.new.pass"; - private final String oldEncryptedHex = "010203"; - private final String newEncryptedHex = "020304"; - private final byte[] oldEncryptedBytes = new byte[] {1, 2, 3}; - private final byte[] newEncryptedBytes = new byte[] {2, 3, 4}; - private final byte[] keyBytes = getSecretKey().getBytes(); + 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"); @Test - public void testChangePasswordReturnsTrue() { + public void testChangePasswordReturnsTrue() throws Exception { context.checking(new Expectations() {{ // Look up the encrypted DB key oneOf(briarPrefs).getString("key", null); - will(returnValue(oldEncryptedHex)); + will(returnValue(null)); + allowing(databaseConfig).getDatabaseKeyDirectory(); + will(returnValue(keyDir)); // Decrypt and re-encrypt the key - oneOf(crypto).decryptWithPassword(oldEncryptedBytes, oldPassword); - will(returnValue(keyBytes)); - oneOf(crypto).encryptWithPassword(keyBytes, newPassword); - will(returnValue(newEncryptedBytes)); - // Store the re-encrypted key - oneOf(briarPrefs).edit(); - will(returnValue(editor)); - oneOf(editor).putString("key", newEncryptedHex); - will(returnValue(editor)); - oneOf(editor).commit(); + oneOf(crypto).decryptWithPassword(oldEncryptedKey, oldPassword); + will(returnValue(key)); + oneOf(crypto).encryptWithPassword(key, newPassword); + will(returnValue(newEncryptedKey)); }}); + assertFalse(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + + storeDatabaseKey(keyFile, toHexString(oldEncryptedKey)); + PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs, databaseConfig, cryptoExecutor, crypto, estimator); AtomicBoolean capturedResult = new AtomicBoolean(false); p.changePassword(oldPassword, newPassword, capturedResult::set); assertTrue(capturedResult.get()); + + assertTrue(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + assertEquals(toHexString(newEncryptedKey), loadDatabaseKey(keyFile)); } @Test - public void testChangePasswordReturnsFalseIfOldPasswordIsWrong() { + public void testChangePasswordReturnsFalseIfOldPasswordIsWrong() + throws Exception { context.checking(new Expectations() {{ // Look up the encrypted DB key oneOf(briarPrefs).getString("key", null); - will(returnValue(oldEncryptedHex)); + will(returnValue(null)); + allowing(databaseConfig).getDatabaseKeyDirectory(); + will(returnValue(keyDir)); // Try to decrypt the key - the password is wrong - oneOf(crypto).decryptWithPassword(oldEncryptedBytes, oldPassword); + oneOf(crypto).decryptWithPassword(oldEncryptedKey, oldPassword); will(returnValue(null)); }}); + assertFalse(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + + storeDatabaseKey(keyFile, toHexString(oldEncryptedKey)); + PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs, databaseConfig, cryptoExecutor, crypto, estimator); AtomicBoolean capturedResult = new AtomicBoolean(true); p.changePassword(oldPassword, newPassword, capturedResult::set); assertFalse(capturedResult.get()); + + assertTrue(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + assertEquals(toHexString(oldEncryptedKey), loadDatabaseKey(keyFile)); + } + + @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 1aa79e74f80fbda9a087384781e45fd9f2e50a2b..21568344be49972ea8f44a76f558e3282b55f580 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 @@ -9,7 +9,6 @@ import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.ImmediateExecutor; -import org.briarproject.bramble.test.TestUtils; import org.jmock.Expectations; import org.jmock.lib.legacy.ClassImposteriser; import org.junit.After; @@ -19,10 +18,17 @@ 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.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 { @@ -33,18 +39,18 @@ public class SetupControllerImplTest extends BrambleMockTestCase { private final CryptoComponent crypto = context.mock(CryptoComponent.class); private final PasswordStrengthEstimator estimator = context.mock(PasswordStrengthEstimator.class); - private final SharedPreferences.Editor editor = - context.mock(SharedPreferences.Editor.class); private final SetupActivity setupActivity; private final Executor cryptoExecutor = new ImmediateExecutor(); private final String authorName = getRandomString(MAX_AUTHOR_NAME_LENGTH); private final String password = "some.strong.pass"; - private final String encryptedHex = "010203"; - private final byte[] encryptedBytes = new byte[] {1, 2, 3}; + private final byte[] encryptedKey = getRandomBytes(123); private final SecretKey key = getSecretKey(); - private final File testDir = TestUtils.getTestDirectory(); + 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); @@ -53,7 +59,7 @@ public class SetupControllerImplTest extends BrambleMockTestCase { @Test @SuppressWarnings("ResultOfMethodCallIgnored") - public void testCreateAccount() { + public void testCreateAccount() throws Exception { context.checking(new Expectations() {{ // Allow the contents of the data directory to be logged allowing(setupActivity).getApplicationInfo(); @@ -76,15 +82,15 @@ public class SetupControllerImplTest extends BrambleMockTestCase { oneOf(databaseConfig).setEncryptionKey(key); // Encrypt the key with the password oneOf(crypto).encryptWithPassword(key.getBytes(), password); - will(returnValue(encryptedBytes)); + will(returnValue(encryptedKey)); // Store the encrypted key - oneOf(briarPrefs).edit(); - will(returnValue(editor)); - oneOf(editor).putString("key", encryptedHex); - will(returnValue(editor)); - oneOf(editor).commit(); + allowing(databaseConfig).getDatabaseKeyDirectory(); + will(returnValue(keyDir)); }}); + assertFalse(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + SetupControllerImpl s = new SetupControllerImpl(briarPrefs, databaseConfig, cryptoExecutor, crypto, estimator); s.setSetupActivity(setupActivity); @@ -94,10 +100,14 @@ public class SetupControllerImplTest extends BrambleMockTestCase { s.setPassword(password); s.createAccount(result -> called.set(true)); assertTrue(called.get()); + + assertTrue(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + assertEquals(toHexString(encryptedKey), loadDatabaseKey(keyFile)); } @After public void tearDown() { - TestUtils.deleteTestDirectory(testDir); + deleteTestDirectory(testDir); } }