/* * 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.tasks; import android.content.SharedPreferences; import android.os.AsyncTask; import android.preference.PreferenceManager; import android.util.Log; import com.aegiswallet.PayBitsApplication; import com.aegiswallet.objects.KeyCache; import com.aegiswallet.utils.Constants; import com.aegiswallet.utils.WalletUtils; import com.google.bitcoin.core.ECKey; import com.google.bitcoin.core.Wallet; import com.google.bitcoin.crypto.KeyCrypter; import com.google.bitcoin.crypto.KeyCrypterException; import com.google.bitcoin.crypto.KeyCrypterScrypt; import org.spongycastle.crypto.params.KeyParameter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.math.BigInteger; import java.text.DateFormat; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.TimeZone; /** * Created by bsimic on 5/6/14. */ public class BaseTask extends AsyncTask { private String TAG = this.getClass().getName(); @Override protected Object doInBackground(Object[] objects) { return null; } @Override protected void onPostExecute(Object o) { super.onPostExecute(o); } public void encryptWalletShamirNFC(Wallet wallet, String x2, PayBitsApplication application) { String x1 = application.getPrefs().getString(Constants.SHAMIR_LOCAL_KEY, null); BigInteger result = WalletUtils.generateSecretFromStrings(x1, x2, null); String resultHashed = WalletUtils.convertToSha256(result.toString()); KeyCrypter keyCrypter = wallet.getKeyCrypter(); if (keyCrypter == null) keyCrypter = new KeyCrypterScrypt(); KeyParameter aesKey = keyCrypter.deriveKey(resultHashed); wallet.encrypt(keyCrypter, aesKey); application.setKeyCache(new KeyCache(aesKey, keyCrypter, null)); } public void encryptWalletWithShamir(Wallet wallet, String passOrNfc, PayBitsApplication application) { String x1 = application.getPrefs().getString(Constants.SHAMIR_LOCAL_KEY, null); String x2; if (application.getPrefs().contains(Constants.SHAMIR_ENCRYPTED_KEY)) { x2 = application.getPrefs().getString(Constants.SHAMIR_ENCRYPTED_KEY, null); } else { x2 = passOrNfc; } System.out.println("Generating secret from two X valuess...."); Log.d(TAG, "Generating secret from two X valuess...."); BigInteger result = WalletUtils.generateSecretFromStrings(x1, x2, null); if (result != null) { Log.d(TAG, "Getting the hashed result value for encryption..."); System.out.println("Getting the hashed result value for encryption..."); String resultHashed = WalletUtils.convertToSha256(result.toString()); Log.d(TAG, "Getting the wallet keyCrypter..."); System.out.println("Getting the wallet keyCrypter..."); KeyCrypter keyCrypter = wallet.getKeyCrypter(); if (keyCrypter == null) keyCrypter = new KeyCrypterScrypt(); Log.d(TAG, "Deriving wallet AES Key..."); System.out.println("Deriving wallet AES Key..."); KeyParameter aesKey = keyCrypter.deriveKey(resultHashed); Log.d(TAG, "Setting the wallet key cache..."); System.out.println("Setting the wallet key cache..."); application.setKeyCache(new KeyCache(aesKey, keyCrypter, passOrNfc)); Log.d(TAG, "Executing wallet encrypt call..."); System.out.println("Executing wallet encrypt call..."); wallet.encrypt(keyCrypter, aesKey); //only add the encrypted shamir key if nfc is not enabled.... if (application.getPrefs().contains(Constants.SHAMIR_ENCRYPTED_KEY)) { Log.d(TAG, "Encrypting the X2 shamir value by using password..."); System.out.println("Encrypting the X2 shamir value by using password..."); String encryptedX2 = WalletUtils.encryptString(x2, passOrNfc); Log.d(TAG, "Saving encrypted X2 value to preferences..."); System.out.println("Saving encrypted X2 value to preferences..."); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(application.getApplicationContext()); SharedPreferences.Editor editor= prefs.edit(); editor.putString(Constants.SHAMIR_ENCRYPTED_KEY, encryptedX2); editor.commit(); } } } public void decryptWallet(PayBitsApplication application, Wallet wallet, String passOrNFC) { String x2; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(application.getApplicationContext()); SharedPreferences.Editor editor = prefs.edit(); if (application.getKeyCache() != null) { try { wallet.decrypt(application.getKeyCache().getAesKey()); if (application.getPrefs().contains(Constants.SHAMIR_ENCRYPTED_KEY)) { x2 = WalletUtils.decryptString(application.getPrefs().getString(Constants.SHAMIR_ENCRYPTED_KEY, null), application.getKeyCache().getPassword()); editor.putString(Constants.SHAMIR_ENCRYPTED_KEY, x2); editor.commit(); } } catch (Exception e) { Log.e(TAG, "unable to decrypt: " + e.getMessage()); } } else { if (application.getPrefs().contains(Constants.SHAMIR_ENCRYPTED_KEY)) { x2 = WalletUtils.decryptString(application.getPrefs().getString(Constants.SHAMIR_ENCRYPTED_KEY, null), passOrNFC); editor.putString(Constants.SHAMIR_ENCRYPTED_KEY, x2); } else { x2 = passOrNFC; } String x1 = application.getPrefs().getString(Constants.SHAMIR_LOCAL_KEY, null); BigInteger result = WalletUtils.generateSecretFromStrings(x1, x2, null); String resultHashed = WalletUtils.convertToSha256(result.toString()); try { KeyParameter aesKey = wallet.getKeyCrypter().deriveKey(resultHashed); application.setKeyCache(new KeyCache(aesKey, wallet.getKeyCrypter(), passOrNFC)); wallet.decrypt(aesKey); editor.commit(); } catch (KeyCrypterException e) { Log.e(TAG, e.getMessage()); } catch (Exception e) { Log.e(TAG, e.getMessage()); } } } public void updateEncryptedX2(PayBitsApplication application, KeyCache keyCache) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(application.getApplicationContext()); SharedPreferences.Editor editor= prefs.edit(); //ONly update encrypted x2 if we are NOT using NFC if (application.getPrefs().contains(Constants.SHAMIR_ENCRYPTED_KEY)) { String x2 = application.getPrefs().getString(Constants.SHAMIR_ENCRYPTED_KEY, null); String encryptedX2 = WalletUtils.encryptString(x2, keyCache.getPassword()); editor.putString(Constants.SHAMIR_ENCRYPTED_KEY, encryptedX2); editor.commit(); } } public String doWalletBackup(Wallet wallet, boolean justDecrypted, PayBitsApplication application, String passOrNFC) { if (!wallet.isEncrypted()) { KeyCache keyCache = application.getKeyCache(); try { Constants.WALLET_BACKUP_DIRECTORY.mkdirs(); DateFormat dateFormat = Constants.backupDateFormat; dateFormat.setTimeZone(TimeZone.getDefault()); String date = dateFormat.format(new Date()); File file = new File(Constants.WALLET_BACKUP_DIRECTORY, Constants.WALLET_BACKUP_FILENAME + "-" + date); List<ECKey> keys = new LinkedList<ECKey>(); for (ECKey key : wallet.getKeys()) if (!wallet.isKeyRotating(key)) keys.add(key); Writer cipherOut = new OutputStreamWriter(new FileOutputStream(file), Constants.UTF_8); WalletUtils.writeEncryptedKeys(cipherOut, keys, application.getPrefs(), passOrNFC); cipherOut.close(); if (justDecrypted) { if (keyCache != null) { wallet.encrypt(keyCache.getKeyCrypter(), keyCache.getAesKey()); updateEncryptedX2(application, keyCache); application.setKeyCache(keyCache); } else { encryptWalletWithShamir(wallet, passOrNFC, application); } } SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(application.getApplicationContext()); SharedPreferences.Editor editor= prefs.edit(); editor.putString(Constants.LAST_BACKUP_DATE, date).commit(); editor.putInt(Constants.LAST_BACKUP_NUM_ADDRESSES, wallet.getKeychainSize()).commit(); return file.getAbsolutePath(); } catch (IOException e) { Log.e(TAG, e.getMessage()); } } return null; } }