Move identity creation into AccountManager.

This commit is contained in:
akwizgran
2018-08-02 09:51:17 +01:00
parent 2a0ecc3f80
commit c1789a8e52
8 changed files with 53 additions and 41 deletions

View File

@@ -8,6 +8,7 @@ import android.preference.PreferenceManager;
import org.briarproject.bramble.api.account.AccountManager; import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.util.IoUtils; import org.briarproject.bramble.util.IoUtils;
import java.io.File; import java.io.File;
@@ -29,8 +30,9 @@ class AndroidAccountManager extends AccountManagerImpl
@Inject @Inject
AndroidAccountManager(DatabaseConfig databaseConfig, AndroidAccountManager(DatabaseConfig databaseConfig,
CryptoComponent crypto, SharedPreferences prefs, Application app) { CryptoComponent crypto, IdentityManager identityManager,
super(databaseConfig, crypto); SharedPreferences prefs, Application app) {
super(databaseConfig, crypto, identityManager);
this.prefs = prefs; this.prefs = prefs;
appContext = app.getApplicationContext(); appContext = app.getApplicationContext();
} }

View File

@@ -6,6 +6,7 @@ import android.content.pm.ApplicationInfo;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.lib.legacy.ClassImposteriser; import org.jmock.lib.legacy.ClassImposteriser;
@@ -32,6 +33,8 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
private final DatabaseConfig databaseConfig = private final DatabaseConfig databaseConfig =
context.mock(DatabaseConfig.class); context.mock(DatabaseConfig.class);
private final CryptoComponent crypto = context.mock(CryptoComponent.class); private final CryptoComponent crypto = context.mock(CryptoComponent.class);
private final IdentityManager identityManager =
context.mock(IdentityManager.class);
private final SharedPreferences.Editor private final SharedPreferences.Editor
editor = context.mock(SharedPreferences.Editor.class); editor = context.mock(SharedPreferences.Editor.class);
private final Application app; private final Application app;
@@ -64,7 +67,7 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
will(returnValue(app)); will(returnValue(app));
}}); }});
accountManager = new AndroidAccountManager(databaseConfig, crypto, accountManager = new AndroidAccountManager(databaseConfig, crypto,
prefs, app) { identityManager, prefs, app) {
@Override @Override
SharedPreferences getDefaultSharedPreferences() { SharedPreferences getDefaultSharedPreferences() {
return defaultPrefs; return defaultPrefs;

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.api.account; package org.briarproject.bramble.api.account;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -10,17 +11,18 @@ public interface AccountManager {
/** /**
* Returns true if the manager has the database key. This will be false * Returns true if the manager has the database key. This will be false
* before {@link #createAccount(String)} or {@link #signIn(String)} has * before {@link #createAccount(String, String)} or {@link #signIn(String)}
* been called, and true after {@link #createAccount(String)} or * has been called, and true after {@link #createAccount(String, String)}
* {@link #signIn(String)} has returned true, until the process exits. * or {@link #signIn(String)} has returned true, until the process exits.
*/ */
boolean hasDatabaseKey(); boolean hasDatabaseKey();
/** /**
* Returns the database key if the manager has it. This will be null * Returns the database key if the manager has it. This will be null
* before {@link #createAccount(String)} or {@link #signIn(String)} has * before {@link #createAccount(String, String)} or {@link #signIn(String)}
* been called, and non-null after {@link #createAccount(String)} or * has been called, and non-null after
* {@link #signIn(String)} has returned true, until the process exits. * {@link #createAccount(String, String)} or {@link #signIn(String)} has
* returned true, until the process exits.
*/ */
@Nullable @Nullable
SecretKey getDatabaseKey(); SecretKey getDatabaseKey();
@@ -32,12 +34,15 @@ public interface AccountManager {
boolean accountExists(); boolean accountExists();
/** /**
* Creates a database key, encrypts it with the given password and stores * Creates an identity with the given name and registers it with the
* it on disk. This method does not create the database directory, so * {@link IdentityManager}. Creates a database key, encrypts it with the
* given password and stores it on disk.
* <p/>
* This method does not create the database directory, so
* {@link #accountExists()} will continue to return false until the * {@link #accountExists()} will continue to return false until the
* database directory is created. * database directory is created.
*/ */
boolean createAccount(String password); boolean createAccount(String name, String password);
/** /**
* Deletes all account state from disk. {@link #accountExists()} will * Deletes all account state from disk. {@link #accountExists()} will

View File

@@ -4,6 +4,8 @@ import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.util.IoUtils; import org.briarproject.bramble.util.IoUtils;
@@ -36,6 +38,7 @@ class AccountManagerImpl implements AccountManager {
private final DatabaseConfig databaseConfig; private final DatabaseConfig databaseConfig;
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final IdentityManager identityManager;
private final File dbKeyFile, dbKeyBackupFile; private final File dbKeyFile, dbKeyBackupFile;
final Object stateChangeLock = new Object(); final Object stateChangeLock = new Object();
@@ -44,9 +47,11 @@ class AccountManagerImpl implements AccountManager {
private volatile SecretKey databaseKey = null; private volatile SecretKey databaseKey = null;
@Inject @Inject
AccountManagerImpl(DatabaseConfig databaseConfig, CryptoComponent crypto) { AccountManagerImpl(DatabaseConfig databaseConfig, CryptoComponent crypto,
IdentityManager identityManager) {
this.databaseConfig = databaseConfig; this.databaseConfig = databaseConfig;
this.crypto = crypto; this.crypto = crypto;
this.identityManager = identityManager;
File keyDir = databaseConfig.getDatabaseKeyDirectory(); File keyDir = databaseConfig.getDatabaseKeyDirectory();
dbKeyFile = new File(keyDir, DB_KEY_FILENAME); dbKeyFile = new File(keyDir, DB_KEY_FILENAME);
dbKeyBackupFile = new File(keyDir, DB_KEY_BACKUP_FILENAME); dbKeyBackupFile = new File(keyDir, DB_KEY_BACKUP_FILENAME);
@@ -152,8 +157,10 @@ class AccountManagerImpl implements AccountManager {
} }
@Override @Override
public boolean createAccount(String password) { public boolean createAccount(String name, String password) {
synchronized (stateChangeLock) { synchronized (stateChangeLock) {
LocalAuthor localAuthor = identityManager.createLocalAuthor(name);
identityManager.registerLocalAuthor(localAuthor);
SecretKey key = crypto.generateSecretKey(); SecretKey key = crypto.generateSecretKey();
if (!encryptAndStoreDatabaseKey(key, password)) return false; if (!encryptAndStoreDatabaseKey(key, password)) return false;
databaseKey = key; databaseKey = key;

View File

@@ -3,6 +3,8 @@ package org.briarproject.bramble.account;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.junit.After; import org.junit.After;
@@ -22,6 +24,7 @@ import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.assertTrue;
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; 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.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory; import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
@@ -36,12 +39,16 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
private final DatabaseConfig databaseConfig = private final DatabaseConfig databaseConfig =
context.mock(DatabaseConfig.class); context.mock(DatabaseConfig.class);
private final CryptoComponent crypto = context.mock(CryptoComponent.class); private final CryptoComponent crypto = context.mock(CryptoComponent.class);
private final IdentityManager identityManager =
context.mock(IdentityManager.class);
private final SecretKey key = getSecretKey(); private final SecretKey key = getSecretKey();
private final byte[] encryptedKey = getRandomBytes(123); private final byte[] encryptedKey = getRandomBytes(123);
private final String encryptedKeyHex = toHexString(encryptedKey); private final String encryptedKeyHex = toHexString(encryptedKey);
private final byte[] newEncryptedKey = getRandomBytes(123); private final byte[] newEncryptedKey = getRandomBytes(123);
private final String newEncryptedKeyHex = toHexString(newEncryptedKey); private final String newEncryptedKeyHex = toHexString(newEncryptedKey);
private final LocalAuthor localAuthor = getLocalAuthor();
private final String authorName = localAuthor.getName();
private final String password = getRandomString(10); private final String password = getRandomString(10);
private final String newPassword = getRandomString(10); private final String newPassword = getRandomString(10);
private final File testDir = getTestDirectory(); private final File testDir = getTestDirectory();
@@ -61,7 +68,8 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
will(returnValue(keyDir)); will(returnValue(keyDir));
}}); }});
accountManager = new AccountManagerImpl(databaseConfig, crypto); accountManager =
new AccountManagerImpl(databaseConfig, crypto, identityManager);
assertFalse(keyFile.exists()); assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists()); assertFalse(keyBackupFile.exists());
@@ -243,6 +251,9 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
@Test @Test
public void testCreateAccountStoresDbKey() throws Exception { public void testCreateAccountStoresDbKey() throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(identityManager).createLocalAuthor(authorName);
will(returnValue(localAuthor));
oneOf(identityManager).registerLocalAuthor(localAuthor);
oneOf(crypto).generateSecretKey(); oneOf(crypto).generateSecretKey();
will(returnValue(key)); will(returnValue(key));
oneOf(crypto).encryptWithPassword(key.getBytes(), password); oneOf(crypto).encryptWithPassword(key.getBytes(), password);
@@ -251,7 +262,7 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
assertFalse(accountManager.hasDatabaseKey()); assertFalse(accountManager.hasDatabaseKey());
assertTrue(accountManager.createAccount(password)); assertTrue(accountManager.createAccount(authorName, password));
assertTrue(accountManager.hasDatabaseKey()); assertTrue(accountManager.hasDatabaseKey());
SecretKey dbKey = accountManager.getDatabaseKey(); SecretKey dbKey = accountManager.getDatabaseKey();

View File

@@ -5,6 +5,7 @@ import android.content.SharedPreferences;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.Localizer; import org.briarproject.briar.android.Localizer;
import org.briarproject.briar.android.util.UiUtils; import org.briarproject.briar.android.util.UiUtils;
@@ -15,8 +16,9 @@ class BriarAccountManager extends AndroidAccountManager {
@Inject @Inject
BriarAccountManager(DatabaseConfig databaseConfig, CryptoComponent crypto, BriarAccountManager(DatabaseConfig databaseConfig, CryptoComponent crypto,
SharedPreferences prefs, Application app) { IdentityManager identityManager, SharedPreferences prefs,
super(databaseConfig, crypto, prefs, app); Application app) {
super(databaseConfig, crypto, identityManager, prefs, app);
} }
@Override @Override

View File

@@ -4,8 +4,6 @@ import android.support.annotation.Nullable;
import org.briarproject.bramble.api.account.AccountManager; import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator; import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.android.controller.handler.ResultHandler; import org.briarproject.briar.android.controller.handler.ResultHandler;
@@ -23,18 +21,14 @@ public class SetupControllerImpl extends PasswordControllerImpl
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(SetupControllerImpl.class.getName()); Logger.getLogger(SetupControllerImpl.class.getName());
private final IdentityManager identityManager;
@Nullable @Nullable
private volatile SetupActivity setupActivity; private volatile SetupActivity setupActivity;
@Inject @Inject
SetupControllerImpl(AccountManager accountManager, SetupControllerImpl(AccountManager accountManager,
@IoExecutor Executor ioExecutor, @IoExecutor Executor ioExecutor,
PasswordStrengthEstimator strengthEstimator, PasswordStrengthEstimator strengthEstimator) {
IdentityManager identityManager) {
super(accountManager, ioExecutor, strengthEstimator); super(accountManager, ioExecutor, strengthEstimator);
this.identityManager = identityManager;
} }
@Override @Override
@@ -104,10 +98,8 @@ public class SetupControllerImpl extends PasswordControllerImpl
if (password == null) throw new IllegalStateException(); if (password == null) throw new IllegalStateException();
ioExecutor.execute(() -> { ioExecutor.execute(() -> {
LOG.info("Creating account"); LOG.info("Creating account");
LocalAuthor localAuthor = resultHandler.onResult(accountManager.createAccount(authorName,
identityManager.createLocalAuthor(authorName); password));
identityManager.registerLocalAuthor(localAuthor);
resultHandler.onResult(accountManager.createAccount(password));
}); });
} }
} }

View File

@@ -2,8 +2,6 @@ package org.briarproject.briar.android.login;
import org.briarproject.bramble.api.account.AccountManager; import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator; import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.ImmediateExecutor; import org.briarproject.bramble.test.ImmediateExecutor;
import org.jmock.Expectations; import org.jmock.Expectations;
@@ -15,7 +13,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.assertTrue;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.briarproject.bramble.util.StringUtils.getRandomString;
public class SetupControllerImplTest extends BrambleMockTestCase { public class SetupControllerImplTest extends BrambleMockTestCase {
@@ -24,15 +21,12 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
context.mock(AccountManager.class); context.mock(AccountManager.class);
private final PasswordStrengthEstimator estimator = private final PasswordStrengthEstimator estimator =
context.mock(PasswordStrengthEstimator.class); context.mock(PasswordStrengthEstimator.class);
private final IdentityManager identityManager =
context.mock(IdentityManager.class);
private final SetupActivity setupActivity; private final SetupActivity setupActivity;
private final Executor ioExecutor = new ImmediateExecutor(); private final Executor ioExecutor = new ImmediateExecutor();
private final String authorName = getRandomString(MAX_AUTHOR_NAME_LENGTH); private final String authorName = getRandomString(MAX_AUTHOR_NAME_LENGTH);
private final String password = getRandomString(10); private final String password = getRandomString(10);
private final LocalAuthor localAuthor = getLocalAuthor();
public SetupControllerImplTest() { public SetupControllerImplTest() {
context.setImposteriser(ClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
@@ -51,17 +45,13 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
will(returnValue(authorName)); will(returnValue(authorName));
oneOf(setupActivity).getPassword(); oneOf(setupActivity).getPassword();
will(returnValue(password)); will(returnValue(password));
// Create and register the local author
oneOf(identityManager).createLocalAuthor(authorName);
will(returnValue(localAuthor));
oneOf(identityManager).registerLocalAuthor(localAuthor);
// Create the account // Create the account
oneOf(accountManager).createAccount(password); oneOf(accountManager).createAccount(authorName, password);
will(returnValue(true)); will(returnValue(true));
}}); }});
SetupControllerImpl s = new SetupControllerImpl(accountManager, SetupControllerImpl s = new SetupControllerImpl(accountManager,
ioExecutor, estimator, identityManager); ioExecutor, estimator);
s.setSetupActivity(setupActivity); s.setSetupActivity(setupActivity);
AtomicBoolean called = new AtomicBoolean(false); AtomicBoolean called = new AtomicBoolean(false);