diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5ff4f1c0..4bf5b3a6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -7,6 +7,7 @@
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.USE_FINGERPRINT" />
 
     <application
         android:allowBackup="true"
diff --git a/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java b/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java
index a1726074..82bc40a8 100644
--- a/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java
+++ b/app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java
@@ -16,12 +16,15 @@
 
 package com.m2049r.xmrwallet;
 
+import android.app.AlertDialog;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.design.widget.TextInputLayout;
 import android.support.v4.app.Fragment;
 import android.text.Editable;
+import android.text.Html;
 import android.text.InputType;
 import android.text.TextWatcher;
 import android.view.KeyEvent;
@@ -32,21 +35,23 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.view.inputmethod.EditorInfo;
 import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.Switch;
 import android.widget.TextView;
 
+import com.m2049r.xmrwallet.model.Wallet;
+import com.m2049r.xmrwallet.model.WalletManager;
+import com.m2049r.xmrwallet.util.FingerprintHelper;
+import com.m2049r.xmrwallet.util.Helper;
 import com.m2049r.xmrwallet.util.KeyStoreHelper;
 import com.m2049r.xmrwallet.util.RestoreHeight;
 import com.m2049r.xmrwallet.widget.Toolbar;
-import com.m2049r.xmrwallet.model.Wallet;
-import com.m2049r.xmrwallet.model.WalletManager;
-import com.m2049r.xmrwallet.util.Helper;
 import com.nulabinc.zxcvbn.Strength;
 import com.nulabinc.zxcvbn.Zxcvbn;
 
 import java.io.File;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.util.Calendar;
 
 import timber.log.Timber;
 
@@ -60,6 +65,7 @@ public class GenerateFragment extends Fragment {
 
     private TextInputLayout etWalletName;
     private TextInputLayout etWalletPassword;
+    private LinearLayout llFingerprintAuth;
     private TextInputLayout etWalletAddress;
     private TextInputLayout etWalletMnemonic;
     private TextInputLayout etWalletViewKey;
@@ -80,6 +86,7 @@ public class GenerateFragment extends Fragment {
 
         etWalletName = (TextInputLayout) view.findViewById(R.id.etWalletName);
         etWalletPassword = (TextInputLayout) view.findViewById(R.id.etWalletPassword);
+        llFingerprintAuth = (LinearLayout) view.findViewById(R.id.llFingerprintAuth);
         etWalletMnemonic = (TextInputLayout) view.findViewById(R.id.etWalletMnemonic);
         etWalletAddress = (TextInputLayout) view.findViewById(R.id.etWalletAddress);
         etWalletViewKey = (TextInputLayout) view.findViewById(R.id.etWalletViewKey);
@@ -147,6 +154,30 @@ public class GenerateFragment extends Fragment {
             }
         });
 
