From a9de12520da337d47c703969b339afca0a7b824b Mon Sep 17 00:00:00 2001
From: Ernir Erlingsson <ernir@ymirmobile.com>
Date: Fri, 1 Apr 2016 14:34:41 +0200
Subject: [PATCH] phase 2: helpers and app bus

---
 .../briarproject/android/ActivityModule.java  |  25 ++--
 .../android/AndroidComponent.java             |   3 +
 .../briarproject/android/BaseActivity.java    |  50 ++++----
 .../android/NavDrawerActivity.java            |   6 +-
 .../android/PasswordActivity.java             |  87 +++++--------
 .../briarproject/android/SetupActivity.java   |  62 +++------
 .../android/SplashScreenActivity.java         |  12 +-
 .../briarproject/android/event/AppBus.java    |   6 +
 .../briarproject/android/event/AppBusImp.java |  25 ++++
 .../android/event/ErrorEvent.java             |  10 ++
 .../event/LocalAuthorCreatedEvent.java        |  16 +++
 .../android/event/PasswordValidateEvent.java  |  16 +++
 .../android/helper/ConfigHelper.java          |   9 ++
 .../android/helper/ConfigHelperImp.java       |  41 ++++++
 .../android/helper/PasswordHelper.java        |   5 +
 .../android/helper/PasswordHelperImp.java     |  70 +++++++++++
 .../android/helper/SetupHelper.java           |   6 +
 .../android/helper/SetupHelperImp.java        | 119 ++++++++++++++++++
 .../android/panic/PanicResponderActivity.java |  11 +-
 .../briarproject/android/sdk/BriarHelper.java |   4 -
 .../android/sdk/BriarHelperImp.java           |  13 --
 21 files changed, 430 insertions(+), 166 deletions(-)
 create mode 100644 briar-android/src/org/briarproject/android/event/AppBus.java
 create mode 100644 briar-android/src/org/briarproject/android/event/AppBusImp.java
 create mode 100644 briar-android/src/org/briarproject/android/event/ErrorEvent.java
 create mode 100644 briar-android/src/org/briarproject/android/event/LocalAuthorCreatedEvent.java
 create mode 100644 briar-android/src/org/briarproject/android/event/PasswordValidateEvent.java
 create mode 100644 briar-android/src/org/briarproject/android/helper/ConfigHelper.java
 create mode 100644 briar-android/src/org/briarproject/android/helper/ConfigHelperImp.java
 create mode 100644 briar-android/src/org/briarproject/android/helper/PasswordHelper.java
 create mode 100644 briar-android/src/org/briarproject/android/helper/PasswordHelperImp.java
 create mode 100644 briar-android/src/org/briarproject/android/helper/SetupHelper.java
 create mode 100644 briar-android/src/org/briarproject/android/helper/SetupHelperImp.java
 delete mode 100644 briar-android/src/org/briarproject/android/sdk/BriarHelper.java
 delete mode 100644 briar-android/src/org/briarproject/android/sdk/BriarHelperImp.java

diff --git a/briar-android/src/org/briarproject/android/ActivityModule.java b/briar-android/src/org/briarproject/android/ActivityModule.java
index 8c1989a711..3ae6e004c3 100644
--- a/briar-android/src/org/briarproject/android/ActivityModule.java
+++ b/briar-android/src/org/briarproject/android/ActivityModule.java
@@ -4,15 +4,16 @@ import android.app.Activity;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.os.Bundle;
-import android.support.v4.app.Fragment;
 
 import org.briarproject.android.contact.ContactListFragment;
 import org.briarproject.android.forum.ForumListFragment;
 import org.briarproject.android.fragment.BaseFragment;
-import org.briarproject.android.sdk.BriarHelper;
-import org.briarproject.android.sdk.BriarHelperImp;
-
-import java.util.logging.Logger;
+import org.briarproject.android.helper.PasswordHelper;
+import org.briarproject.android.helper.PasswordHelperImp;
+import org.briarproject.android.helper.SetupHelper;
+import org.briarproject.android.helper.SetupHelperImp;
+import org.briarproject.android.helper.ConfigHelper;
+import org.briarproject.android.helper.ConfigHelperImp;
 
 import javax.inject.Named;
 
