mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 21:59:54 +01:00
Store second copy of DB key in backup file.
This commit is contained in:
@@ -33,6 +33,7 @@ public class ConfigControllerImpl implements ConfigController {
|
|||||||
private static final String DB_KEY_BACKUP_FILENAME = "db.key.bak";
|
private static final String DB_KEY_BACKUP_FILENAME = "db.key.bak";
|
||||||
|
|
||||||
private final SharedPreferences briarPrefs;
|
private final SharedPreferences briarPrefs;
|
||||||
|
private final File dbKeyFile, dbKeyBackupFile;
|
||||||
protected final DatabaseConfig databaseConfig;
|
protected final DatabaseConfig databaseConfig;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -40,6 +41,9 @@ public class ConfigControllerImpl implements ConfigController {
|
|||||||
DatabaseConfig databaseConfig) {
|
DatabaseConfig databaseConfig) {
|
||||||
this.briarPrefs = briarPrefs;
|
this.briarPrefs = briarPrefs;
|
||||||
this.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
|
@Override
|
||||||
@@ -61,10 +65,10 @@ public class ConfigControllerImpl implements ConfigController {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private String getDatabaseKeyFromFile() {
|
private String getDatabaseKeyFromFile() {
|
||||||
String key = readDbKeyFromFile(getDbKeyFile());
|
String key = readDbKeyFromFile(dbKeyFile);
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
LOG.info("No database key in primary file");
|
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");
|
if (key == null) LOG.info("No database key in backup file");
|
||||||
else LOG.warning("Found database key in backup file");
|
else LOG.warning("Found database key in backup file");
|
||||||
} else {
|
} 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) {
|
private void migrateDatabaseKeyToFile(String key) {
|
||||||
if (storeEncryptedDatabaseKey(key)) {
|
if (storeEncryptedDatabaseKey(key)) {
|
||||||
if (briarPrefs.edit().remove(PREF_DB_KEY).commit())
|
if (briarPrefs.edit().remove(PREF_DB_KEY).commit())
|
||||||
@@ -114,39 +108,48 @@ public class ConfigControllerImpl implements ConfigController {
|
|||||||
@Override
|
@Override
|
||||||
public boolean storeEncryptedDatabaseKey(String hex) {
|
public boolean storeEncryptedDatabaseKey(String hex) {
|
||||||
LOG.info("Storing database key in file");
|
LOG.info("Storing database key in file");
|
||||||
File dbKey = getDbKeyFile();
|
|
||||||
File dbKeyBackup = getDbKeyBackupFile();
|
|
||||||
// Create the directory if necessary
|
// Create the directory if necessary
|
||||||
if (databaseConfig.getDatabaseKeyDirectory().mkdirs())
|
if (databaseConfig.getDatabaseKeyDirectory().mkdirs())
|
||||||
LOG.info("Created database key directory");
|
LOG.info("Created database key directory");
|
||||||
// If only the backup file exists, rename it so we don't overwrite it
|
// If only the backup file exists, rename it so we don't overwrite it
|
||||||
if (dbKeyBackup.exists() && !dbKey.exists()) {
|
if (dbKeyBackupFile.exists() && !dbKeyFile.exists()) {
|
||||||
if (dbKeyBackup.renameTo(dbKey)) LOG.info("Renamed old backup");
|
if (dbKeyBackupFile.renameTo(dbKeyFile))
|
||||||
|
LOG.info("Renamed old backup");
|
||||||
else LOG.warning("Failed to rename old backup");
|
else LOG.warning("Failed to rename old backup");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// Write to the backup file
|
// Write to the backup file
|
||||||
FileOutputStream out = new FileOutputStream(dbKeyBackup);
|
writeDbKeyToFile(hex, dbKeyBackupFile);
|
||||||
out.write(hex.getBytes("UTF-8"));
|
|
||||||
out.flush();
|
|
||||||
out.close();
|
|
||||||
LOG.info("Stored database key in backup file");
|
LOG.info("Stored database key in backup file");
|
||||||
// Delete the old primary file, if it exists
|
// Delete the old primary file, if it exists
|
||||||
if (dbKey.exists()) {
|
if (dbKeyFile.exists()) {
|
||||||
if (dbKey.delete()) LOG.info("Deleted primary file");
|
if (dbKeyFile.delete()) LOG.info("Deleted primary file");
|
||||||
else LOG.warning("Failed to delete primary file");
|
else LOG.warning("Failed to delete primary file");
|
||||||
}
|
}
|
||||||
// The backup file becomes the new primary
|
// The backup file becomes the new primary
|
||||||
boolean renamed = dbKeyBackup.renameTo(dbKey);
|
if (dbKeyBackupFile.renameTo(dbKeyFile)) {
|
||||||
if (renamed) LOG.info("Renamed backup file to primary");
|
LOG.info("Renamed backup file to primary");
|
||||||
else LOG.warning("Failed to rename backup file to primary");
|
} else {
|
||||||
return renamed;
|
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) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
return false;
|
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
|
@Override
|
||||||
public void deleteAccount(Context ctx) {
|
public void deleteAccount(Context ctx) {
|
||||||
LOG.info("Deleting account");
|
LOG.info("Deleting account");
|
||||||
|
|||||||
@@ -72,8 +72,7 @@ public class PasswordControllerImpl extends ConfigControllerImpl
|
|||||||
} else {
|
} else {
|
||||||
String hex =
|
String hex =
|
||||||
encryptDatabaseKey(new SecretKey(key), newPassword);
|
encryptDatabaseKey(new SecretKey(key), newPassword);
|
||||||
boolean stored = storeEncryptedDatabaseKey(hex);
|
resultHandler.onResult(storeEncryptedDatabaseKey(hex));
|
||||||
resultHandler.onResult(stored);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import static junit.framework.Assert.assertTrue;
|
|||||||
public class TestDatabaseKeyUtils {
|
public class TestDatabaseKeyUtils {
|
||||||
|
|
||||||
public static void storeDatabaseKey(File f, String hex) throws IOException {
|
public static void storeDatabaseKey(File f, String hex) throws IOException {
|
||||||
assertTrue(f.getParentFile().mkdirs());
|
f.getParentFile().mkdirs();
|
||||||
FileOutputStream out = new FileOutputStream(f);
|
FileOutputStream out = new FileOutputStream(f);
|
||||||
out.write(hex.getBytes("UTF-8"));
|
out.write(hex.getBytes("UTF-8"));
|
||||||
out.flush();
|
out.flush();
|
||||||
|
|||||||
@@ -62,8 +62,9 @@ public class ConfigControllerImplTest extends BrambleMockTestCase {
|
|||||||
assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey());
|
assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey());
|
||||||
|
|
||||||
assertTrue(keyFile.exists());
|
assertTrue(keyFile.exists());
|
||||||
assertFalse(keyBackupFile.exists());
|
assertTrue(keyBackupFile.exists());
|
||||||
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -165,8 +166,9 @@ public class ConfigControllerImplTest extends BrambleMockTestCase {
|
|||||||
assertTrue(c.storeEncryptedDatabaseKey(encryptedKeyHex));
|
assertTrue(c.storeEncryptedDatabaseKey(encryptedKeyHex));
|
||||||
|
|
||||||
assertTrue(keyFile.exists());
|
assertTrue(keyFile.exists());
|
||||||
assertFalse(keyBackupFile.exists());
|
assertTrue(keyBackupFile.exists());
|
||||||
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -191,8 +193,9 @@ public class ConfigControllerImplTest extends BrambleMockTestCase {
|
|||||||
assertTrue(c.storeEncryptedDatabaseKey(encryptedKeyHex));
|
assertTrue(c.storeEncryptedDatabaseKey(encryptedKeyHex));
|
||||||
|
|
||||||
assertTrue(keyFile.exists());
|
assertTrue(keyFile.exists());
|
||||||
assertFalse(keyBackupFile.exists());
|
assertTrue(keyBackupFile.exists());
|
||||||
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ public class PasswordControllerImplTest extends BrambleMockTestCase {
|
|||||||
assertFalse(keyBackupFile.exists());
|
assertFalse(keyBackupFile.exists());
|
||||||
|
|
||||||
storeDatabaseKey(keyFile, toHexString(oldEncryptedKey));
|
storeDatabaseKey(keyFile, toHexString(oldEncryptedKey));
|
||||||
|
storeDatabaseKey(keyBackupFile, toHexString(oldEncryptedKey));
|
||||||
|
|
||||||
PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs,
|
PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs,
|
||||||
databaseConfig, cryptoExecutor, crypto, estimator);
|
databaseConfig, cryptoExecutor, crypto, estimator);
|
||||||
@@ -76,8 +77,10 @@ public class PasswordControllerImplTest extends BrambleMockTestCase {
|
|||||||
assertTrue(capturedResult.get());
|
assertTrue(capturedResult.get());
|
||||||
|
|
||||||
assertTrue(keyFile.exists());
|
assertTrue(keyFile.exists());
|
||||||
assertFalse(keyBackupFile.exists());
|
assertTrue(keyBackupFile.exists());
|
||||||
assertEquals(toHexString(newEncryptedKey), loadDatabaseKey(keyFile));
|
assertEquals(toHexString(newEncryptedKey), loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(toHexString(newEncryptedKey),
|
||||||
|
loadDatabaseKey(keyBackupFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -98,6 +101,7 @@ public class PasswordControllerImplTest extends BrambleMockTestCase {
|
|||||||
assertFalse(keyBackupFile.exists());
|
assertFalse(keyBackupFile.exists());
|
||||||
|
|
||||||
storeDatabaseKey(keyFile, toHexString(oldEncryptedKey));
|
storeDatabaseKey(keyFile, toHexString(oldEncryptedKey));
|
||||||
|
storeDatabaseKey(keyBackupFile, toHexString(oldEncryptedKey));
|
||||||
|
|
||||||
PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs,
|
PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs,
|
||||||
databaseConfig, cryptoExecutor, crypto, estimator);
|
databaseConfig, cryptoExecutor, crypto, estimator);
|
||||||
@@ -107,8 +111,10 @@ public class PasswordControllerImplTest extends BrambleMockTestCase {
|
|||||||
assertFalse(capturedResult.get());
|
assertFalse(capturedResult.get());
|
||||||
|
|
||||||
assertTrue(keyFile.exists());
|
assertTrue(keyFile.exists());
|
||||||
assertFalse(keyBackupFile.exists());
|
assertTrue(keyBackupFile.exists());
|
||||||
assertEquals(toHexString(oldEncryptedKey), loadDatabaseKey(keyFile));
|
assertEquals(toHexString(oldEncryptedKey), loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(toHexString(oldEncryptedKey),
|
||||||
|
loadDatabaseKey(keyBackupFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|||||||
@@ -102,8 +102,9 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
|
|||||||
assertTrue(called.get());
|
assertTrue(called.get());
|
||||||
|
|
||||||
assertTrue(keyFile.exists());
|
assertTrue(keyFile.exists());
|
||||||
assertFalse(keyBackupFile.exists());
|
assertTrue(keyBackupFile.exists());
|
||||||
assertEquals(toHexString(encryptedKey), loadDatabaseKey(keyFile));
|
assertEquals(toHexString(encryptedKey), loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(toHexString(encryptedKey), loadDatabaseKey(keyBackupFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|||||||
Reference in New Issue
Block a user