+        if (FingerprintHelper.isDeviceSupported(getContext())) {
+            llFingerprintAuth.setVisibility(View.VISIBLE);
+
+            final Switch swFingerprintAllowed = (Switch) llFingerprintAuth.getChildAt(0);
+            swFingerprintAllowed.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View view) {
+                    if (!swFingerprintAllowed.isChecked()) return;
+
+                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+                    builder.setMessage(Html.fromHtml(getString(R.string.generate_fingerprint_warn)))
+                            .setCancelable(false)
+                            .setPositiveButton(getString(R.string.label_ok), null)
+                            .setNegativeButton(getString(R.string.label_cancel), new DialogInterface.OnClickListener() {
+                                @Override
+                                public void onClick(DialogInterface dialogInterface, int i) {
+                                    swFingerprintAllowed.setChecked(false);
+                                }
+                            })
+                            .show();
+                }
+            });
+        }
+
         if (type.equals(TYPE_NEW)) {
             etWalletPassword.getEditText().setImeOptions(EditorInfo.IME_ACTION_DONE);
             etWalletPassword.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
@@ -424,6 +455,7 @@ public class GenerateFragment extends Fragment {
 
         String name = etWalletName.getEditText().getText().toString();
         String password = etWalletPassword.getEditText().getText().toString();
+        boolean fingerprintAuthAllowed = ((Switch) llFingerprintAuth.getChildAt(0)).isChecked();
 
         // create the real wallet password
         String crazyPass = KeyStoreHelper.getCrazyPass(getActivity(), password);
@@ -433,11 +465,17 @@ public class GenerateFragment extends Fragment {
 
         if (type.equals(TYPE_NEW)) {
             bGenerate.setEnabled(false);
+            if (fingerprintAuthAllowed) {
+                KeyStoreHelper.saveWalletUserPass(getActivity(), name, password);
+            }
             activityCallback.onGenerate(name, crazyPass);
         } else if (type.equals(TYPE_SEED)) {
             if (!checkMnemonic()) return;
             String seed = etWalletMnemonic.getEditText().getText().toString();
             bGenerate.setEnabled(false);
+            if (fingerprintAuthAllowed) {
+                KeyStoreHelper.saveWalletUserPass(getActivity(), name, password);
+            }
             activityCallback.onGenerate(name, crazyPass, seed, height);
         } else if (type.equals(TYPE_KEY) || type.equals(TYPE_VIEWONLY)) {
             if (checkAddress() && checkViewKey() && checkSpendKey()) {
@@ -448,6 +486,9 @@ public class GenerateFragment extends Fragment {
                 if (type.equals(TYPE_KEY)) {
                     spendKey = etWalletSpendKey.getEditText().getText().toString();
                 }
+                if (fingerprintAuthAllowed) {
+                    KeyStoreHelper.saveWalletUserPass(getActivity(), name, password);
+                }
                 activityCallback.onGenerate(name, crazyPass, address, viewKey, spendKey, height);
             }
         }
diff --git a/app/src/main/java/com/m2049r/xmrwallet/GenerateReviewFragment.java b/app/src/main/java/com/m2049r/xmrwallet/GenerateReviewFragment.java
index b99a271b..cabcb830 100644
--- a/app/src/main/java/com/m2049r/xmrwallet/GenerateReviewFragment.java
+++ b/app/src/main/java/com/m2049r/xmrwallet/GenerateReviewFragment.java
@@ -25,6 +25,7 @@ import android.support.annotation.Nullable;
 import android.support.design.widget.TextInputLayout;
 import android.support.v4.app.Fragment;
 import android.text.Editable;
+import android.text.Html;
 import android.text.TextWatcher;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -38,18 +39,21 @@ import android.widget.ImageButton;
 import android.widget.LinearLayout;
 import android.widget.ProgressBar;
 import android.widget.ScrollView;
+import android.widget.Switch;
 import android.widget.TextView;
 import android.widget.Toast;
 
 import com.m2049r.xmrwallet.model.NetworkType;
-import com.m2049r.xmrwallet.util.KeyStoreHelper;
-import com.m2049r.xmrwallet.widget.Toolbar;
 import com.m2049r.xmrwallet.model.Wallet;
 import com.m2049r.xmrwallet.model.WalletManager;
+import com.m2049r.xmrwallet.util.FingerprintHelper;
 import com.m2049r.xmrwallet.util.Helper;
+import com.m2049r.xmrwallet.util.KeyStoreHelper;
 import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
+import com.m2049r.xmrwallet.widget.Toolbar;
 
 import java.io.File;
+import java.security.KeyStoreException;
 
 import timber.log.Timber;
 
@@ -369,12 +373,21 @@ public class GenerateReviewFragment extends Fragment {
 
         @Override
         protected Boolean doInBackground(String... params) {
-            if (params.length != 3) return false;
+            if (params.length != 4) return false;
             File walletFile = Helper.getWalletFile(getActivity(), params[0]);
             String oldPassword = params[1];
             String userPassword = params[2];
+            boolean fingerprintAuthAllowed = Boolean.valueOf(params[3]);
             newPassword = KeyStoreHelper.getCrazyPass(getActivity(), userPassword);
-            return changeWalletPassword(newPassword);
+            boolean success = changeWalletPassword(newPassword);
+            if (success) {
+                if (fingerprintAuthAllowed) {
+                    KeyStoreHelper.saveWalletUserPass(getActivity(), walletName, userPassword);
+                } else {
+                    KeyStoreHelper.removeWalletUserPass(getActivity(), walletName);
+                }
+            }
+            return success;
         }
 
         @Override
@@ -410,6 +423,37 @@ public class GenerateReviewFragment extends Fragment {
         final TextInputLayout etPasswordB = (TextInputLayout) promptsView.findViewById(R.id.etWalletPasswordB);
         etPasswordB.setHint(getString(R.string.prompt_changepwB, walletName));
 
+        LinearLayout llFingerprintAuth = (LinearLayout) promptsView.findViewById(R.id.llFingerprintAuth);
+        final Switch swFingerprintAllowed = (Switch) llFingerprintAuth.getChildAt(0);
+        if (FingerprintHelper.isDeviceSupported(getActivity())) {
+            llFingerprintAuth.setVisibility(View.VISIBLE);
+
+            swFingerprintAllowed.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View view) {
+                    if (!swFingerprintAllowed.isChecked()) return;
+
+                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+                    builder.setMessage(Html.fromHtml(getString(R.string.generate_fingerprint_warn)))
+                            .setCancelable(false)
+                            .setPositiveButton(getString(R.string.label_ok), null)
+                            .setNegativeButton(getString(R.string.label_cancel), new DialogInterface.OnClickListener() {
+                                @Override
+                                public void onClick(DialogInterface dialogInterface, int i) {
+                                    swFingerprintAllowed.setChecked(false);
+                                }
+                            })
+                            .show();
+                }
+            });
+
+            try {
+                swFingerprintAllowed.setChecked(FingerprintHelper.isFingerprintAuthAllowed(walletName));
+            } catch (KeyStoreException ex) {
+                ex.printStackTrace();
+            }
+        }
+
         etPasswordA.getEditText().addTextChangedListener(new TextWatcher() {
             @Override
             public void afterTextChanged(Editable s) {
@@ -483,7 +527,7 @@ public class GenerateReviewFragment extends Fragment {
                         } else if (!newPasswordA.equals(newPasswordB)) {
                             etPasswordB.setError(getString(R.string.generate_bad_passwordB));
                         } else if (newPasswordA.equals(newPasswordB)) {
-                            new AsyncChangePassword().execute(walletName, walletPassword, newPasswordA);
+                            new AsyncChangePassword().execute(walletName, walletPassword, newPasswordA, Boolean.toString(swFingerprintAllowed.isChecked()));
                             Helper.hideKeyboardAlways(getActivity());
                             openDialog.dismiss();
                             openDialog = null;
@@ -505,7 +549,7 @@ public class GenerateReviewFragment extends Fragment {
                     } else if (!newPasswordA.equals(newPasswordB)) {
                         etPasswordB.setError(getString(R.string.generate_bad_passwordB));
                     } else if (newPasswordA.equals(newPasswordB)) {
-                        new AsyncChangePassword().execute(walletName, walletPassword, newPasswordA);
+                        new AsyncChangePassword().execute(walletName, walletPassword, newPasswordA, Boolean.toString(swFingerprintAllowed.isChecked()));
                         Helper.hideKeyboardAlways(getActivity());
                         openDialog.dismiss();
                         openDialog = null;
diff --git a/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java b/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java
index 69cc5c84..b4473cad 100644
--- a/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java
+++ b/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java
@@ -29,18 +29,14 @@ import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
 import android.support.annotation.NonNull;
-import android.support.design.widget.TextInputLayout;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentTransaction;
-import android.text.Editable;
-import android.text.TextWatcher;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.inputmethod.EditorInfo;
-import android.widget.Button;
 import android.widget.EditText;
 import android.widget.TextView;
 import android.widget.Toast;
@@ -54,7 +50,7 @@ import com.m2049r.xmrwallet.model.NetworkType;
 import com.m2049r.xmrwallet.model.Wallet;
 import com.m2049r.xmrwallet.model.WalletManager;
 import com.m2049r.xmrwallet.service.WalletService;
-import com.m2049r.xmrwallet.util.CrazyPassEncoder;
+import com.m2049r.xmrwallet.util.FingerprintHelper;
 import com.m2049r.xmrwallet.util.Helper;
 import com.m2049r.xmrwallet.util.KeyStoreHelper;
 import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
@@ -67,6 +63,7 @@ import java.io.IOException;
 import java.net.Socket;
 import java.net.SocketAddress;
 import java.nio.channels.FileChannel;
+import java.security.KeyStoreException;
 import java.util.Date;
 
 import timber.log.Timber;
@@ -179,9 +176,9 @@ public class LoginActivity extends SecureActivity
                     case DialogInterface.BUTTON_POSITIVE:
                         final File walletFile = Helper.getWalletFile(LoginActivity.this, walletName);
                         if (WalletManager.getInstance().walletExists(walletFile)) {
-                            promptPassword(walletName, new PasswordAction() {
+                            Helper.promptPassword(LoginActivity.this, walletName, true, new Helper.PasswordAction() {
                                 @Override
-                                public void action(String walletName, String password) {
+                                public void action(String walletName, String password, boolean fingerprintUsed) {
                                     startDetails(walletFile, password, GenerateReviewFragment.VIEW_TYPE_DETAILS);
                                 }
                             });
@@ -211,9 +208,9 @@ public class LoginActivity extends SecureActivity
         if (checkServiceRunning()) return;
         final File walletFile = Helper.getWalletFile(this, walletName);
         if (WalletManager.getInstance().walletExists(walletFile)) {
-            promptPassword(walletName, new PasswordAction() {
+            Helper.promptPassword(LoginActivity.this, walletName, false, new Helper.PasswordAction() {
                 @Override
-                public void action(String walletName, String password) {
+                public void action(String walletName, String password, boolean fingerprintUsed) {
                     startReceive(walletFile, password);
                 }
             });
@@ -234,7 +231,17 @@ public class LoginActivity extends SecureActivity
             if (params.length != 2) return false;
             File walletFile = Helper.getWalletFile(LoginActivity.this, params[0]);
             String newName = params[1];
-            return renameWallet(walletFile, newName);
+            boolean success = renameWallet(walletFile, newName);
+            try {
+                if (success && FingerprintHelper.isFingerprintAuthAllowed(params[0])) {
+                    String savedPass = KeyStoreHelper.loadWalletUserPass(LoginActivity.this, params[0]);
+                    KeyStoreHelper.saveWalletUserPass(LoginActivity.this, newName, savedPass);
+                    KeyStoreHelper.removeWalletUserPass(LoginActivity.this, params[0]);
+                }
+            } catch (KeyStoreException ex) {
+                ex.printStackTrace();
+            }
+            return success;
         }
 
         @Override
@@ -381,6 +388,7 @@ public class LoginActivity extends SecureActivity
             if (params.length != 1) return false;
             String walletName = params[0];
             if (backupWallet(walletName) && deleteWallet(Helper.getWalletFile(LoginActivity.this, walletName))) {
+                KeyStoreHelper.removeWalletUserPass(LoginActivity.this, walletName);
                 return true;
             } else {
                 return false;
@@ -460,110 +468,6 @@ public class LoginActivity extends SecureActivity
         startGenerateFragment(type);
     }
 
-    AlertDialog openDialog = null; // for preventing opening of multiple dialogs
-
-    void promptPassword(final String wallet, final PasswordAction action) {
-        if (openDialog != null) return; // we are already asking for password
-        Context context = LoginActivity.this;
-        LayoutInflater li = LayoutInflater.from(context);
-        View promptsView = li.inflate(R.layout.prompt_password, null);
-
-        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
-        alertDialogBuilder.setView(promptsView);
-
-        final TextInputLayout etPassword = (TextInputLayout) promptsView.findViewById(R.id.etPassword);
-        etPassword.setHint(LoginActivity.this.getString(R.string.prompt_password, wallet));
-
-        etPassword.getEditText().addTextChangedListener(new TextWatcher() {
-
-            @Override
-            public void afterTextChanged(Editable s) {
-                if (etPassword.getError() != null) {
-                    etPassword.setError(null);
-                }
-            }
-
-            @Override
-            public void beforeTextChanged(CharSequence s, int start,
-                                          int count, int after) {
-            }
-
-            @Override
-            public void onTextChanged(CharSequence s, int start,
-                                      int before, int count) {
-            }
-        });
-
-        // set dialog message
-        alertDialogBuilder
-                .setCancelable(false)
-                .setPositiveButton(getString(R.string.label_ok), null)
-                .setNegativeButton(getString(R.string.label_cancel),
-                        new DialogInterface.OnClickListener() {
-                            public void onClick(DialogInterface dialog, int id) {
-                                Helper.hideKeyboardAlways(LoginActivity.this);
-                                dialog.cancel();
-                                openDialog = null;
-                            }
-                        });
-        openDialog = alertDialogBuilder.create();
-
-        openDialog.setOnShowListener(new DialogInterface.OnShowListener() {
-            @Override
-            public void onShow(DialogInterface dialog) {
-                Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
-                button.setOnClickListener(new View.OnClickListener() {
-                    @Override
-                    public void onClick(View view) {
-                        String pass = etPassword.getEditText().getText().toString();
-                        if (processPasswordEntry(wallet, pass, action)) {
-                            Helper.hideKeyboardAlways(LoginActivity.this);
-                            openDialog.dismiss();
-                            openDialog = null;
-                        } else {
-                            etPassword.setError(getString(R.string.bad_password));
-                        }
-                    }
-                });
-            }
-        });
-
-        // accept keyboard "ok"
-        etPassword.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
-            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
-                if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
-                    String pass = etPassword.getEditText().getText().toString();
-                    if (processPasswordEntry(wallet, pass, action)) {
-                        Helper.hideKeyboardAlways(LoginActivity.this);
-                        openDialog.dismiss();
-                        openDialog = null;
-                    } else {
-                        etPassword.setError(getString(R.string.bad_password));
-                    }
-                    return true;
-                }
-                return false;
-            }
-        });
-
-        Helper.showKeyboard(openDialog);
-        openDialog.show();
-    }
-
-    interface PasswordAction {
-        void action(String walletName, String password);
-    }
-
-    private boolean processPasswordEntry(String walletName, String pass, PasswordAction action) {
-        String walletPassword = Helper.getWalletPassword(getApplicationContext(), walletName, pass);
-        if (walletPassword != null) {
-            action.action(walletName, walletPassword);
-            return true;
-        } else {
-            return false;
-        }
-    }
-
     ////////////////////////////////////////
     // LoginFragment.Listener
     ////////////////////////////////////////
@@ -699,11 +603,12 @@ public class LoginActivity extends SecureActivity
         }
     }
 
-    void startWallet(String walletName, String walletPassword) {
+    void startWallet(String walletName, String walletPassword, boolean fingerprintUsed) {
         Timber.d("startWallet()");
         Intent intent = new Intent(getApplicationContext(), WalletActivity.class);
         intent.putExtra(WalletActivity.REQUEST_ID, walletName);
         intent.putExtra(WalletActivity.REQUEST_PW, walletPassword);
+        intent.putExtra(WalletActivity.REQUEST_FINGERPRINT_USED, fingerprintUsed);
         startActivity(intent);
     }
 
@@ -1193,10 +1098,10 @@ public class LoginActivity extends SecureActivity
         File walletFile = Helper.getWalletFile(this, walletNode.getName());
         if (WalletManager.getInstance().walletExists(walletFile)) {
             WalletManager.getInstance().setDaemon(walletNode);
-            promptPassword(walletNode.getName(), new PasswordAction() {
+            Helper.promptPassword(LoginActivity.this, walletNode.getName(), false, new Helper.PasswordAction() {
                 @Override
-                public void action(String walletName, String password) {
-                    startWallet(walletName, password);
+                public void action(String walletName, String password, boolean fingerprintUsed) {
+                    startWallet(walletName, password, fingerprintUsed);
                 }
             });
         } else { // this cannot really happen as we prefilter choices
diff --git a/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java b/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java
index a7c3fb4f..881e8e33 100644
--- a/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java
+++ b/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java
@@ -53,6 +53,7 @@ import com.m2049r.xmrwallet.layout.WalletInfoAdapter;
 import com.m2049r.xmrwallet.model.NetworkType;
 import com.m2049r.xmrwallet.model.WalletManager;
 import com.m2049r.xmrwallet.util.Helper;
+import com.m2049r.xmrwallet.util.KeyStoreHelper;
 import com.m2049r.xmrwallet.util.NodeList;
 import com.m2049r.xmrwallet.util.Notice;
 import com.m2049r.xmrwallet.widget.DropDownEditText;
@@ -61,6 +62,7 @@ import com.m2049r.xmrwallet.widget.Toolbar;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import timber.log.Timber;
 
@@ -311,6 +313,17 @@ public class LoginFragment extends Fragment implements WalletInfoAdapter.OnInter
                 ivGunther.setImageDrawable(null);
             }
         }
+
+        // remove information of non-existent wallet
+        Set<String> removedWallets = getActivity()
+                .getSharedPreferences(KeyStoreHelper.SecurityConstants.WALLET_PASS_PREFS_NAME, Context.MODE_PRIVATE)
+                .getAll().keySet();
+        for (WalletManager.WalletInfo s : walletList) {
+            removedWallets.remove(s.name);
+        }
+        for (String name : removedWallets) {
+            KeyStoreHelper.removeWalletUserPass(getActivity(), name);
+        }
     }
 
     private void showInfo(@NonNull String name) {
diff --git a/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java b/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java
index 4a2c8d71..abfd24f5 100644
--- a/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java
+++ b/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java
@@ -49,8 +49,6 @@ import com.m2049r.xmrwallet.util.Helper;
 import com.m2049r.xmrwallet.util.UserNotes;
 import com.m2049r.xmrwallet.widget.Toolbar;
 
-import java.io.File;
-
 import timber.log.Timber;
 
 public class WalletActivity extends SecureActivity implements WalletFragment.Listener,
@@ -62,8 +60,10 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
 
     public static final String REQUEST_ID = "id";
     public static final String REQUEST_PW = "pw";
+    public static final String REQUEST_FINGERPRINT_USED = "fingerprint";
 
     private Toolbar toolbar;
+    private boolean needVerifyIdentity;
 
     @Override
     public void setToolbarButton(int type) {
@@ -120,6 +120,7 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
             acquireWakeLock();
             String walletId = extras.getString(REQUEST_ID);
             String walletPassword = extras.getString(REQUEST_PW);
+            needVerifyIdentity = extras.getBoolean(REQUEST_FINGERPRINT_USED);
             connectWalletService(walletId, walletPassword);
         } else {
             finish();
@@ -397,7 +398,17 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
 
     @Override
     public void onSendRequest() {
-        replaceFragment(new SendFragment(), null, null);
+        if (needVerifyIdentity) {
+            Helper.promptPassword(WalletActivity.this, getWallet().getName(), true, new Helper.PasswordAction() {
+                @Override
+                public void action(String walletName, String password, boolean fingerprintUsed) {
+                    replaceFragment(new SendFragment(), null, null);
+                    needVerifyIdentity = false;
+                }
+            });
+        } else {
+            replaceFragment(new SendFragment(), null, null);
+        }
     }
 
     @Override
@@ -697,10 +708,22 @@ public class WalletActivity extends SecureActivity implements WalletFragment.Lis
             public void onClick(DialogInterface dialog, int which) {
                 switch (which) {
                     case DialogInterface.BUTTON_POSITIVE:
-                        Bundle extras = new Bundle();
+                        final Bundle extras = new Bundle();
                         extras.putString("type", GenerateReviewFragment.VIEW_TYPE_WALLET);
                         extras.putString("password", getIntent().getExtras().getString(REQUEST_PW));
-                        replaceFragment(new GenerateReviewFragment(), null, extras);
+
+                        if (needVerifyIdentity) {
+                            Helper.promptPassword(WalletActivity.this, getWallet().getName(), true, new Helper.PasswordAction() {
+                                @Override
+                                public void action(String walletName, String password, boolean fingerprintUsed) {
+                                    replaceFragment(new GenerateReviewFragment(), null, extras);
+                                    needVerifyIdentity = false;
+                                }
+                            });
+                        } else {
+                            replaceFragment(new GenerateReviewFragment(), null, extras);
+                        }
+
                         break;
                     case DialogInterface.BUTTON_NEGATIVE:
                         // do nothing
diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/FingerprintHelper.java b/app/src/main/java/com/m2049r/xmrwallet/util/FingerprintHelper.java
new file mode 100644
index 00000000..46de0364
--- /dev/null
+++ b/app/src/main/java/com/m2049r/xmrwallet/util/FingerprintHelper.java
@@ -0,0 +1,40 @@
+package com.m2049r.xmrwallet.util;
+
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.support.v4.hardware.fingerprint.FingerprintManagerCompat;
+import android.support.v4.os.CancellationSignal;
+
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+
+public class FingerprintHelper {
+
+    public static boolean isDeviceSupported(Context context) {
+        FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.from(context);
+        KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
+
+        return keyguardManager != null &&
+                keyguardManager.isKeyguardSecure() &&
+                fingerprintManager.isHardwareDetected() &&
+                fingerprintManager.hasEnrolledFingerprints();
+    }
+
+    public static boolean isFingerprintAuthAllowed(String wallet) throws KeyStoreException {
+        KeyStore keyStore = KeyStore.getInstance(KeyStoreHelper.SecurityConstants.KEYSTORE_PROVIDER_ANDROID_KEYSTORE);
+        try {
+            keyStore.load(null);
+        } catch (Exception ex) {
+            throw new IllegalStateException("Could not load KeyStore", ex);
+        }
+
+        return keyStore.containsAlias(KeyStoreHelper.SecurityConstants.WALLET_PASS_KEY_PREFIX + wallet);
+    }
+
+    public static void authenticate(Context context, CancellationSignal cancelSignal,
+                                    FingerprintManagerCompat.AuthenticationCallback callback) {
+        FingerprintManagerCompat manager = FingerprintManagerCompat.from(context);
+        manager.authenticate(null, 0, cancelSignal, callback, null);
+    }
+
+}
diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java b/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java
index b50fa1e4..510134d6 100644
--- a/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java
+++ b/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java
@@ -18,10 +18,12 @@ package com.m2049r.xmrwallet.util;
 
 import android.Manifest;
 import android.app.Activity;
+import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -30,13 +32,24 @@ import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.VectorDrawable;
 import android.os.Environment;
+import android.support.design.widget.TextInputLayout;
 import android.support.v4.content.ContextCompat;
+import android.support.v4.hardware.fingerprint.FingerprintManagerCompat;
+import android.support.v4.os.CancellationSignal;
 import android.system.ErrnoException;
 import android.system.Os;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
 import android.view.WindowManager;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
+import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.TextView;
 
 import com.m2049r.xmrwallet.BuildConfig;
 import com.m2049r.xmrwallet.R;
@@ -51,6 +64,7 @@ import java.math.BigInteger;
 import java.net.MalformedURLException;
 import java.net.SocketTimeoutException;
 import java.net.URL;
+import java.security.KeyStoreException;
 import java.util.Locale;
 
 import javax.net.ssl.HttpsURLConnection;
@@ -340,4 +354,150 @@ public class Helper {
 
         return null;
     }
+
+    static AlertDialog openDialog = null; // for preventing opening of multiple dialogs
+
+    static public void promptPassword(final Context context, final String wallet, boolean fingerprintDisabled, final PasswordAction action) {
+        if (openDialog != null) return; // we are already asking for password
+        LayoutInflater li = LayoutInflater.from(context);
+        final View promptsView = li.inflate(R.layout.prompt_password, null);
+
+        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
+        alertDialogBuilder.setView(promptsView);
+
+        final TextInputLayout etPassword = (TextInputLayout) promptsView.findViewById(R.id.etPassword);
+        etPassword.setHint(context.getString(R.string.prompt_password, wallet));
+
+        boolean fingerprintAuthCheck;
+        try {
+            fingerprintAuthCheck = FingerprintHelper.isFingerprintAuthAllowed(wallet);
+        } catch (KeyStoreException ex) {
+            fingerprintAuthCheck = false;
+        }
+
+        final boolean fingerprintAuthAllowed = !fingerprintDisabled && fingerprintAuthCheck;
+        final CancellationSignal cancelSignal = new CancellationSignal();
+
+        if (fingerprintAuthAllowed) {
+            promptsView.findViewById(R.id.txtFingerprintAuth).setVisibility(View.VISIBLE);
+        }
+
+        etPassword.getEditText().addTextChangedListener(new TextWatcher() {
+
+            @Override
+            public void afterTextChanged(Editable s) {
+                if (etPassword.getError() != null) {
+                    etPassword.setError(null);
+                }
+            }
+
+            @Override
+            public void beforeTextChanged(CharSequence s, int start,
+                                          int count, int after) {
+            }
+
+            @Override
+            public void onTextChanged(CharSequence s, int start,
+                                      int before, int count) {
+            }
+        });
+
+        // set dialog message
+        alertDialogBuilder
+                .setCancelable(false)
+                .setPositiveButton(context.getString(R.string.label_ok), null)
+                .setNegativeButton(context.getString(R.string.label_cancel),
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int id) {
+                                Helper.hideKeyboardAlways((Activity) context);
+                                cancelSignal.cancel();
+                                dialog.cancel();
+                                openDialog = null;
+                            }
+                        });
+        openDialog = alertDialogBuilder.create();
+
+        final FingerprintManagerCompat.AuthenticationCallback fingerprintAuthCallback = new FingerprintManagerCompat.AuthenticationCallback() {
+            @Override
+            public void onAuthenticationError(int errMsgId, CharSequence errString) {
+                ((TextView) promptsView.findViewById(R.id.txtFingerprintAuth)).setText(errString);
+            }
+
+            @Override
+            public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
+                String userPass = KeyStoreHelper.loadWalletUserPass(context, wallet);
+                if (Helper.processPasswordEntry(context, wallet, userPass, true, action)) {
+                    Helper.hideKeyboardAlways((Activity) context);
+                    openDialog.dismiss();
+                    openDialog = null;
+                } else {
+                    etPassword.setError(context.getString(R.string.bad_password));
+                }
+            }
+
+            @Override
+            public void onAuthenticationFailed() {
+                ((TextView) promptsView.findViewById(R.id.txtFingerprintAuth))
+                        .setText(context.getString(R.string.bad_fingerprint));
+            }
+        };
+
+        openDialog.setOnShowListener(new DialogInterface.OnShowListener() {
+            @Override
+            public void onShow(DialogInterface dialog) {
+                if (fingerprintAuthAllowed) {
+                    FingerprintHelper.authenticate(context, cancelSignal, fingerprintAuthCallback);
+                }
+                Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
+                button.setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View view) {
+                        String pass = etPassword.getEditText().getText().toString();
+                        if (processPasswordEntry(context, wallet, pass, false, action)) {
+                            Helper.hideKeyboardAlways((Activity) context);
+                            openDialog.dismiss();
+                            openDialog = null;
+                        } else {
+                            etPassword.setError(context.getString(R.string.bad_password));
+                        }
+                    }
+                });
+            }
+        });
+
+        // accept keyboard "ok"
+        etPassword.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
+            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+                if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
+                    String pass = etPassword.getEditText().getText().toString();
+                    if (processPasswordEntry(context, wallet, pass, false, action)) {
+                        Helper.hideKeyboardAlways((Activity) context);
+                        openDialog.dismiss();
+                        openDialog = null;
+                    } else {
+                        etPassword.setError(context.getString(R.string.bad_password));
+                    }
+                    return true;
+                }
+                return false;
+            }
+        });
+
+        Helper.showKeyboard(openDialog);
+        openDialog.show();
+    }
+
+    public interface PasswordAction {
+        void action(String walletName, String password, boolean fingerprintUsed);
+    }
+
+    static private boolean processPasswordEntry(Context context, String walletName, String pass, boolean fingerprintUsed, PasswordAction action) {
+        String walletPassword = Helper.getWalletPassword(context, walletName, pass);
+        if (walletPassword != null) {
+            action.action(walletName, walletPassword, fingerprintUsed);
+            return true;
+        } else {
+            return false;
+        }
+    }
 }
diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/KeyStoreHelper.java b/app/src/main/java/com/m2049r/xmrwallet/util/KeyStoreHelper.java
index ea49cd54..281fd257 100644
--- a/app/src/main/java/com/m2049r/xmrwallet/util/KeyStoreHelper.java
+++ b/app/src/main/java/com/m2049r/xmrwallet/util/KeyStoreHelper.java
@@ -23,6 +23,7 @@ import android.os.Build;
 import android.security.KeyPairGeneratorSpec;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
+import android.util.Base64;
 
 import java.math.BigInteger;
 import java.nio.charset.StandardCharsets;
@@ -35,11 +36,13 @@ import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
 import java.security.PrivateKey;
+import java.security.PublicKey;
 import java.security.Signature;
 import java.security.SignatureException;
 import java.util.Calendar;
 import java.util.GregorianCalendar;
 
+import javax.crypto.Cipher;
 import javax.security.auth.x500.X500Principal;
 
 import timber.log.Timber;
@@ -71,6 +74,41 @@ public class KeyStoreHelper {
         return CrazyPassEncoder.encode(cnSlowHash(sig));
     }
 
+    public static void saveWalletUserPass(Context context, String wallet, String password) {
+        String walletKeyAlias = SecurityConstants.WALLET_PASS_KEY_PREFIX + wallet;
+        byte[] data = password.getBytes(StandardCharsets.UTF_8);
+        try {
+            KeyStoreHelper.createKeys(context, walletKeyAlias);
+            byte[] encrypted = KeyStoreHelper.encrypt(walletKeyAlias, data);
+            context.getSharedPreferences(SecurityConstants.WALLET_PASS_PREFS_NAME, Context.MODE_PRIVATE).edit()
+                    .putString(wallet, Base64.encodeToString(encrypted, Base64.DEFAULT))
+                    .apply();
+        } catch (Exception ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    public static String loadWalletUserPass(Context context, String wallet) {
+        String walletKeyAlias = SecurityConstants.WALLET_PASS_KEY_PREFIX + wallet;
+        String encoded = context.getSharedPreferences(SecurityConstants.WALLET_PASS_PREFS_NAME, Context.MODE_PRIVATE)
+                .getString(wallet, "");
+        byte[] data = Base64.decode(encoded, Base64.DEFAULT);
+        byte[] decrypted = KeyStoreHelper.decrypt(walletKeyAlias, data);
+
+        return new String(decrypted, StandardCharsets.UTF_8);
+    }
+
+    public static void removeWalletUserPass(Context context, String wallet) {
+        String walletKeyAlias = SecurityConstants.WALLET_PASS_KEY_PREFIX + wallet;
+        try {
+            KeyStoreHelper.deleteKeys(walletKeyAlias);
+            context.getSharedPreferences(SecurityConstants.WALLET_PASS_PREFS_NAME, Context.MODE_PRIVATE).edit()
+                    .remove(wallet).apply();
+        } catch (Exception ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
     /**
      * Creates a public and private key and stores it using the Android Key
      * Store, so that only this application will be able to access the keys.
@@ -132,9 +170,10 @@ public class KeyStoreHelper {
                     KeyProperties.KEY_ALGORITHM_RSA, SecurityConstants.KEYSTORE_PROVIDER_ANDROID_KEYSTORE);
             keyPairGenerator.initialize(
                     new KeyGenParameterSpec.Builder(
-                            alias, KeyProperties.PURPOSE_SIGN)
+                            alias, KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                             .setDigests(KeyProperties.DIGEST_SHA256)
                             .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
+                            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
                             .build());
             KeyPair keyPair = keyPairGenerator.generateKeyPair();
             Timber.d("M Keys created");
@@ -166,6 +205,30 @@ public class KeyStoreHelper {
         }
     }
 
+    public static byte[] encrypt(String alias, byte[] data) {
+        try {
+            PublicKey publicKey = getPrivateKeyEntry(alias).getCertificate().getPublicKey();
+            Cipher cipher = Cipher.getInstance(SecurityConstants.CIPHER_RSA_ECB_PKCS1);
+
+            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+            return cipher.doFinal(data);
+        } catch (Exception ex) {
+            throw new IllegalStateException("Could not initialize RSA cipher", ex);
+        }
+    }
+
+    public static byte[] decrypt(String alias, byte[] data) {
+        try {
+            PrivateKey privateKey = getPrivateKeyEntry(alias).getPrivateKey();
+            Cipher cipher = Cipher.getInstance(SecurityConstants.CIPHER_RSA_ECB_PKCS1);
+
+            cipher.init(Cipher.DECRYPT_MODE, privateKey);
+            return cipher.doFinal(data);
+        } catch (Exception ex) {
+            throw new IllegalStateException("Could not initialize RSA cipher", ex);
+        }
+    }
+
     /**
      * Signs the data using the key pair stored in the Android Key Store. This
      * signature can be used with the data later to verify it was signed by this
@@ -213,5 +276,8 @@ public class KeyStoreHelper {
         String KEYSTORE_PROVIDER_ANDROID_KEYSTORE = "AndroidKeyStore";
         String TYPE_RSA = "RSA";
         String SIGNATURE_SHA256withRSA = "SHA256withRSA";
+        String CIPHER_RSA_ECB_PKCS1 = "RSA/ECB/PKCS1Padding";
+        String WALLET_PASS_PREFS_NAME = "wallet";
+        String WALLET_PASS_KEY_PREFIX = "walletKey-";
     }
 }
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_fingerprint.xml b/app/src/main/res/drawable/ic_fingerprint.xml
new file mode 100644
index 00000000..81eccc55
--- /dev/null
+++ b/app/src/main/res/drawable/ic_fingerprint.xml
@@ -0,0 +1,37 @@
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+        http://www.apache.org/licenses/LICENSE-2.0
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="32.0"
+    android:viewportHeight="32.0">
+
+    <path
+        android:fillColor="#6b8693"
+        android:pathData="M16,16m -16, 0a 16, 16 0 1, 0 32, 0a 16, 16 0 1, 0 -32, 0" />
+    <path
+        android:fillColor="#ffffff"
+        android:pathData="M23.7,5.9c-0.1,0.0 -0.2,0.0 -0.3,-0.1C21.0,4.5 18.6,3.9 16.0,3.9c-2.5,0.0 -4.6,0.6 -6.9,1.9C8.8,6.0 8.3,5.9 8.1,5.5C7.9,5.2 8.0,4.7 8.4,4.5c2.5,-1.4 4.9,-2.1 7.7,-2.1c2.8,0.0 5.4,0.7 8.0,2.1c0.4,0.2 0.5,0.6 0.3,1.0C24.2,5.7 24.0,5.9 23.7,5.9z"/>
+    <path
+        android:fillColor="#ffffff"
+        android:pathData="M5.3,13.2c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,-0.2 -0.4,-0.7 -0.2,-1.0c1.3,-1.9 2.9,-3.4 4.9,-4.5c4.1,-2.2 9.3,-2.2 13.4,0.0c1.9,1.1 3.6,2.5 4.9,4.4c0.2,0.3 0.1,0.8 -0.2,1.0c-0.3,0.2 -0.8,0.1 -1.0,-0.2c-1.2,-1.7 -2.6,-3.0 -4.3,-4.0c-3.7,-2.0 -8.3,-2.0 -12.0,0.0c-1.7,0.9 -3.2,2.3 -4.3,4.0C5.7,13.1 5.5,13.2 5.3,13.2z"/>
+    <path
+        android:fillColor="#ffffff"
+        android:pathData="M13.3,29.6c-0.2,0.0 -0.4,-0.1 -0.5,-0.2c-1.1,-1.2 -1.7,-2.0 -2.6,-3.6c-0.9,-1.7 -1.4,-3.7 -1.4,-5.9c0.0,-4.1 3.3,-7.4 7.4,-7.4c4.1,0.0 7.4,3.3 7.4,7.4c0.0,0.4 -0.3,0.7 -0.7,0.7s-0.7,-0.3 -0.7,-0.7c0.0,-3.3 -2.7,-5.9 -5.9,-5.9c-3.3,0.0 -5.9,2.7 -5.9,5.9c0.0,2.0 0.4,3.8 1.2,5.2c0.8,1.6 1.4,2.2 2.4,3.3c0.3,0.3 0.3,0.8 0.0,1.0C13.7,29.5 13.5,29.6 13.3,29.6z"/>
+    <path
+        android:fillColor="#ffffff"
+        android:pathData="M22.6,27.1c-1.6,0.0 -2.9,-0.4 -4.1,-1.2c-1.9,-1.4 -3.1,-3.6 -3.1,-6.0c0.0,-0.4 0.3,-0.7 0.7,-0.7s0.7,0.3 0.7,0.7c0.0,1.9 0.9,3.7 2.5,4.8c0.9,0.6 1.9,1.0 3.2,1.0c0.3,0.0 0.8,0.0 1.3,-0.1c0.4,-0.1 0.8,0.2 0.8,0.6c0.1,0.4 -0.2,0.8 -0.6,0.8C23.4,27.1 22.8,27.1 22.6,27.1z"/>
+    <path
+        android:fillColor="#ffffff"
+        android:pathData="M20.0,29.9c-0.1,0.0 -0.1,0.0 -0.2,0.0c-2.1,-0.6 -3.4,-1.4 -4.8,-2.9c-1.8,-1.9 -2.8,-4.4 -2.8,-7.1c0.0,-2.2 1.8,-4.1 4.1,-4.1c2.2,0.0 4.1,1.8 4.1,4.1c0.0,1.4 1.2,2.6 2.6,2.6c1.4,0.0 2.6,-1.2 2.6,-2.6c0.0,-5.1 -4.2,-9.3 -9.3,-9.3c-3.6,0.0 -6.9,2.1 -8.4,5.4C7.3,17.1 7.0,18.4 7.0,19.8c0.0,1.1 0.1,2.7 0.9,4.9c0.1,0.4 -0.1,0.8 -0.4,0.9c-0.4,0.1 -0.8,-0.1 -0.9,-0.4c-0.6,-1.8 -0.9,-3.6 -0.9,-5.4c0.0,-1.6 0.3,-3.1 0.9,-4.4c1.7,-3.8 5.6,-6.3 9.8,-6.3c5.9,0.0 10.7,4.8 10.7,10.7c0.0,2.2 -1.8,4.1 -4.1,4.1s-4.0,-1.8 -4.0,-4.1c0.0,-1.4 -1.2,-2.6 -2.6,-2.6c-1.4,0.0 -2.6,1.2 -2.6,2.6c0.0,2.3 0.9,4.5 2.4,6.1c1.2,1.3 2.4,2.0 4.2,2.5c0.4,0.1 0.6,0.5 0.5,0.9C20.6,29.7 20.3,29.9 20.0,29.9z"/>
+</vector>
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_generate.xml b/app/src/main/res/layout/fragment_generate.xml
index 517ba60c..976448a2 100644
--- a/app/src/main/res/layout/fragment_generate.xml
+++ b/app/src/main/res/layout/fragment_generate.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:layout_margin="8dp">
@@ -55,6 +56,27 @@
             </android.support.design.widget.TextInputLayout>
         </LinearLayout>
 
+        <LinearLayout
+            android:id="@+id/llFingerprintAuth"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:paddingBottom="16dp"
+            android:visibility="gone">
+
+            <Switch
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent" />
+
+            <TextView
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:gravity="center_vertical"
+                android:text="@string/generate_fingerprint_hint"
+                android:textSize="18sp" />
+        </LinearLayout>
+
         <android.support.design.widget.TextInputLayout
             android:id="@+id/etWalletMnemonic"
             android:layout_width="match_parent"
diff --git a/app/src/main/res/layout/prompt_changepw.xml b/app/src/main/res/layout/prompt_changepw.xml
index 94c3c33f..d66b2672 100644
--- a/app/src/main/res/layout/prompt_changepw.xml
+++ b/app/src/main/res/layout/prompt_changepw.xml
@@ -40,4 +40,24 @@
             android:textAlignment="textStart" />
     </android.support.design.widget.TextInputLayout>
 
+    <LinearLayout
+        android:id="@+id/llFingerprintAuth"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:visibility="gone">
+
+        <Switch
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent" />
+
+        <TextView
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:gravity="center_vertical"
+            android:text="@string/generate_fingerprint_hint"
+            android:textSize="18sp" />
+    </LinearLayout>
+
 </LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/prompt_password.xml b/app/src/main/res/layout/prompt_password.xml
index d39604d1..eea8413e 100644
--- a/app/src/main/res/layout/prompt_password.xml
+++ b/app/src/main/res/layout/prompt_password.xml
@@ -22,4 +22,14 @@
             android:inputType="textPassword" />
 
     </android.support.design.widget.TextInputLayout>
+
+    <TextView
+        android:id="@+id/txtFingerprintAuth"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:drawablePadding="10dp"
+        android:drawableStart="@drawable/ic_fingerprint"
+        android:gravity="center_vertical"
+        android:text="@string/prompt_fingerprint_auth"
+        android:visibility="gone" />
 </LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 04176f38..af99e107 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -91,7 +91,9 @@
     <string name="prompt_changepw">Nueva contraseña para %1$s</string>
     <string name="prompt_changepwB">Repetir contraseña para %1$s</string>
     <string name="prompt_password">Contraseña para %1$s</string>
+    <string name="prompt_fingerprint_auth">[You can also open wallet using fingerprint.\nPlease touch sensor.]</string>
     <string name="prompt_send_password">Confirmar Contraseña</string>
+    <string name="bad_fingerprint">[Fingerprint not recognized. Try again.]</string>
     <string name="bad_password">¡Contraseña incorrecta!</string>
     <string name="bad_wallet">¡El monedero no existe!</string>
     <string name="error_not_wallet">¡Esto no es un monedero!</string>
@@ -140,6 +142,19 @@
     <string name="generate_title">Crear monedero</string>
     <string name="generate_name_hint">Nombre del monedero</string>
     <string name="generate_password_hint">Frase de Contraseña</string>
+    <string name="generate_fingerprint_hint">[Allow to open wallet using fingerprint]</string>
+    <string name="generate_fingerprint_warn">[<![CDATA[
+        <strong>Fingerprint Authentication</strong>
+        <p>With fingerprint authentication enabled, you can view wallet balance and receive funds
+        without entering password.</p>
+        <p>But for additional security, monerujo will still require you to enter password when
+        viewing wallet details or sending funds.</p>
+        <strong>Security Warning</strong>
+        <p>Finally, monerujo wants to remind you that anyone who can get your fingerprint will be
+        able to peep into your wallet balance.</p>
+        <p>For instance, a malicious user around you can open your wallet when you are asleep.</p>
+        <strong>Are you sure to enable this function?</strong>
+    ]]>]</string>
     <string name="generate_bad_passwordB">Contraseñas no coinciden</string>
     <string name="generate_empty_passwordB">Contraseña no puede estar vacía</string>
     <string name="generate_buttonGenerate">¡Házme ya un monedero!</string>
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 0cbc3410..1cce7f6a 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -155,7 +155,9 @@
     <string name="prompt_changepw">[New Passphrase for %1$s]</string>
     <string name="prompt_changepwB">[Repeat Passphrase for %1$s]</string>
     <string name="prompt_password">Password per %1$s</string>
+    <string name="prompt_fingerprint_auth">[You can also open wallet using fingerprint.\nPlease touch sensor.]</string>
     <string name="prompt_send_password">Conferma Password</string>
+    <string name="bad_fingerprint">[Fingerprint not recognized. Try again.]</string>
     <string name="bad_password">Password errata!</string>
     <string name="bad_wallet">Il portafoglio non esiste!</string>
     <string name="error_not_wallet">Questo non è un portafoglio!</string>
@@ -207,6 +209,19 @@
     <string name="generate_title">Crea portafoglio</string>
     <string name="generate_name_hint">Nome del portafoglio</string>
     <string name="generate_password_hint">Passphrase del portafoglio</string>
+    <string name="generate_fingerprint_hint">[Allow to open wallet using fingerprint]</string>
+    <string name="generate_fingerprint_warn">[<![CDATA[
+        <strong>Fingerprint Authentication</strong>
+        <p>With fingerprint authentication enabled, you can view wallet balance and receive funds
+        without entering password.</p>
+        <p>But for additional security, monerujo will still require you to enter password when
+        viewing wallet details or sending funds.</p>
+        <strong>Security Warning</strong>
+        <p>Finally, monerujo wants to remind you that anyone who can get your fingerprint will be
+        able to peep into your wallet balance.</p>
+        <p>For instance, a malicious user around you can open your wallet when you are asleep.</p>
+        <strong>Are you sure to enable this function?</strong>
+    ]]>]</string>
     <string name="generate_bad_passwordB">[Passphrases do not match]</string>
     <string name="generate_empty_passwordB">[Passphrase may not be empty]</string>
     <string name="generate_buttonGenerate">Fammi subito un portafoglio!</string>
diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml
index 79ecb73c..7b2e7ebe 100644
--- a/app/src/main/res/values-nb/strings.xml
+++ b/app/src/main/res/values-nb/strings.xml
@@ -153,7 +153,9 @@
 	<string name="prompt_changepw">[Nytt passord for %1$s]</string>
 	<string name="prompt_changepwB">[Gjenta passord for %1$s]</string>
     <string name="prompt_password">Passord for %1$s</string>
+    <string name="prompt_fingerprint_auth">[You can also open wallet using fingerprint.\nPlease touch sensor.]</string>
     <string name="prompt_send_password">Bekreft passord</string>
+    <string name="bad_fingerprint">[Fingerprint not recognized. Try again.]</string>
     <string name="bad_password">Feil passord!</string>
     <string name="bad_wallet">Lommebok eksisterer ikke!</string>
     <string name="error_not_wallet">Dette er ikke en lommebok!</string>
@@ -205,6 +207,19 @@
     <string name="generate_title">Lag lommebok</string>
     <string name="generate_name_hint">Lommeboknavn</string>
     <string name="generate_password_hint">Lommebokpassord</string>
+    <string name="generate_fingerprint_hint">[Allow to open wallet using fingerprint]</string>
+    <string name="generate_fingerprint_warn">[<![CDATA[
+        <strong>Fingerprint Authentication</strong>
+        <p>With fingerprint authentication enabled, you can view wallet balance and receive funds
+        without entering password.</p>
+        <p>But for additional security, monerujo will still require you to enter password when
+        viewing wallet details or sending funds.</p>
+        <strong>Security Warning</strong>
+        <p>Finally, monerujo wants to remind you that anyone who can get your fingerprint will be
+        able to peep into your wallet balance.</p>
+        <p>For instance, a malicious user around you can open your wallet when you are asleep.</p>
+        <strong>Are you sure to enable this function?</strong>
+    ]]>]</string>
     <string name="generate_bad_passwordB">[Passordene stemmer ikke overens]</string>
     <string name="generate_empty_passwordB">[Passord kan ikke være tomt]</string>
     <string name="generate_buttonGenerate">Lag meg en lommebok!</string>
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 1793bb05..b04945bb 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -155,7 +155,9 @@
     <string name="prompt_changepw">為 %1$s 設定新密碼</string>
     <string name="prompt_changepwB">重複輸入 %1$s 的密碼</string>
     <string name="prompt_password">%1$s 的密碼</string>
+    <string name="prompt_fingerprint_auth">你也可以使用指紋來開啟錢包。\n請輕觸你的指紋感應器。</string>
     <string name="prompt_send_password">確認密碼</string>
+    <string name="bad_fingerprint">無法辨識的指紋,請再試一次。</string>
     <string name="bad_password">密碼錯誤!</string>
     <string name="bad_wallet">錢包不存在!</string>
     <string name="error_not_wallet">這不是錢包!</string>
@@ -207,6 +209,16 @@
     <string name="generate_title">建立錢包</string>
     <string name="generate_name_hint">錢包名稱</string>
     <string name="generate_password_hint">錢包密碼</string>
+    <string name="generate_fingerprint_hint">允許使用指紋開啟錢包</string>
+    <string name="generate_fingerprint_warn"><![CDATA[
+        <strong>指紋驗證</strong>
+        <p>啟用指紋驗證後,您可以觀看錢包餘額並接收資金,而無需輸入密碼。</p>
+        <p>但為了提高安全性,monerujo 仍然會要求您在觀看錢包詳細資訊或發送資金時輸入密碼。</p>
+        <strong>安全警告</strong>
+        <p>最後,monerujo 想提醒您,任何可以取得您指紋的人都能夠窺視您的錢包餘額。</p>
+        <p>例如,您周遭的惡意使用者可以趁您睡著時使用您的指紋開啟錢包。</p>
+        <strong>您確定要啟用本功能嗎?</strong>
+    ]]></string>
     <string name="generate_bad_passwordB">密碼不符</string>
     <string name="generate_empty_passwordB">密碼不得空白</string>
     <string name="generate_buttonGenerate">建立錢包!</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index aac66986..93ea2cb9 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -158,7 +158,9 @@
     <string name="prompt_changepw">New Passphrase for %1$s</string>
     <string name="prompt_changepwB">Repeat Passphrase for %1$s</string>
     <string name="prompt_password">Password for %1$s</string>
+    <string name="prompt_fingerprint_auth">You can also open wallet using fingerprint.\nPlease touch sensor.</string>
     <string name="prompt_send_password">Confirm Password</string>
+    <string name="bad_fingerprint">Fingerprint not recognized. Try again.</string>
     <string name="bad_password">Incorrect password!</string>
     <string name="bad_wallet">Wallet does not exist!</string>
     <string name="error_not_wallet">This is not a wallet!</string>
@@ -211,6 +213,19 @@
     <string name="generate_title">Create Wallet</string>
     <string name="generate_name_hint">Wallet Name</string>
     <string name="generate_password_hint">Wallet Passphrase</string>
+    <string name="generate_fingerprint_hint">Allow to open wallet using fingerprint</string>
+    <string name="generate_fingerprint_warn"><![CDATA[
+        <strong>Fingerprint Authentication</strong>
+        <p>With fingerprint authentication enabled, you can view wallet balance and receive funds
+        without entering password.</p>
+        <p>But for additional security, monerujo will still require you to enter password when
+        viewing wallet details or sending funds.</p>
+        <strong>Security Warning</strong>
+        <p>Finally, monerujo wants to remind you that anyone who can get your fingerprint will be
+        able to peep into your wallet balance.</p>
+        <p>For instance, a malicious user around you can open your wallet when you are asleep.</p>
+        <strong>Are you sure to enable this function?</strong>
+    ]]></string>
     <string name="generate_bad_passwordB">Passphrases do not match</string>
     <string name="generate_empty_passwordB">Passphrase may not be empty</string>
     <string name="generate_buttonGenerate">Make me a wallet already!</string>