/* * Aegis Bitcoin Wallet - The secure Bitcoin wallet for Android * Copyright 2014 Bojan Simic and specularX.co, designed by Reuven Yamrom * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.aegiswallet.actions; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.os.Vibrator; import android.view.View; import android.widget.TextView; import android.widget.Toast; import com.aegiswallet.PayBitsApplication; import com.aegiswallet.R; import com.aegiswallet.listeners.BackupCompletedListener; import com.aegiswallet.listeners.ImportCompletedListener; import com.aegiswallet.listeners.PasswordProvidedListener; import com.aegiswallet.listeners.WalletDecryptedListener; import com.aegiswallet.listeners.WalletEncryptedListener; import com.aegiswallet.tasks.BackupWalletTask; import com.aegiswallet.tasks.DecryptWalletAndAddKeysTask; import com.aegiswallet.tasks.DecryptWalletTask; import com.aegiswallet.tasks.EncryptWalletTask; import com.aegiswallet.tasks.ImportWalletTask; import com.aegiswallet.utils.BasicUtils; import com.aegiswallet.utils.Constants; import com.aegiswallet.utils.NfcUtils; import com.aegiswallet.utils.WalletUtils; import com.google.bitcoin.core.ECKey; import java.util.List; /** * Created by bsimic on 5/12/14. */ public class NFCActivity extends Activity implements WalletDecryptedListener, WalletEncryptedListener, BackupCompletedListener, ImportCompletedListener, PasswordProvidedListener { private String TAG = this.getClass().getName(); private String action; private Context context = this; private PayBitsApplication application; private String fileNameForRestoreBackup; private TextView messageTextView; private boolean restoreBackupFile; private boolean restoreBackupFilePart2; private boolean switchToPassword; private boolean switchToNFC = false; private String newPassword; private boolean copyStepOne; private boolean copyStepTwo; private String copyString; private long lastScanTime = 0; private List<ECKey> providedKeyList; private boolean nfcEnabled; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_nfc); messageTextView = (TextView) findViewById(R.id.nfc_activity_message); action = getIntent().getStringExtra("nfc_action"); if (action != null && action.equals("restore_backup")) { fileNameForRestoreBackup = getIntent().getStringExtra("fileNameForRestoreBackup"); messageTextView.setText(getString(R.string.nfc_activity_message) + " " + fileNameForRestoreBackup); messageTextView.setVisibility(View.VISIBLE); restoreBackupFile = true; } else if (action != null && action.equals("switch_to_password")) { newPassword = getIntent().getStringExtra("new_password"); switchToPassword = true; } else if (action != null && action.equals("switch_to_nfc")) { switchToNFC = true; } else if (action != null && action.equals("copy_tag")) { messageTextView.setText(getString(R.string.nfc_activity_message_main)); copyStepOne = true; } application = (PayBitsApplication) getApplication(); determineNFCEnabled(); } @Override protected void onResume() { super.onResume(); NfcUtils.listen(this, getClass()); determineNFCEnabled(); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if(System.currentTimeMillis() - lastScanTime < 1500) return; if (switchToNFC && !application.getWallet().isEncrypted()) { String x2Value = application.getPrefs().getString(Constants.SHAMIR_ENCRYPTED_KEY, null); if (x2Value != null) { String result = NfcUtils.write(intent, x2Value.getBytes()); Vibrator v = (Vibrator) this.context.getSystemService(Context.VIBRATOR_SERVICE); v.vibrate(500); if (result.equals(Constants.NFC_TAG_WRITTEN)) { EncryptWalletTask encryptWalletTask = new EncryptWalletTask(context, application.getWallet(), application.getPrefs().getString(Constants.SHAMIR_ENCRYPTED_KEY, null), application, true); //encryptWalletTask.execute(); encryptWalletTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); application.getPrefs().edit().putString(Constants.SHAMIR_X2_HASHED, WalletUtils.convertToSha256(x2Value)).commit(); application.getPrefs().edit().remove(Constants.SHAMIR_ENCRYPTED_KEY).commit(); } else { String errorMessage = BasicUtils.getNFCErrorMessage(context, result); if (errorMessage != null) Toast.makeText(context, errorMessage, Toast.LENGTH_LONG).show(); } } return; } byte[] result = NfcUtils.getData(intent); if(result != null){ lastScanTime = System.currentTimeMillis(); } Vibrator v = (Vibrator) this.context.getSystemService(Context.VIBRATOR_SERVICE); v.vibrate(500); String shamirX2Hashed = application.getPrefs().getString(Constants.SHAMIR_X2_HASHED, null); String resultString = null; if (result != null) resultString = new String(result); if(copyStepOne){ String resultSha256Value = WalletUtils.convertToSha256(resultString); String currentX2ShaValue = shamirX2Hashed; if(resultSha256Value != null && resultSha256Value.equals(currentX2ShaValue)){ copyString = resultString; messageTextView.setText(getString(R.string.nfc_tag_copy_steptwo_message)); messageTextView.setVisibility(View.VISIBLE); copyStepTwo = true; copyStepOne = false; } else{ Toast.makeText(context, getString(R.string.nfc_tag_copy_invalid_string), Toast.LENGTH_SHORT).show(); } } else if(copyStepTwo){ String writeResult = NfcUtils.write(intent, copyString.getBytes()); v.vibrate(500); if (writeResult.equals(Constants.NFC_TAG_WRITTEN)) { Intent openSettingsActivity = new Intent(context, SettingsActivity.class); openSettingsActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); openSettingsActivity.putExtra("message", getString(R.string.nfc_tag_copy_successful)); context.startActivity(openSettingsActivity); finish(); } } if (resultString != null && restoreBackupFile) { ImportWalletTask importWalletTask = new ImportWalletTask(application, application.getWallet(), context, resultString, fileNameForRestoreBackup); //importWalletTask.execute(); importWalletTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); return; } if (resultString != null && shamirX2Hashed.equals(WalletUtils.convertToSha256(resultString)) && action != null) { if (action.equals("decrypt")) { DecryptWalletTask decryptWalletTask = new DecryptWalletTask(context, application.getWallet(), resultString, application); //decryptWalletTask.execute(); decryptWalletTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); } else if (action.equals("encrypt")) { EncryptWalletTask encryptWalletTask = new EncryptWalletTask(context, application.getWallet(), resultString, application, true); //encryptWalletTask.execute(); encryptWalletTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); } else if (action.equals("backup")) { BackupWalletTask backupWalletTask = new BackupWalletTask(application, context, application.getWallet(), resultString); //backupWalletTask.execute(); backupWalletTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); } else if (restoreBackupFilePart2) { DecryptWalletAndAddKeysTask decryptWalletAndAddKeysTask = new DecryptWalletAndAddKeysTask(application, application.getWallet(), context, resultString, providedKeyList); //decryptWalletAndAddKeysTask.execute(); decryptWalletAndAddKeysTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); } else if (switchToPassword) { if (application.getWallet().isEncrypted()) { DecryptWalletTask decryptWalletTask = new DecryptWalletTask(context, application.getWallet(), resultString, application); //decryptWalletTask.execute(); decryptWalletTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); } else { doPasswordReset(false, resultString); } } } else { if(!action.equals("copy_tag")) Toast.makeText(context, getString(R.string.nfc_tag_invalid_string), Toast.LENGTH_SHORT).show(); } } @Override public void onWalletDecrypted(String passOrNFC) { if (switchToPassword && newPassword != null) { doPasswordReset(true, passOrNFC); } else { startMainActivity(); } } public void doPasswordReset(boolean justDecrypted, String valueFromNFC) { if (newPassword != null) { application.getPrefs().edit().putString(Constants.SHAMIR_ENCRYPTED_KEY, valueFromNFC).commit(); String passwordSalt = BasicUtils.generateSecureKey(); String passwordHash = passwordSalt + WalletUtils.convertToSha256(passwordSalt + newPassword); application.getPrefs().edit().putString(Constants.PASSWORD_HASH, passwordHash).commit(); application.getPrefs().edit().putString(Constants.PASSWORD_SALT, passwordSalt).commit(); application.setKeyCache(null); if (justDecrypted) { EncryptWalletTask encryptWalletTask = new EncryptWalletTask(context, application.getWallet(), newPassword, application, false); //encryptWalletTask.execute(); encryptWalletTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); } else { startMainActivity(); } } } @Override public void onWalletEncrypted() { startMainActivity(); } @Override public void onImportCompleted(String fileName, List<ECKey> keyList) { if (!application.getWallet().isEncrypted()) { application.showImportCompletedPrompt(context, fileNameForRestoreBackup); } else if (restoreBackupFile && nfcEnabled) { providedKeyList = keyList; restoreBackupFile = false; restoreBackupFilePart2 = true; messageTextView.setText(getString(R.string.nfc_activity_message_main)); } else if (restoreBackupFile && !nfcEnabled) { providedKeyList = keyList; restoreBackupFile = false; application.showPasswordPrompt(this, Constants.ACTION_RESTORE_BACKUP); restoreBackupFilePart2 = true; } else if (restoreBackupFilePart2) { //application.deleteBlockchainAndRestartApp(context, null); application.showImportCompletedPrompt(context, fileNameForRestoreBackup); restoreBackupFilePart2 = false; } } @Override public void onBackupCompleted(String fileName) { Intent openMainActivity = new Intent(this, MainActivity.class); openMainActivity.putExtra("backup_done", true); openMainActivity.putExtra("backup_file", fileName); startActivity(openMainActivity); } private void startMainActivity() { Intent openMainActivity = new Intent(context, MainActivity.class); openMainActivity.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); context.startActivity(openMainActivity); finish(); } private void determineNFCEnabled() { nfcEnabled = application.getPrefs().contains(Constants.SHAMIR_ENCRYPTED_KEY) ? false : true; } @Override //This is IF the wallet is password encrypted but we are importing a NFC encrypted file. public void onPasswordProvided(String password, int encrypt) { if (restoreBackupFilePart2 && providedKeyList != null) { DecryptWalletAndAddKeysTask decryptWalletAndAddKeysTask = new DecryptWalletAndAddKeysTask(application, application.getWallet(), context, password, providedKeyList); //decryptWalletAndAddKeysTask.execute(); decryptWalletAndAddKeysTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); } } }