Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Input NFC Password #5

Merged
merged 2 commits into from
May 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

<activity
android:name=".LoginActivity"
android:launchMode="singleTop"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name"
android:screenOrientation="portrait">
Expand Down
35 changes: 35 additions & 0 deletions app/src/main/java/com/m2049r/xmrwallet/GenerateFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputLayout;
Expand All @@ -35,6 +36,7 @@
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;
Expand Down Expand Up @@ -71,6 +73,15 @@ public class GenerateFragment extends Fragment {
private TextInputLayout etWalletViewKey;
private TextInputLayout etWalletSpendKey;
private TextInputLayout etWalletRestoreHeight;

private LinearLayout llNfcPasswordSeed;
private TextInputLayout etNfcPasswordSeed;
private ImageView ivNfcPasswordSeed;

private LinearLayout llNfcPasswordkey;
private TextInputLayout etNfcPasswordkey;
private ImageView ivNfcPasswordkey;

private Button bGenerate;

private String type = null;
Expand All @@ -92,8 +103,26 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
etWalletViewKey = (TextInputLayout) view.findViewById(R.id.etWalletViewKey);
etWalletSpendKey = (TextInputLayout) view.findViewById(R.id.etWalletSpendKey);
etWalletRestoreHeight = (TextInputLayout) view.findViewById(R.id.etWalletRestoreHeight);

llNfcPasswordSeed = (LinearLayout) view.findViewById(R.id.llNfcPasswordSeed);
etNfcPasswordSeed = (TextInputLayout) view.findViewById(R.id.etNfcPasswordSeed);
ivNfcPasswordSeed = (ImageView) view.findViewById(R.id.ivNfcPasswordSeed);
llNfcPasswordkey = (LinearLayout) view.findViewById(R.id.llNfcPasswordkey);
etNfcPasswordkey = (TextInputLayout) view.findViewById(R.id.etNfcPasswordkey);
ivNfcPasswordkey = (ImageView) view.findViewById(R.id.ivNfcPasswordkey);

bGenerate = (Button) view.findViewById(R.id.bGenerate);

ivNfcPasswordkey.setImageResource(R.drawable.nfc_signal);
ivNfcPasswordSeed.setImageResource(R.drawable.nfc_signal);
AnimationDrawable nfcAnimationkey = (AnimationDrawable) ivNfcPasswordkey.getDrawable();
nfcAnimationkey.setOneShot(false);
nfcAnimationkey.start();

AnimationDrawable nfcAnimationSeed = (AnimationDrawable) ivNfcPasswordSeed.getDrawable();
nfcAnimationSeed.setOneShot(false);
nfcAnimationSeed.start();

etWalletMnemonic.getEditText().setRawInputType(InputType.TYPE_CLASS_TEXT);
etWalletAddress.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
etWalletViewKey.getEditText().setRawInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
Expand Down Expand Up @@ -212,6 +241,8 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
return false;
}
});
llNfcPasswordSeed.setVisibility(View.VISIBLE);

} else if (type.equals(TYPE_KEY) || type.equals(TYPE_VIEWONLY)) {
etWalletPassword.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
Expand Down Expand Up @@ -252,6 +283,8 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
return false;
}
});

llNfcPasswordkey.setVisibility(View.VISIBLE);
}
if (type.equals(TYPE_KEY)) {
etWalletSpendKey.setVisibility(View.VISIBLE);
Expand All @@ -268,6 +301,7 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
return false;
}
});
llNfcPasswordkey.setVisibility(View.VISIBLE);
}
if (!type.equals(TYPE_NEW)) {
etWalletRestoreHeight.setVisibility(View.VISIBLE);
Expand All @@ -281,6 +315,7 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
return false;
}
});

}
bGenerate.setOnClickListener(new View.OnClickListener()

Expand Down
97 changes: 93 additions & 4 deletions app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@

import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.media.MediaScannerConnection;
import android.nfc.NfcAdapter;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
Expand All @@ -45,6 +47,7 @@
import com.m2049r.xmrwallet.dialog.AboutFragment;
import com.m2049r.xmrwallet.dialog.CreditsFragment;
import com.m2049r.xmrwallet.dialog.HelpFragment;
import com.m2049r.xmrwallet.dialog.InputNfcPasswordFragment;
import com.m2049r.xmrwallet.dialog.PrivacyFragment;
import com.m2049r.xmrwallet.model.NetworkType;
import com.m2049r.xmrwallet.model.Wallet;
Expand Down Expand Up @@ -82,6 +85,10 @@ public class LoginActivity extends SecureActivity

private Toolbar toolbar;

private TagUtil tagUtil ;

private InputNfcPasswordFragment inputNfcPassword;

@Override
public void setToolbarButton(int type) {
toolbar.setButton(type);
Expand Down Expand Up @@ -323,7 +330,6 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
return false;
}
});

dialog.show();
}

Expand Down Expand Up @@ -379,6 +385,36 @@ protected void onPostExecute(Boolean result) {
}
}

private class AsyncBackupToNFC2 extends AsyncTask<Object, Void, Boolean> {
@Override
protected void onPreExecute() {
super.onPreExecute();

}

@Override
protected Boolean doInBackground(Object... params) {
if (params.length != 2) return false;
Intent intent = (Intent) params[0];
String walletName = (String) params[1];
return backupWalletToNFC(intent,walletName);
}

@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (isDestroyed()) {
return;
}
dismissProgressDialog();
if (!result) {
Toast.makeText(LoginActivity.this, getString(R.string.backup_failed), Toast.LENGTH_LONG).show();
}else{
InputNfcPasswordFragment.getInstance().dismiss();
}
}
}

