mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Store database key in a file rather than shared prefs.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ public interface ConfigController {
|
||||
@Nullable
|
||||
String getEncryptedDatabaseKey();
|
||||
|
||||
void storeEncryptedDatabaseKey(String hex);
|
||||
boolean storeEncryptedDatabaseKey(String hex);
|
||||
|
||||
void deleteAccount(Context ctx);
|
||||
|
||||
|
||||
@@ -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 = briarPrefs.getString(PREF_DB_KEY, null);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Got database key from preferences: " + (key != null));
|
||||
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 (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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user