@@ -36,13 +37,14 @@ public class ActivityModule {
 
 	@ActivityScope
 	@Provides
-	BriarHelper provideBriarHelper(BriarHelperImp briarHelperImp) {
-		return briarHelperImp;
+	SetupHelper provideSetupHelper(SetupHelperImp setupHelperImp) {
+		return setupHelperImp;
 	}
 
 	@ActivityScope
-	Logger provideLogger(Activity activity) {
-		return Logger.getLogger(activity.getClass().getName());
+	@Provides
+	ConfigHelper provideConfigHelper(ConfigHelperImp configHelperImp) {
+		return configHelperImp;
 	}
 
 	@ActivityScope
@@ -51,6 +53,11 @@ public class ActivityModule {
 		return activity.getSharedPreferences("db", Context.MODE_PRIVATE);
 	}
 
+	@ActivityScope
+	@Provides
+	PasswordHelper providePasswordHelper(PasswordHelperImp passwordHelperImp) {
+		return passwordHelperImp;
+	}
 
 	@Provides
 	@Named("ForumListFragment")
diff --git a/briar-android/src/org/briarproject/android/AndroidComponent.java b/briar-android/src/org/briarproject/android/AndroidComponent.java
index 8766c4324e..02469114f4 100644
--- a/briar-android/src/org/briarproject/android/AndroidComponent.java
+++ b/briar-android/src/org/briarproject/android/AndroidComponent.java
@@ -6,6 +6,7 @@ import org.briarproject.android.api.AndroidNotificationManager;
 import org.briarproject.android.api.ReferenceManager;
 import org.briarproject.android.contact.ContactListFragment;
 import org.briarproject.android.contact.ConversationActivity;
+import org.briarproject.android.event.AppBus;
 import org.briarproject.android.forum.AvailableForumsActivity;
 import org.briarproject.android.forum.ContactSelectorFragment;
 import org.briarproject.android.forum.CreateForumActivity;
@@ -50,6 +51,7 @@ import org.briarproject.system.AndroidSystemModule;
 
 import java.util.concurrent.Executor;
 
+import javax.inject.Named;
 import javax.inject.Singleton;
 
 import dagger.Component;
@@ -74,6 +76,7 @@ public interface AndroidComponent extends CoreEagerSingletons {
 	IdentityManager identityManager();
 	PluginManager pluginManager();
 	EventBus eventBus();
+	AppBus appEventBus();
 	InvitationTaskFactory invitationTaskFactory();
 	AndroidNotificationManager androidNotificationManager();
 	ConnectionRegistry connectionRegistry();
diff --git a/briar-android/src/org/briarproject/android/BaseActivity.java b/briar-android/src/org/briarproject/android/BaseActivity.java
index 9e602c9e55..213088daa8 100644
--- a/briar-android/src/org/briarproject/android/BaseActivity.java
+++ b/briar-android/src/org/briarproject/android/BaseActivity.java
@@ -1,29 +1,30 @@
 package org.briarproject.android;
 
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.res.Configuration;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.support.annotation.CallSuper;
 import android.support.v7.app.AppCompatActivity;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
 
+import org.briarproject.android.event.AppBus;
+import org.briarproject.android.event.ErrorEvent;
+import org.briarproject.api.event.Event;
+import org.briarproject.api.event.EventListener;
+
 import javax.inject.Inject;
 
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT;
 import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS;
 
-public abstract class BaseActivity extends AppCompatActivity {
-
-	public final static String PREFS_NAME = "db";
-	public final static String PREF_DB_KEY = "key";
-	public final static String PREF_SEEN_WELCOME_MESSAGE = "welcome_message";
+public abstract class BaseActivity extends AppCompatActivity implements
+		EventListener {
 
 	protected ActivityComponent activityComponent;
 
-	// TODO Shared prefs
+	@Inject
+	protected AppBus appBus;
 
 	@Override
 	public void onCreate(Bundle savedInstanceState) {
@@ -42,27 +43,27 @@ public abstract class BaseActivity extends AppCompatActivity {
 		injectActivity(activityComponent);
 	}
 
-	public abstract void injectActivity(ActivityComponent component);
-
-	private SharedPreferences getSharedPrefs() {
-		return getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
+	@Override
+	protected void onResume() {
+		super.onResume();
+		appBus.addListener(this);
 	}
 
-	protected String getEncryptedDatabaseKey() {
-		return getSharedPrefs().getString(PREF_DB_KEY, null);
+	@Override
+	protected void onPause() {
+		appBus.removeListener(this);
+		super.onPause();
 	}
 
-	protected void storeEncryptedDatabaseKey(final String hex) {
-		SharedPreferences.Editor editor = getSharedPrefs().edit();
-		editor.putString(PREF_DB_KEY, hex);
-		editor.apply();
+	@Override
+	@CallSuper
+	public void eventOccurred(Event e) {
+		if (e instanceof ErrorEvent) {
+			finish();
+		}
 	}
 
-	protected void clearSharedPrefs() {
-		SharedPreferences.Editor editor = getSharedPrefs().edit();
-		editor.clear();
-		editor.apply();
-	}
+	public abstract void injectActivity(ActivityComponent component);
 
 	protected void showSoftKeyboard(View view) {
 		Object o = getSystemService(INPUT_METHOD_SERVICE);
@@ -74,4 +75,5 @@ public abstract class BaseActivity extends AppCompatActivity {
 		Object o = getSystemService(INPUT_METHOD_SERVICE);
 		((InputMethodManager) o).hideSoftInputFromWindow(token, 0);
 	}
+
 }
diff --git a/briar-android/src/org/briarproject/android/NavDrawerActivity.java b/briar-android/src/org/briarproject/android/NavDrawerActivity.java
index af98c88fac..c058bc1968 100644
--- a/briar-android/src/org/briarproject/android/NavDrawerActivity.java
+++ b/briar-android/src/org/briarproject/android/NavDrawerActivity.java
@@ -1,5 +1,6 @@
 package org.briarproject.android;
 
+import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
@@ -48,6 +49,8 @@ import static java.util.logging.Level.WARNING;
 public class NavDrawerActivity extends BriarFragmentActivity implements
 		BaseFragment.BaseFragmentListener, EventListener {
 
+	public final static String PREF_SEEN_WELCOME_MESSAGE = "welcome_message";
+
 	public static final String INTENT_CONTACTS = "intent_contacts";
 	public static final String INTENT_FORUMS = "intent_forums";
 
@@ -137,8 +140,7 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
 	}
 
 	private void welcomeMessageCheck() {
-		SharedPreferences prefs = getSharedPreferences(PREFS_NAME,
-				MODE_PRIVATE);
+		SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
 		if (!prefs.getBoolean(PREF_SEEN_WELCOME_MESSAGE, false)) {
 			showMessageDialog(R.string.dialog_title_welcome,
 					R.string.dialog_welcome_message);
diff --git a/briar-android/src/org/briarproject/android/PasswordActivity.java b/briar-android/src/org/briarproject/android/PasswordActivity.java
index 41c2459de3..34dde0fb14 100644
--- a/briar-android/src/org/briarproject/android/PasswordActivity.java
+++ b/briar-android/src/org/briarproject/android/PasswordActivity.java
@@ -16,14 +16,10 @@ import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
 import org.briarproject.R;
+import org.briarproject.android.event.PasswordValidateEvent;
+import org.briarproject.android.helper.PasswordHelper;
 import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.api.crypto.CryptoComponent;
-import org.briarproject.api.crypto.CryptoExecutor;
-import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.db.DatabaseConfig;
-import org.briarproject.util.StringUtils;
-
-import java.util.concurrent.Executor;
+import org.briarproject.api.event.Event;
 
 import javax.inject.Inject;
 
@@ -34,28 +30,22 @@ import static android.view.View.VISIBLE;
 
 public class PasswordActivity extends BaseActivity {
 
-	@Inject @CryptoExecutor protected Executor cryptoExecutor;
 	private Button signInButton;
 	private ProgressBar progress;
 	private TextInputLayout input;
 	private EditText password;
 
-	private byte[] encrypted;
-
-	// Fields that are accessed from background threads must be volatile
-	@Inject protected volatile CryptoComponent crypto;
-	@Inject protected volatile DatabaseConfig databaseConfig;
+	@Inject
+	PasswordHelper passwordHelper;
 
 	@Override
 	public void onCreate(Bundle state) {
 		super.onCreate(state);
 
-		String hex = getEncryptedDatabaseKey();
-		if (hex == null || !databaseConfig.databaseExists()) {
+		if (!passwordHelper.initialized()) {
 			clearSharedPrefsAndDeleteEverything();
 			return;
 		}
-		encrypted = StringUtils.fromHexString(hex);
 
 		setContentView(R.layout.activity_password);
 		signInButton = (Button) findViewById(R.id.btn_sign_in);
@@ -66,8 +56,7 @@ public class PasswordActivity extends BaseActivity {
 			@Override
 			public boolean onEditorAction(TextView v, int actionId,
 					KeyEvent event) {
-				hideSoftKeyboard(password);
-				validatePassword(encrypted, password.getText());
+				validatePassword();
 				return true;
 			}
 		});
@@ -103,7 +92,7 @@ public class PasswordActivity extends BaseActivity {
 	}
 
 	private void clearSharedPrefsAndDeleteEverything() {
-		clearSharedPrefs();
+		passwordHelper.clearPrefs();
 		AndroidUtils.deleteAppData(this);
 		setResult(RESULT_CANCELED);
 		startActivity(new Intent(this, SetupActivity.class));
@@ -111,7 +100,7 @@ public class PasswordActivity extends BaseActivity {
 	}
 
 	public void onSignInClick(View v) {
-		validatePassword(encrypted, password.getText());
+		validatePassword();
 	}
 
 	public void onForgottenPasswordClick(View v) {
@@ -132,47 +121,37 @@ public class PasswordActivity extends BaseActivity {
 		dialog.show();
 	}
 
-	private void validatePassword(final byte[] encrypted, Editable e) {
+	private void validatePassword() {
 		hideSoftKeyboard(password);
-		// Replace the button with a progress bar
 		signInButton.setVisibility(INVISIBLE);
 		progress.setVisibility(VISIBLE);
-		// Decrypt the database key in a background thread
-		final String password = e.toString();
-		cryptoExecutor.execute(new Runnable() {
-			public void run() {
-				byte[] key = crypto.decryptWithPassword(encrypted, password);
-				if (key == null) {
-					tryAgain();
-				} else {
-					databaseConfig.setEncryptionKey(new SecretKey(key));
-					setResultAndFinish();
-				}
-			}
-		});
-	}
-
-	private void tryAgain() {
-		runOnUiThread(new Runnable() {
-			public void run() {
-				AndroidUtils.setError(input, getString(R.string.try_again),
-						true);
-				signInButton.setVisibility(VISIBLE);
-				progress.setVisibility(INVISIBLE);
-				password.setText("");
-
-				// show the keyboard again
-				showSoftKeyboard(password);
-			}
-		});
+		passwordHelper.validatePassword(password.getText().toString());
 	}
 
-	private void setResultAndFinish() {
-		runOnUiThread(new Runnable() {
-			public void run() {
+	@Override
+	public void eventOccurred(Event e) {
+		super.eventOccurred(e);
+		if (e instanceof PasswordValidateEvent) {
+			boolean validated = ((PasswordValidateEvent)e).passwordValidated();
+			if (validated) {
 				setResult(RESULT_OK);
 				finish();
 			}
-		});
+			else {
+				tryAgain();
+			}
+		}
 	}
+
+	private void tryAgain() {
+		AndroidUtils.setError(input, getString(R.string.try_again),
+				true);
+		signInButton.setVisibility(VISIBLE);
+		progress.setVisibility(INVISIBLE);
+		password.setText("");
+
+		// show the keyboard again
+		showSoftKeyboard(password);
+	}
+
 }
diff --git a/briar-android/src/org/briarproject/android/SetupActivity.java b/briar-android/src/org/briarproject/android/SetupActivity.java
index 1ddb6dd58e..8305e09d70 100644
--- a/briar-android/src/org/briarproject/android/SetupActivity.java
+++ b/briar-android/src/org/briarproject/android/SetupActivity.java
@@ -15,6 +15,7 @@ import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
 import org.briarproject.R;
+import org.briarproject.android.helper.SetupHelper;
 import org.briarproject.android.util.AndroidUtils;
 import org.briarproject.android.util.StrengthMeter;
 import org.briarproject.android.api.ReferenceManager;
@@ -45,17 +46,8 @@ import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENG
 public class SetupActivity extends BaseActivity implements OnClickListener,
 		OnEditorActionListener {
 
-	private static final Logger LOG =
-			Logger.getLogger(SetupActivity.class.getName());
-
-	@Inject @CryptoExecutor protected Executor cryptoExecutor;
-	@Inject protected PasswordStrengthEstimator strengthEstimator;
-
-	// Fields that are accessed from background threads must be volatile
-	@Inject protected volatile CryptoComponent crypto;
-	@Inject protected volatile DatabaseConfig databaseConfig;
-	@Inject protected volatile AuthorFactory authorFactory;
-	@Inject protected volatile ReferenceManager referenceManager;
+	@Inject
+	SetupHelper setupHelper;
 
 	TextInputLayout nicknameEntryWrapper;
 	TextInputLayout passwordEntryWrapper;
@@ -123,7 +115,8 @@ public class SetupActivity extends BaseActivity implements OnClickListener,
 		String firstPassword = passwordEntry.getText().toString();
 		String secondPassword = passwordConfirmation.getText().toString();
 		boolean passwordsMatch = firstPassword.equals(secondPassword);
-		float strength = strengthEstimator.estimateStrength(firstPassword);
+//		float strength = strengthEstimator.estimateStrength(firstPassword);
+		float strength = setupHelper.estimatePasswordStrength(firstPassword);
 		strengthMeter.setStrength(strength);
 		AndroidUtils.setError(nicknameEntryWrapper,
 				getString(R.string.name_too_long),
@@ -150,41 +143,22 @@ public class SetupActivity extends BaseActivity implements OnClickListener,
 		progress.setVisibility(VISIBLE);
 		final String nickname = nicknameEntry.getText().toString();
 		final String password = passwordEntry.getText().toString();
-		// Store the DB key and create the identity in a background thread
-		cryptoExecutor.execute(new Runnable() {
-			public void run() {
-				SecretKey key = crypto.generateSecretKey();
-				databaseConfig.setEncryptionKey(key);
-				String hex = encryptDatabaseKey(key, password);
-				storeEncryptedDatabaseKey(hex);
-				LocalAuthor localAuthor = createLocalAuthor(nickname);
-				showDashboard(referenceManager.putReference(localAuthor,
-						LocalAuthor.class));
-			}
-		});
+		setupHelper.createIdentity(nickname, password);
+//		// Store the DB key and create the identity in a background thread
+//		cryptoExecutor.execute(new Runnable() {
+//			public void run() {
+//				SecretKey key = crypto.generateSecretKey();
+//				databaseConfig.setEncryptionKey(key);
+//				String hex = encryptDatabaseKey(key, password);
+//				storeEncryptedDatabaseKey(hex);
+//				LocalAuthor localAuthor = createLocalAuthor(nickname);
+//				showDashboard(referenceManager.putReference(localAuthor,
+//						LocalAuthor.class));
+//			}
+//		});
 	}
 
-	private String encryptDatabaseKey(SecretKey key, String password) {
-		long now = System.currentTimeMillis();
-		byte[] encrypted = crypto.encryptWithPassword(key.getBytes(), password);
-		long duration = System.currentTimeMillis() - now;
-		if (LOG.isLoggable(INFO))
-			LOG.info("Key derivation took " + duration + " ms");
-		return StringUtils.toHexString(encrypted);
-	}
 
-	private LocalAuthor createLocalAuthor(String nickname) {
-		long now = System.currentTimeMillis();
-		KeyPair keyPair = crypto.generateSignatureKeyPair();
-		byte[] publicKey = keyPair.getPublic().getEncoded();
-		byte[] privateKey = keyPair.getPrivate().getEncoded();
-		LocalAuthor localAuthor = authorFactory.createLocalAuthor(nickname,
-				publicKey, privateKey);
-		long duration = System.currentTimeMillis() - now;
-		if (LOG.isLoggable(INFO))
-			LOG.info("Identity creation took " + duration + " ms");
-		return localAuthor;
-	}
 
 	private void showDashboard(final long handle) {
 		runOnUiThread(new Runnable() {
diff --git a/briar-android/src/org/briarproject/android/SplashScreenActivity.java b/briar-android/src/org/briarproject/android/SplashScreenActivity.java
index 9a736d9163..0439159703 100644
--- a/briar-android/src/org/briarproject/android/SplashScreenActivity.java
+++ b/briar-android/src/org/briarproject/android/SplashScreenActivity.java
@@ -9,9 +9,8 @@ import android.os.StrictMode.VmPolicy;
 import android.support.v7.preference.PreferenceManager;
 
 import org.briarproject.R;
-import org.briarproject.android.api.AndroidExecutor;
+import org.briarproject.android.helper.ConfigHelper;
 import org.briarproject.android.util.AndroidUtils;
-import org.briarproject.api.db.DatabaseConfig;
 
 import java.util.logging.Logger;
 
@@ -29,9 +28,7 @@ public class SplashScreenActivity extends BaseActivity {
 	private static final long EXPIRY_DATE = 1464735600 * 1000L;
 
 	@Inject
-	protected DatabaseConfig dbConfig;
-	@Inject
-	protected AndroidExecutor androidExecutor;
+	ConfigHelper configHelper;
 
 	public SplashScreenActivity() {
 		Logger.getLogger("").setLevel(DEFAULT_LOG_LEVEL);
@@ -65,11 +62,10 @@ public class SplashScreenActivity extends BaseActivity {
 			LOG.info("Expired");
 			startActivity(new Intent(this, ExpiredActivity.class));
 		} else {
-			String hex = getEncryptedDatabaseKey();
-			if (hex != null && dbConfig.databaseExists()) {
+			if (configHelper.initialized()) {
 				startActivity(new Intent(this, NavDrawerActivity.class));
 			} else {
-				clearSharedPrefs();
+				configHelper.clearPrefs();
 				AndroidUtils.deleteAppData(this);
 				startActivity(new Intent(this, SetupActivity.class));
 			}
diff --git a/briar-android/src/org/briarproject/android/event/AppBus.java b/briar-android/src/org/briarproject/android/event/AppBus.java
new file mode 100644
index 0000000000..08008e28ee
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/event/AppBus.java
@@ -0,0 +1,6 @@
+package org.briarproject.android.event;
+
+import org.briarproject.api.event.EventBus;
+
+public interface AppBus extends EventBus{
+}
diff --git a/briar-android/src/org/briarproject/android/event/AppBusImp.java b/briar-android/src/org/briarproject/android/event/AppBusImp.java
new file mode 100644
index 0000000000..f193e13101
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/event/AppBusImp.java
@@ -0,0 +1,25 @@
+package org.briarproject.android.event;
+
+
+import org.briarproject.api.event.Event;
+import org.briarproject.api.event.EventListener;
+
+import java.util.Collection;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class AppBusImp implements AppBus {
+	private final Collection<EventListener> listeners =
+			new CopyOnWriteArrayList<EventListener>();
+
+	public void addListener(EventListener l) {
+		listeners.add(l);
+	}
+
+	public void removeListener(EventListener l) {
+		listeners.remove(l);
+	}
+
+	public void broadcast(Event e) {
+		for (EventListener l : listeners) l.eventOccurred(e);
+	}
+}
diff --git a/briar-android/src/org/briarproject/android/event/ErrorEvent.java b/briar-android/src/org/briarproject/android/event/ErrorEvent.java
new file mode 100644
index 0000000000..f326fd575d
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/event/ErrorEvent.java
@@ -0,0 +1,10 @@
+package org.briarproject.android.event;
+
+import org.briarproject.api.event.Event;
+
+public class ErrorEvent extends Event {
+
+	public ErrorEvent() {
+
+	}
+}
diff --git a/briar-android/src/org/briarproject/android/event/LocalAuthorCreatedEvent.java b/briar-android/src/org/briarproject/android/event/LocalAuthorCreatedEvent.java
new file mode 100644
index 0000000000..6a9b2e2560
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/event/LocalAuthorCreatedEvent.java
@@ -0,0 +1,16 @@
+package org.briarproject.android.event;
+
+import org.briarproject.api.event.Event;
+
+public class LocalAuthorCreatedEvent extends Event {
+
+	private final long handle;
+
+	public LocalAuthorCreatedEvent(long handle) {
+		this.handle = handle;
+	}
+
+	public long getAuthorHandle() {
+		return handle;
+	}
+}
diff --git a/briar-android/src/org/briarproject/android/event/PasswordValidateEvent.java b/briar-android/src/org/briarproject/android/event/PasswordValidateEvent.java
new file mode 100644
index 0000000000..35a3552821
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/event/PasswordValidateEvent.java
@@ -0,0 +1,16 @@
+package org.briarproject.android.event;
+
+import org.briarproject.api.event.Event;
+
+public class PasswordValidateEvent extends Event {
+
+	private final boolean passwordValidated;
+
+	public PasswordValidateEvent(boolean passwordValidated) {
+		this.passwordValidated = passwordValidated;
+	}
+
+	public boolean passwordValidated() {
+		return passwordValidated;
+	}
+}
diff --git a/briar-android/src/org/briarproject/android/helper/ConfigHelper.java b/briar-android/src/org/briarproject/android/helper/ConfigHelper.java
new file mode 100644
index 0000000000..0fe70579da
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/helper/ConfigHelper.java
@@ -0,0 +1,9 @@
+package org.briarproject.android.helper;
+
+public interface ConfigHelper {
+	String getEncryptedDatabaseKey();
+
+	void clearPrefs();
+
+	boolean initialized();
+}
diff --git a/briar-android/src/org/briarproject/android/helper/ConfigHelperImp.java b/briar-android/src/org/briarproject/android/helper/ConfigHelperImp.java
new file mode 100644
index 0000000000..ca818148a0
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/helper/ConfigHelperImp.java
@@ -0,0 +1,41 @@
+package org.briarproject.android.helper;
+
+import android.content.SharedPreferences;
+
+import org.briarproject.api.db.DatabaseConfig;
+
+import javax.inject.Inject;
+
+public class ConfigHelperImp implements ConfigHelper {
+
+	private final static String PREF_DB_KEY = "key";
+
+	@Inject
+	protected SharedPreferences briarPrefs;
+	@Inject
+	protected volatile DatabaseConfig databaseConfig;
+
+	@Inject
+	public ConfigHelperImp() {
+
+	}
+
+	public String getEncryptedDatabaseKey() {
+		return briarPrefs.getString(PREF_DB_KEY, null);
+	}
+
+	public void clearPrefs() {
+		SharedPreferences.Editor editor = briarPrefs.edit();
+		editor.clear();
+		editor.apply();
+	}
+
+	@Override
+	public boolean initialized() {
+		String hex = getEncryptedDatabaseKey();
+		if (hex != null && databaseConfig.databaseExists()) {
+			return true;
+		}
+		return false;
+	}
+}
diff --git a/briar-android/src/org/briarproject/android/helper/PasswordHelper.java b/briar-android/src/org/briarproject/android/helper/PasswordHelper.java
new file mode 100644
index 0000000000..00aeb3da6d
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/helper/PasswordHelper.java
@@ -0,0 +1,5 @@
+package org.briarproject.android.helper;
+
+public interface PasswordHelper extends ConfigHelper {
+	void validatePassword(String password);
+}
diff --git a/briar-android/src/org/briarproject/android/helper/PasswordHelperImp.java b/briar-android/src/org/briarproject/android/helper/PasswordHelperImp.java
new file mode 100644
index 0000000000..95481bd4a0
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/helper/PasswordHelperImp.java
@@ -0,0 +1,70 @@
+package org.briarproject.android.helper;
+
+import android.app.Activity;
+
+import org.briarproject.android.event.AppBus;
+import org.briarproject.android.event.ErrorEvent;
+import org.briarproject.android.event.PasswordValidateEvent;
+import org.briarproject.api.crypto.CryptoComponent;
+import org.briarproject.api.crypto.CryptoExecutor;
+import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.util.StringUtils;
+
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+
+public class PasswordHelperImp extends ConfigHelperImp
+		implements PasswordHelper {
+
+	@Inject
+	@CryptoExecutor
+	protected Executor cryptoExecutor;
+	@Inject
+	protected CryptoComponent crypto;
+	@Inject
+	protected Activity activity;
+	@Inject
+	protected AppBus appBus;
+
+	@Inject
+	public PasswordHelperImp() {
+
+	}
+
+	@Override
+	public void validatePassword(final String password) {
+		final byte[] encrypted = getEncryptedKey();
+		if (encrypted == null) {
+			appBus.broadcast(new ErrorEvent());
+		}
+		cryptoExecutor.execute(new Runnable() {
+			public void run() {
+				byte[] key = crypto.decryptWithPassword(encrypted, password);
+				if (key == null) {
+//					tryAgain();.
+					onPasswordValidated(false);
+				} else {
+					databaseConfig.setEncryptionKey(new SecretKey(key));
+					onPasswordValidated(true);
+//					setResultAndFinish();
+				}
+			}
+		});
+	}
+
+	private void onPasswordValidated(final boolean validated) {
+		activity.runOnUiThread(new Runnable() {
+			@Override
+			public void run() {
+				appBus.broadcast(new PasswordValidateEvent(validated));
+			}
+		});
+	}
+
+
+	private byte[] getEncryptedKey() {
+		String hex = getEncryptedDatabaseKey();
+		return hex == null? null : StringUtils.fromHexString(hex);
+	}
+}
diff --git a/briar-android/src/org/briarproject/android/helper/SetupHelper.java b/briar-android/src/org/briarproject/android/helper/SetupHelper.java
new file mode 100644
index 0000000000..329b8b2106
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/helper/SetupHelper.java
@@ -0,0 +1,6 @@
+package org.briarproject.android.helper;
+
+public interface SetupHelper {
+	float estimatePasswordStrength(String password);
+	void createIdentity(String nickname, String password);
+}
diff --git a/briar-android/src/org/briarproject/android/helper/SetupHelperImp.java b/briar-android/src/org/briarproject/android/helper/SetupHelperImp.java
new file mode 100644
index 0000000000..9015c482f5
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/helper/SetupHelperImp.java
@@ -0,0 +1,119 @@
+package org.briarproject.android.helper;
+
+import android.app.Activity;
+import android.content.SharedPreferences;
+
+import org.briarproject.android.api.ReferenceManager;
+import org.briarproject.android.event.AppBus;
+import org.briarproject.android.event.LocalAuthorCreatedEvent;
+import org.briarproject.api.crypto.CryptoComponent;
+import org.briarproject.api.crypto.CryptoExecutor;
+import org.briarproject.api.crypto.KeyPair;
+import org.briarproject.api.crypto.PasswordStrengthEstimator;
+import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.api.db.DatabaseConfig;
+import org.briarproject.api.identity.AuthorFactory;
+import org.briarproject.api.identity.LocalAuthor;
+import org.briarproject.util.StringUtils;
+
+import java.util.concurrent.Executor;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+
+import static java.util.logging.Level.INFO;
+
+public class SetupHelperImp implements SetupHelper {
+
+	private static final Logger LOG =
+			Logger.getLogger(SetupHelperImp.class.getName());
+
+	private final static String PREF_DB_KEY = "key";
+
+	@Inject
+	@CryptoExecutor
+	protected Executor cryptoExecutor;
+	@Inject
+	protected PasswordStrengthEstimator strengthEstimator;
+
+	// Fields that are accessed from background threads must be volatile
+	@Inject
+	protected volatile CryptoComponent crypto;
+	@Inject
+	protected volatile DatabaseConfig databaseConfig;
+	@Inject
+	protected volatile AuthorFactory authorFactory;
+	@Inject
+	protected volatile ReferenceManager referenceManager;
+
+	@Inject
+	protected Activity activity;
+	@Inject
+	protected SharedPreferences briarPrefs;
+	@Inject
+	protected AppBus appBus;
+
+	@Inject
+	public SetupHelperImp() {
+
+	}
+
+	private String encryptDatabaseKey(SecretKey key, String password) {
+		long now = System.currentTimeMillis();
+		byte[] encrypted = crypto.encryptWithPassword(key.getBytes(), password);
+		long duration = System.currentTimeMillis() - now;
+		if (LOG.isLoggable(INFO))
+			LOG.info("Key derivation took " + duration + " ms");
+		return StringUtils.toHexString(encrypted);
+	}
+
+	private LocalAuthor createLocalAuthor(String nickname) {
+		long now = System.currentTimeMillis();
+		KeyPair keyPair = crypto.generateSignatureKeyPair();
+		byte[] publicKey = keyPair.getPublic().getEncoded();
+		byte[] privateKey = keyPair.getPrivate().getEncoded();
+		LocalAuthor localAuthor = authorFactory.createLocalAuthor(nickname,
+				publicKey, privateKey);
+		long duration = System.currentTimeMillis() - now;
+		if (LOG.isLoggable(INFO))
+			LOG.info("Identity creation took " + duration + " ms");
+		return localAuthor;
+	}
+
+	@Override
+	public float estimatePasswordStrength(String password) {
+		return strengthEstimator.estimateStrength(password);
+	}
+
+	@Override
+	public void createIdentity(final String nickname, final String password) {
+		cryptoExecutor.execute(new Runnable() {
+			public void run() {
+				SecretKey key = crypto.generateSecretKey();
+				databaseConfig.setEncryptionKey(key);
+				String hex = encryptDatabaseKey(key, password);
+				storeEncryptedDatabaseKey(hex);
+				final LocalAuthor localAuthor = createLocalAuthor(nickname);
+				onIdentityCreated(referenceManager.putReference(localAuthor,
+						LocalAuthor.class));
+
+			}
+		});
+	}
+
+	private void onIdentityCreated(final long handle) {
+		activity.runOnUiThread(new Runnable() {
+			@Override
+			public void run() {
+				appBus.broadcast(new LocalAuthorCreatedEvent(handle));
+			}
+		});
+	}
+
+	private void storeEncryptedDatabaseKey(final String hex) {
+		SharedPreferences.Editor editor = briarPrefs.edit();
+		editor.putString(PREF_DB_KEY, hex);
+		editor.apply();
+	}
+
+}
diff --git a/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java b/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java
index c57e44d03b..03198cf482 100644
--- a/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java
+++ b/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java
@@ -10,7 +10,7 @@ import android.support.v7.preference.PreferenceManager;
 import org.briarproject.android.ActivityComponent;
 import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
-import org.briarproject.android.api.AndroidExecutor;
+import org.briarproject.android.helper.ConfigHelper;
 import org.briarproject.android.util.AndroidUtils;
 import org.briarproject.api.db.DatabaseConfig;
 import org.iilab.IilabEngineeringRSA2048Pin;
@@ -24,7 +24,6 @@ import info.guardianproject.panic.Panic;
 import info.guardianproject.panic.PanicResponder;
 import info.guardianproject.trustedintents.TrustedIntents;
 
-import static android.content.Intent.ACTION_DELETE;
 import static org.briarproject.android.panic.PanicPreferencesFragment.KEY_LOCK;
 import static org.briarproject.android.panic.PanicPreferencesFragment.KEY_PURGE;
 import static org.briarproject.android.panic.PanicPreferencesFragment.KEY_UNINSTALL;
@@ -33,11 +32,7 @@ public class PanicResponderActivity extends BriarActivity {
 
 	private static final Logger LOG =
 			Logger.getLogger(PanicResponderActivity.class.getName());
-
-	@Inject
-	protected DatabaseConfig databaseConfig;
-	@Inject
-	protected AndroidExecutor androidExecutor;
+	@Inject protected ConfigHelper configHelper;
 
 	@Override
 	public void onCreate(Bundle savedInstanceState) {
@@ -113,7 +108,7 @@ public class PanicResponderActivity extends BriarActivity {
 	private void deleteAllData() {
 		androidExecutor.execute(new Runnable() {
 			public void run() {
-				clearSharedPrefs();
+				configHelper.clearPrefs();
 				// TODO somehow delete/shred the database more thoroughly
 				AndroidUtils.deleteAppData(PanicResponderActivity.this);
 				PanicResponder.deleteAllAppData(PanicResponderActivity.this);
diff --git a/briar-android/src/org/briarproject/android/sdk/BriarHelper.java b/briar-android/src/org/briarproject/android/sdk/BriarHelper.java
deleted file mode 100644
index 1cb8993ae8..0000000000
--- a/briar-android/src/org/briarproject/android/sdk/BriarHelper.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package org.briarproject.android.sdk;
-
-public interface BriarHelper {
-}
diff --git a/briar-android/src/org/briarproject/android/sdk/BriarHelperImp.java b/briar-android/src/org/briarproject/android/sdk/BriarHelperImp.java
deleted file mode 100644
index c83c33ac83..0000000000
--- a/briar-android/src/org/briarproject/android/sdk/BriarHelperImp.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.briarproject.android.sdk;
-
-import javax.inject.Inject;
-
-public class BriarHelperImp implements BriarHelper {
-
-	
-
-	@Inject
-	public BriarHelperImp() {
-
-	}
-}
-- 
GitLab