private boolean backupWallet(String walletName) {
File backupFolder = new File(getStorageRoot(), "backups");
if (!backupFolder.exists()) {
Expand All @@ -400,6 +436,42 @@ private boolean backupWallet(String walletName) {
return success;
}

private boolean backupWalletToNFC(Intent intent,String walletName) {
boolean success=false;
File walletFile = Helper.getWalletFile(LoginActivity.this, walletName);
//Timber.d("backup " + walletFile.getAbsolutePath() + " to " + backupFile.getAbsolutePath());

boolean authenticated=false;
try {
tagUtil = TagUtil.selectTag(intent, false);
authenticated = tagUtil.authentication(intent, getKey(), false);
}catch (Exception e) {
e.printStackTrace();
}

if(authenticated)
{
Toast toast = Toast.makeText(LoginActivity.this, "Authentication Successful", Toast.LENGTH_LONG);
try {

byte[] bytes = new byte[(int)walletFile.length()];
new FileInputStream(walletFile).read(bytes);
tagUtil.writeTag(intent,(byte)4,bytes,false);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (AuthenticationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
else
return false;
return success;
}

private boolean backupWalletToNFC(String walletName) {
boolean success=false;
File walletFile = Helper.getWalletFile(LoginActivity.this, walletName);
Expand Down Expand Up @@ -432,8 +504,8 @@ private boolean backupWalletToNFC(String walletName) {
e.printStackTrace();
}
}
else
return false;
else
return false;
return success;
}
private byte[] getKey()
Expand Down Expand Up @@ -475,7 +547,9 @@ public void onWalletBackupToFile(String walletName) {
@Override
public void onWalletBackupToNFC(String walletName) {
Timber.d("backup to NFC hard wallet for wallet ." + walletName + ".");
new AsyncBackupToNFC().execute(walletName);
InputNfcPasswordFragment.display(getSupportFragmentManager());
InputNfcPasswordFragment.getInstance().setWalletName(walletName);

}

private class AsyncArchive extends AsyncTask<String, Void, Boolean> {
Expand Down Expand Up @@ -659,6 +733,21 @@ protected void onResume() {
}
}

@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())
|| NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())
|| NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
try {
tagUtil = TagUtil.selectTag(intent, false);
new AsyncBackupToNFC2().execute(intent,InputNfcPasswordFragment.getInstance().getWalletName());
} catch (Exception e) {
e.printStackTrace();
}
}
}

private class MyProgressDialog extends ProgressDialog {
Activity activity;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package com.m2049r.xmrwallet.dialog;


import android.app.AlertDialog;
import android.app.Dialog;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.support.design.widget.TextInputLayout;
import android.support.v4.app.DialogFragment;
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.LayoutInflater;
import android.view.View;
import android.widget.ImageView;

import com.m2049r.xmrwallet.R;
import com.nulabinc.zxcvbn.Strength;
import com.nulabinc.zxcvbn.Zxcvbn;

public class InputNfcPasswordFragment extends DialogFragment {

private String walletName = null;


static final String TAG = "InputNfcPasswordFragment";

private TextInputLayout etWalletPassword;

private static InputNfcPasswordFragment fragment = null;


public static InputNfcPasswordFragment getInstance() {
if(fragment ==null){
fragment = new InputNfcPasswordFragment();
}

return fragment;
}

public static void display(FragmentManager fm) {
FragmentTransaction ft = fm.beginTransaction();
Fragment prev = fm.findFragmentByTag(TAG);
if (prev != null) {
ft.remove(prev);
}
InputNfcPasswordFragment.getInstance().show(ft, TAG);
}


@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_input_nfc_password, null);
etWalletPassword = (TextInputLayout) view.findViewById(R.id.etWalletPassword);
etWalletPassword.getEditText().addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable editable) {
checkPassword();
}

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
etWalletPassword.requestFocus();
ImageView nfcAnimationImage = (ImageView) view.findViewById(R.id.NfcAnimation);
nfcAnimationImage.setImageResource(R.drawable.nfc_signal);
AnimationDrawable nfcAnimation = (AnimationDrawable) nfcAnimationImage.getDrawable();
nfcAnimation.setOneShot(false);
nfcAnimation.start();


AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(view);
initZxcvbn();
return builder.create();
}
Zxcvbn zxcvbn = new Zxcvbn();
// initialize zxcvbn engine in background thread
private void initZxcvbn() {
new Thread(new Runnable() {
@Override
public void run() {
zxcvbn.measure("");
}
}).start();
}

private void checkPassword() {
String password = etWalletPassword.getEditText().getText().toString();
if (!password.isEmpty()) {
Strength strength = zxcvbn.measure(password);
int msg;
double guessesLog10 = strength.getGuessesLog10();
if (guessesLog10 < 10)
msg = R.string.password_weak;
else if (guessesLog10 < 11)
msg = R.string.password_fair;
else if (guessesLog10 < 12)
msg = R.string.password_good;
else if (guessesLog10 < 13)
msg = R.string.password_strong;
else
msg = R.string.password_very_strong;
etWalletPassword.setError(getResources().getString(msg));
} else {
etWalletPassword.setError(null);
}
}

//get input nfc password
public String getPassword(){
String password = etWalletPassword.getEditText().getText().toString();
return password;
}

public String getWalletName() {
return walletName;
}

public void setWalletName(String walletName) {
this.walletName = walletName;
}
}
Binary file added app/src/main/res/drawable/nfc1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/nfc2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable/nfc3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading