Skip to content
Snippets Groups Projects
Verified Commit b9e60774 authored by akwizgran's avatar akwizgran
Browse files

Store second copy of DB key in backup file.

parent b410b8ef
No related branches found
No related tags found
No related merge requests found
......@@ -33,6 +33,7 @@ public class ConfigControllerImpl implements ConfigController {
private static final String DB_KEY_BACKUP_FILENAME = "db.key.bak";
private final SharedPreferences briarPrefs;
private final File dbKeyFile, dbKeyBackupFile;
protected final DatabaseConfig databaseConfig;
@Inject
......@@ -40,6 +41,9 @@ public class ConfigControllerImpl implements ConfigController {
DatabaseConfig databaseConfig) {
this.briarPrefs = briarPrefs;
this.databaseConfig = databaseConfig;
File keyDir = databaseConfig.getDatabaseKeyDirectory();
dbKeyFile = new File(keyDir, DB_KEY_FILENAME);
dbKeyBackupFile = new File(keyDir, DB_KEY_BACKUP_FILENAME);
}
@Override
......@@ -61,10 +65,10 @@ public class ConfigControllerImpl implements ConfigController {
@Nullable
private String getDatabaseKeyFromFile() {
String key = readDbKeyFromFile(getDbKeyFile());
String key = readDbKeyFromFile(dbKeyFile);
if (key == null) {
LOG.info("No database key in primary file");
key = readDbKeyFromFile(getDbKeyBackupFile());
key = readDbKeyFromFile(dbKeyBackupFile);
if (key == null) LOG.info("No database key in backup file");
else LOG.warning("Found database key in backup file");
} else {
......@@ -91,16 +95,6 @@ public class ConfigControllerImpl implements ConfigController {
}
}
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())
......@@ -114,39 +108,48 @@ public class ConfigControllerImpl implements ConfigController {
@Override
public boolean storeEncryptedDatabaseKey(String hex) {
LOG.info("Storing database key in file");
File dbKey = getDbKeyFile();
File dbKeyBackup = getDbKeyBackupFile();
// 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 (dbKeyBackup.exists() && !dbKey.exists()) {
if (dbKeyBackup.renameTo(dbKey)) LOG.info("Renamed old backup");
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
FileOutputStream out = new FileOutputStream(dbKeyBackup);
out.write(hex.getBytes("UTF-8"));
out.flush();
out.close();
writeDbKeyToFile(hex, dbKeyBackupFile);
LOG.info("Stored database key in backup file");
// Delete the old primary file, if it exists
if (dbKey.exists()) {
if (dbKey.delete()) LOG.info("Deleted primary file");
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
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;
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) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), 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();
}
@Override
public void deleteAccount(Context ctx) {
LOG.info("Deleting account");
......
......@@ -72,8 +72,7 @@ public class PasswordControllerImpl extends ConfigControllerImpl
} else {
String hex =
encryptDatabaseKey(new SecretKey(key), newPassword);
boolean stored = storeEncryptedDatabaseKey(hex);
resultHandler.onResult(stored);
resultHandler.onResult(storeEncryptedDatabaseKey(hex));
}
});
}
......
......@@ -17,7 +17,7 @@ import static junit.framework.Assert.assertTrue;
public class TestDatabaseKeyUtils {
public static void storeDatabaseKey(File f, String hex) throws IOException {
assertTrue(f.getParentFile().mkdirs());
f.getParentFile().mkdirs();
FileOutputStream out = new FileOutputStream(f);
out.write(hex.getBytes("UTF-8"));
out.flush();
......
......@@ -62,8 +62,9 @@ public class ConfigControllerImplTest extends BrambleMockTestCase {
assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey());
assertTrue(keyFile.exists());
assertFalse(keyBackupFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
}
@Test
......@@ -165,8 +166,9 @@ public class ConfigControllerImplTest extends BrambleMockTestCase {
assertTrue(c.storeEncryptedDatabaseKey(encryptedKeyHex));
assertTrue(keyFile.exists());
assertFalse(keyBackupFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
}
@Test
......@@ -191,8 +193,9 @@ public class ConfigControllerImplTest extends BrambleMockTestCase {
assertTrue(c.storeEncryptedDatabaseKey(encryptedKeyHex));
assertTrue(keyFile.exists());
assertFalse(keyBackupFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
}
@After
......
......@@ -67,6 +67,7 @@ public class PasswordControllerImplTest extends BrambleMockTestCase {
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyFile, toHexString(oldEncryptedKey));
storeDatabaseKey(keyBackupFile, toHexString(oldEncryptedKey));
PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs,
databaseConfig, cryptoExecutor, crypto, estimator);
......@@ -76,8 +77,10 @@ public class PasswordControllerImplTest extends BrambleMockTestCase {
assertTrue(capturedResult.get());
assertTrue(keyFile.exists());
assertFalse(keyBackupFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(toHexString(newEncryptedKey), loadDatabaseKey(keyFile));
assertEquals(toHexString(newEncryptedKey),
loadDatabaseKey(keyBackupFile));
}
@Test
......@@ -98,6 +101,7 @@ public class PasswordControllerImplTest extends BrambleMockTestCase {
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyFile, toHexString(oldEncryptedKey));
storeDatabaseKey(keyBackupFile, toHexString(oldEncryptedKey));
PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs,
databaseConfig, cryptoExecutor, crypto, estimator);
......@@ -107,8 +111,10 @@ public class PasswordControllerImplTest extends BrambleMockTestCase {
assertFalse(capturedResult.get());
assertTrue(keyFile.exists());
assertFalse(keyBackupFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(toHexString(oldEncryptedKey), loadDatabaseKey(keyFile));
assertEquals(toHexString(oldEncryptedKey),
loadDatabaseKey(keyBackupFile));
}
@After
......
......@@ -102,8 +102,9 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
assertTrue(called.get());
assertTrue(keyFile.exists());
assertFalse(keyBackupFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(toHexString(encryptedKey), loadDatabaseKey(keyFile));
assertEquals(toHexString(encryptedKey), loadDatabaseKey(keyBackupFile));
}
@After
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment