diff --git a/app/src/main/java/me/impy/aegis/AuthActivity.java b/app/src/main/java/me/impy/aegis/AuthActivity.java
index b1322a67..ddf641d9 100644
--- a/app/src/main/java/me/impy/aegis/AuthActivity.java
+++ b/app/src/main/java/me/impy/aegis/AuthActivity.java
@@ -1,38 +1,84 @@
package me.impy.aegis;
+import android.Manifest;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.Build;
+import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
-import android.text.Editable;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RadioButton;
+import android.widget.TextView;
import java.lang.reflect.UndeclaredThrowableException;
+import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import me.impy.aegis.crypto.CryptoUtils;
+import me.impy.aegis.crypto.KeyStoreHandle;
import me.impy.aegis.crypto.MasterKey;
+import me.impy.aegis.crypto.slots.FingerprintSlot;
import me.impy.aegis.crypto.slots.PasswordSlot;
import me.impy.aegis.crypto.slots.Slot;
import me.impy.aegis.crypto.slots.SlotCollection;
+import me.impy.aegis.finger.FingerprintUiHelper;
+import me.impy.aegis.helpers.AuthHelper;
-public class AuthActivity extends AppCompatActivity {
+public class AuthActivity extends AppCompatActivity implements FingerprintUiHelper.Callback {
public static final int RESULT_OK = 0;
public static final int RESULT_EXCEPTION = 1;
private EditText textPassword;
+ private SlotCollection slots;
+ private LinearLayout boxFingerprint;
+ private ImageView imgFingerprint;
+ private TextView textFingerprint;
+ private FingerprintUiHelper fingerHelper;
+ private Cipher fingerCipher;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_auth);
textPassword = (EditText) findViewById(R.id.text_password);
+ boxFingerprint = (LinearLayout) findViewById(R.id.box_fingerprint);
+ imgFingerprint = (ImageView) findViewById(R.id.img_fingerprint);
+ textFingerprint = (TextView) findViewById(R.id.text_fingerprint);
Intent intent = getIntent();
- final SlotCollection slots = (SlotCollection) intent.getSerializableExtra("slots");
+ slots = (SlotCollection) intent.getSerializableExtra("slots");
+
+ // only show the fingerprint controls if the api version is new enough, permission is granted, a scanner is found and a fingerprint slot is found
+ Context context = getApplicationContext();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ FingerprintManager manager = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
+ if (ActivityCompat.checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT) == PackageManager.PERMISSION_GRANTED && manager.isHardwareDetected()) {
+ if (slots.has(FingerprintSlot.class)) {
+ try {
+ KeyStoreHandle handle = new KeyStoreHandle();
+ if (handle.keyExists()) {
+ SecretKey key = handle.getKey();
+ fingerCipher = Slot.createCipher(key, Cipher.DECRYPT_MODE);
+ fingerHelper = new FingerprintUiHelper(manager, imgFingerprint, textFingerprint, this);
+ boxFingerprint.setVisibility(View.VISIBLE);
+ }
+ } catch (Exception e) {
+ throw new UndeclaredThrowableException(e);
+ }
+ }
+ }
+ }
Button button = (Button) findViewById(R.id.button_decrypt);
button.setOnClickListener(new View.OnClickListener() {
@@ -42,11 +88,13 @@ public class AuthActivity extends AppCompatActivity {
try {
if (slots.has(PasswordSlot.class)) {
PasswordSlot slot = slots.find(PasswordSlot.class);
- char[] password = getPassword(true);
+ char[] password = AuthHelper.getPassword(textPassword, true);
SecretKey key = slot.deriveKey(password);
CryptoUtils.zero(password);
Cipher cipher = Slot.createCipher(key, Cipher.DECRYPT_MODE);
masterKey = MasterKey.decryptSlot(slot, cipher);
+ } else {
+ throw new RuntimeException();
}
} catch (Exception e) {
// TODO: feedback
@@ -54,31 +102,57 @@ public class AuthActivity extends AppCompatActivity {
}
// send the master key back to the main activity
- Intent result = new Intent();
- result.putExtra("key", masterKey);
- setResult(RESULT_OK, result);
- finish();
+ setKey(masterKey);
}
});
}
+ private void setKey(MasterKey key) {
+ // send the master key back to the main activity
+ Intent result = new Intent();
+ result.putExtra("key", key);
+ setResult(RESULT_OK, result);
+ finish();
+ }
+
@Override
public void onBackPressed() {
// ignore back button presses
}
- private char[] getPassword(boolean clear) {
- char[] password = getEditTextChars(textPassword);
- if (clear) {
- textPassword.getText().clear();
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ if (fingerHelper != null) {
+ fingerHelper.startListening(new FingerprintManager.CryptoObject(fingerCipher));
}
- return password;
}
- private static char[] getEditTextChars(EditText text) {
- Editable editable = text.getText();
- char[] chars = new char[editable.length()];
- editable.getChars(0, editable.length(), chars, 0);
- return chars;
+ @Override
+ public void onPause() {
+ super.onPause();
+
+ if (fingerHelper != null) {
+ fingerHelper.stopListening();
+ }
+ }
+
+ @Override
+ public void onAuthenticated() {
+ MasterKey key;
+ FingerprintSlot slot = slots.find(FingerprintSlot.class);
+ try {
+ key = new MasterKey(slot.getKey(fingerCipher));
+ } catch (Exception e) {
+ throw new UndeclaredThrowableException(e);
+ }
+
+ setKey(key);
+ }
+
+ @Override
+ public void onError() {
+
}
}
diff --git a/app/src/main/java/me/impy/aegis/CustomAuthenticatedSlide.java b/app/src/main/java/me/impy/aegis/CustomAuthenticatedSlide.java
index 5e2b52cf..d8861601 100644
--- a/app/src/main/java/me/impy/aegis/CustomAuthenticatedSlide.java
+++ b/app/src/main/java/me/impy/aegis/CustomAuthenticatedSlide.java
@@ -1,42 +1,57 @@
package me.impy.aegis;
+import android.content.Context;
import android.content.Intent;
+import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
-import android.text.Editable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
import com.github.paolorotolo.appintro.ISlidePolicy;
import com.github.paolorotolo.appintro.ISlideSelectionListener;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.spec.InvalidKeySpecException;
-import java.util.Arrays;
+import java.lang.reflect.UndeclaredThrowableException;
import javax.crypto.Cipher;
-import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import me.impy.aegis.crypto.CryptoUtils;
+import me.impy.aegis.crypto.KeyStoreHandle;
+import me.impy.aegis.crypto.slots.FingerprintSlot;
import me.impy.aegis.crypto.slots.PasswordSlot;
import me.impy.aegis.crypto.slots.Slot;
+import me.impy.aegis.finger.FingerprintUiHelper;
+import me.impy.aegis.helpers.AuthHelper;
-public class CustomAuthenticatedSlide extends Fragment implements ISlidePolicy, ISlideSelectionListener {
+public class CustomAuthenticatedSlide extends Fragment implements FingerprintUiHelper.Callback, ISlidePolicy, ISlideSelectionListener {
private int cryptType;
private EditText textPassword;
private EditText textPasswordConfirm;
private int bgColor;
+ private LinearLayout boxFingerprint;
+ private ImageView imgFingerprint;
+ private TextView textFingerprint;
+ private FingerprintUiHelper fingerHelper;
+ private KeyStoreHandle storeHandle;
+ private Cipher fingerCipher;
+ private boolean fingerAuthenticated;
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_authenticated_slide, container, false);
textPassword = (EditText) view.findViewById(R.id.text_password);
textPasswordConfirm = (EditText) view.findViewById(R.id.text_password_confirm);
+ boxFingerprint = (LinearLayout) view.findViewById(R.id.box_fingerprint);
+ imgFingerprint = (ImageView) view.findViewById(R.id.img_fingerprint);
+ textFingerprint = (TextView) view.findViewById(R.id.text_fingerprint);
view.findViewById(R.id.main).setBackgroundColor(bgColor);
return view;
}
@@ -50,46 +65,17 @@ public class CustomAuthenticatedSlide extends Fragment implements ISlidePolicy,
return cryptType;
}
- public Cipher getCipher(PasswordSlot slot, int mode)
- throws InvalidKeySpecException, NoSuchAlgorithmException,
- InvalidKeyException, NoSuchPaddingException {
- char[] password = getPassword(true);
- byte[] salt = CryptoUtils.generateSalt();
- SecretKey key = slot.deriveKey(password, salt, CryptoUtils.CRYPTO_SCRYPT_N, CryptoUtils.CRYPTO_SCRYPT_r, CryptoUtils.CRYPTO_SCRYPT_p);
- CryptoUtils.zero(password);
-
- return Slot.createCipher(key, mode);
- }
-
- private char[] getPassword(boolean clear) {
- char[] password = getEditTextChars(textPassword);
- if (clear) {
- textPassword.getText().clear();
- }
- return password;
- }
-
- private static char[] getEditTextChars(EditText text) {
- Editable editable = text.getText();
- char[] chars = new char[editable.length()];
- editable.getChars(0, editable.length(), chars, 0);
- return chars;
- }
-
- @Override
- public void onSlideSelected() {
- Intent intent = getActivity().getIntent();
- cryptType = intent.getIntExtra("cryptType", 1337);
-
- switch(cryptType) {
- case CustomAuthenticationSlide.CRYPT_TYPE_NONE:
- break;
- case CustomAuthenticationSlide.CRYPT_TYPE_PASS:
- break;
- case CustomAuthenticationSlide.CRYPT_TYPE_FINGER:
- break;
- default:
- throw new RuntimeException();
+ public Cipher getCipher(Slot slot) throws Exception {
+ if (slot instanceof PasswordSlot) {
+ char[] password = AuthHelper.getPassword(textPassword, true);
+ byte[] salt = CryptoUtils.generateSalt();
+ SecretKey key = ((PasswordSlot)slot).deriveKey(password, salt, CryptoUtils.CRYPTO_SCRYPT_N, CryptoUtils.CRYPTO_SCRYPT_r, CryptoUtils.CRYPTO_SCRYPT_p);
+ CryptoUtils.zero(password);
+ return Slot.createCipher(key, Cipher.ENCRYPT_MODE);
+ } else if (slot instanceof FingerprintSlot) {
+ return fingerCipher;
+ } else {
+ throw new RuntimeException();
}
}
@@ -97,8 +83,57 @@ public class CustomAuthenticatedSlide extends Fragment implements ISlidePolicy,
bgColor = color;
}
+ @Override
+ public void onSlideSelected() {
+ Intent intent = getActivity().getIntent();
+ cryptType = intent.getIntExtra("cryptType", CustomAuthenticationSlide.CRYPT_TYPE_INVALID);
+
+ switch(cryptType) {
+ case CustomAuthenticationSlide.CRYPT_TYPE_NONE:
+ case CustomAuthenticationSlide.CRYPT_TYPE_PASS:
+ break;
+ case CustomAuthenticationSlide.CRYPT_TYPE_FINGER:
+ boxFingerprint.setVisibility(View.VISIBLE);
+
+ SecretKey key;
+ try {
+ if (storeHandle == null) {
+ storeHandle = new KeyStoreHandle();
+ }
+ // TODO: consider regenerating the key if it exists
+ if (!storeHandle.keyExists()) {
+ key = storeHandle.generateKey(true);
+ } else {
+ key = storeHandle.getKey();
+ }
+ } catch (Exception e) {
+ throw new UndeclaredThrowableException(e);
+ }
+
+ if (fingerHelper == null) {
+ FingerprintManager fingerManager = (FingerprintManager) getContext().getSystemService(Context.FINGERPRINT_SERVICE);
+ fingerHelper = new FingerprintUiHelper(fingerManager, imgFingerprint, textFingerprint, this);
+ }
+
+ try {
+ fingerCipher = Slot.createCipher(key, Cipher.ENCRYPT_MODE);
+ } catch (Exception e) {
+ throw new UndeclaredThrowableException(e);
+ }
+ fingerHelper.startListening(new FingerprintManager.CryptoObject(fingerCipher));
+ break;
+ default:
+ throw new RuntimeException();
+ }
+ }
+
@Override
public void onSlideDeselected() {
+ if (fingerHelper != null) {
+ fingerAuthenticated = false;
+ boxFingerprint.setVisibility(View.INVISIBLE);
+ fingerHelper.stopListening();
+ }
}
@Override
@@ -106,15 +141,13 @@ public class CustomAuthenticatedSlide extends Fragment implements ISlidePolicy,
switch(cryptType) {
case CustomAuthenticationSlide.CRYPT_TYPE_NONE:
return true;
- case CustomAuthenticationSlide.CRYPT_TYPE_PASS:
- char[] password = getEditTextChars(textPassword);
- char[] passwordConfirm = getEditTextChars(textPasswordConfirm);
- boolean equal = password.length != 0 && Arrays.equals(password, passwordConfirm);
- CryptoUtils.zero(password);
- CryptoUtils.zero(passwordConfirm);
- return equal;
case CustomAuthenticationSlide.CRYPT_TYPE_FINGER:
- return false;
+ if (!fingerAuthenticated) {
+ return false;
+ }
+ // intentional fallthrough
+ case CustomAuthenticationSlide.CRYPT_TYPE_PASS:
+ return AuthHelper.arePasswordsEqual(textPassword, textPasswordConfirm);
default:
throw new RuntimeException();
}
@@ -122,10 +155,29 @@ public class CustomAuthenticatedSlide extends Fragment implements ISlidePolicy,
@Override
public void onUserIllegallyRequestedNextPage() {
+ String message;
+ if (!AuthHelper.arePasswordsEqual(textPassword, textPasswordConfirm)) {
+ message = "Passwords should be equal and non-empty";
+ } else if (!fingerAuthenticated) {
+ message = "Register your fingerprint";
+ } else {
+ return;
+ }
+
View view = getView();
if (view != null) {
- Snackbar snackbar = Snackbar.make(getView(), "Passwords should be equal and non-empty", Snackbar.LENGTH_LONG);
+ Snackbar snackbar = Snackbar.make(getView(), message, Snackbar.LENGTH_LONG);
snackbar.show();
}
}
+
+ @Override
+ public void onAuthenticated() {
+ fingerAuthenticated = true;
+ }
+
+ @Override
+ public void onError() {
+
+ }
}
diff --git a/app/src/main/java/me/impy/aegis/CustomAuthenticationSlide.java b/app/src/main/java/me/impy/aegis/CustomAuthenticationSlide.java
index ca2599ad..3e59ebe0 100644
--- a/app/src/main/java/me/impy/aegis/CustomAuthenticationSlide.java
+++ b/app/src/main/java/me/impy/aegis/CustomAuthenticationSlide.java
@@ -13,11 +13,9 @@ import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
-import android.widget.Toast;
import com.github.paolorotolo.appintro.ISlidePolicy;
@@ -53,9 +51,6 @@ public class CustomAuthenticationSlide extends Fragment implements ISlidePolicy
break;
case R.id.rb_fingerprint:
id = CRYPT_TYPE_FINGER;
- // TODO: remove this
- group.clearCheck();
- Toast.makeText(context, "Fingerprint is not supported yet", Toast.LENGTH_SHORT).show();
break;
default:
throw new RuntimeException();
diff --git a/app/src/main/java/me/impy/aegis/IntroActivity.java b/app/src/main/java/me/impy/aegis/IntroActivity.java
index d12aea47..b48ee94f 100644
--- a/app/src/main/java/me/impy/aegis/IntroActivity.java
+++ b/app/src/main/java/me/impy/aegis/IntroActivity.java
@@ -15,6 +15,7 @@ import javax.crypto.Cipher;
import me.impy.aegis.crypto.CryptResult;
import me.impy.aegis.crypto.MasterKey;
+import me.impy.aegis.crypto.slots.FingerprintSlot;
import me.impy.aegis.crypto.slots.PasswordSlot;
import me.impy.aegis.crypto.slots.SlotCollection;
import me.impy.aegis.db.Database;
@@ -107,13 +108,13 @@ public class IntroActivity extends AppIntro {
}
}
+ SlotCollection slots = databaseFile.getSlots();
if (cryptType != CustomAuthenticationSlide.CRYPT_TYPE_NONE) {
try {
// encrypt the master key with a key derived from the user's password
// and add it to the list of slots
- SlotCollection slots = databaseFile.getSlots();
PasswordSlot slot = new PasswordSlot();
- Cipher cipher = authenticatedSlide.getCipher(slot, Cipher.ENCRYPT_MODE);
+ Cipher cipher = authenticatedSlide.getCipher(slot);
masterKey.encryptSlot(slot, cipher);
slots.add(slot);
} catch (Exception e) {
@@ -122,8 +123,18 @@ public class IntroActivity extends AppIntro {
}
}
- if (cryptType != CustomAuthenticationSlide.CRYPT_TYPE_FINGER) {
- // TODO
+ if (cryptType == CustomAuthenticationSlide.CRYPT_TYPE_FINGER) {
+ try {
+ // encrypt the master key with the fingerprint key
+ // and add it to the list of slots
+ FingerprintSlot slot = new FingerprintSlot();
+ Cipher cipher = authenticatedSlide.getCipher(slot);
+ masterKey.encryptSlot(slot, cipher);
+ slots.add(slot);
+ } catch (Exception e) {
+ setException(e);
+ return;
+ }
}
// finally, save the database
diff --git a/app/src/main/java/me/impy/aegis/crypto/slots/Slot.java b/app/src/main/java/me/impy/aegis/crypto/slots/Slot.java
index 11b8d2ec..20a70605 100644
--- a/app/src/main/java/me/impy/aegis/crypto/slots/Slot.java
+++ b/app/src/main/java/me/impy/aegis/crypto/slots/Slot.java
@@ -25,7 +25,7 @@ public abstract class Slot implements Serializable {
// getKey decrypts the encrypted master key in this slot with the given key and returns it.
public SecretKey getKey(Cipher cipher) throws BadPaddingException, IllegalBlockSizeException {
byte[] decryptedKeyBytes = cipher.doFinal(_encryptedMasterKey);
- SecretKey decryptedKey = new SecretKeySpec(decryptedKeyBytes, CryptoUtils.CRYPTO_CIPHER_RAW);
+ SecretKey decryptedKey = new SecretKeySpec(decryptedKeyBytes, CryptoUtils.CRYPTO_CIPHER_AEAD);
CryptoUtils.zero(decryptedKeyBytes);
return decryptedKey;
}
diff --git a/app/src/main/java/me/impy/aegis/finger/FingerprintUiHelper.java b/app/src/main/java/me/impy/aegis/finger/FingerprintUiHelper.java
index f4f4cbe5..88a10e0a 100644
--- a/app/src/main/java/me/impy/aegis/finger/FingerprintUiHelper.java
+++ b/app/src/main/java/me/impy/aegis/finger/FingerprintUiHelper.java
@@ -1,4 +1,5 @@
-package me.impy.aegis.finger;
+// This file was originally taken from https://github.com/googlesamples/android-FingerprintDialog/blob/2feb02945ae220ebd1bc2c2b620a1d43e30daea8/Application/src/main/java/com/example/android/fingerprintdialog/FingerprintUiHelper.java
+// It has been modified to suit Aegis' needs
/*
* Copyright (C) 2015 The Android Open Source Project
@@ -16,6 +17,8 @@ package me.impy.aegis.finger;
* limitations under the License
*/
+package me.impy.aegis.finger;
+
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.os.CancellationSignal;
@@ -109,8 +112,6 @@ public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallba
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
mIcon.setImageResource(R.drawable.ic_fingerprint_success);
- mErrorTextView.setTextColor(
- mErrorTextView.getResources().getColor(R.color.success_color, null));
mErrorTextView.setText(
mErrorTextView.getResources().getString(R.string.fingerprint_success));
mIcon.postDelayed(new Runnable() {
@@ -124,8 +125,6 @@ public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallba
private void showError(CharSequence error) {
mIcon.setImageResource(R.drawable.ic_fingerprint_error);
mErrorTextView.setText(error);
- mErrorTextView.setTextColor(
- mErrorTextView.getResources().getColor(R.color.warning_color, null));
mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT_MILLIS);
}
@@ -133,8 +132,6 @@ public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallba
private Runnable mResetErrorTextRunnable = new Runnable() {
@Override
public void run() {
- mErrorTextView.setTextColor(
- mErrorTextView.getResources().getColor(R.color.hint_color, null));
mErrorTextView.setText(
mErrorTextView.getResources().getString(R.string.fingerprint_hint));
mIcon.setImageResource(R.drawable.ic_fp_40px);
@@ -147,4 +144,4 @@ public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallba
void onError();
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/me/impy/aegis/helpers/AuthHelper.java b/app/src/main/java/me/impy/aegis/helpers/AuthHelper.java
new file mode 100644
index 00000000..df7f17bd
--- /dev/null
+++ b/app/src/main/java/me/impy/aegis/helpers/AuthHelper.java
@@ -0,0 +1,38 @@
+package me.impy.aegis.helpers;
+
+import android.text.Editable;
+import android.widget.EditText;
+
+import java.util.Arrays;
+
+import me.impy.aegis.crypto.CryptoUtils;
+
+public class AuthHelper {
+ private AuthHelper() {
+ }
+
+ public static char[] getPassword(EditText text, boolean clear) {
+ char[] password = getEditTextChars(text);
+ if (clear) {
+ text.getText().clear();
+ }
+ return password;
+ }
+
+ public static char[] getEditTextChars(EditText text) {
+ Editable editable = text.getText();
+ char[] chars = new char[editable.length()];
+ editable.getChars(0, editable.length(), chars, 0);
+ return chars;
+ }
+
+ public static boolean arePasswordsEqual(EditText text1, EditText text2) {
+ char[] password = getEditTextChars(text1);
+ char[] passwordConfirm = getEditTextChars(text2);
+ boolean equal = password.length != 0 && Arrays.equals(password, passwordConfirm);
+ CryptoUtils.zero(password);
+ CryptoUtils.zero(passwordConfirm);
+ return equal;
+ }
+
+}
diff --git a/app/src/main/res/layout/activity_auth.xml b/app/src/main/res/layout/activity_auth.xml
index 39bba448..7fec3096 100644
--- a/app/src/main/res/layout/activity_auth.xml
+++ b/app/src/main/res/layout/activity_auth.xml
@@ -8,8 +8,8 @@
tools:context="me.impy.aegis.AuthActivity">
@@ -40,5 +40,26 @@
android:layout_height="wrap_content"
android:text="Decrypt" />
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_authenticated_slide.xml b/app/src/main/res/layout/fragment_authenticated_slide.xml
index 65f0c990..be01fb9b 100644
--- a/app/src/main/res/layout/fragment_authenticated_slide.xml
+++ b/app/src/main/res/layout/fragment_authenticated_slide.xml
@@ -17,7 +17,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+