From 0fb6e3ea15adb0ea23018002d26899f4becf4d3d Mon Sep 17 00:00:00 2001 From: ssotomayor Date: Tue, 28 Oct 2014 15:15:42 -0300 Subject: [PATCH] Fixes import for 0.6.4 --- copay.js | 1 + js/controllers/import.js | 29 +++++++++++++++++--- js/models/Compatibility.js | 51 ++++++++++++++++++++++++++++++++++-- js/services/compatibility.js | 2 +- 4 files changed, 76 insertions(+), 7 deletions(-) diff --git a/copay.js b/copay.js index fa2988185..ee4473480 100644 --- a/copay.js +++ b/copay.js @@ -13,6 +13,7 @@ var Insight = module.exports.Insight = require('./js/models/Insight'); module.exports.Identity = require('./js/models/Identity'); module.exports.Wallet = require('./js/models/Wallet'); +module.exports.Compatibility = require('./js/models/Compatibility'); module.exports.PluginManager = require('./js/models/PluginManager'); module.exports.version = require('./version').version; module.exports.commitHash = require('./version').commitHash; diff --git a/js/controllers/import.js b/js/controllers/import.js index 89a71eb57..b6e17f8c0 100644 --- a/js/controllers/import.js +++ b/js/controllers/import.js @@ -39,7 +39,7 @@ angular.module('copayApp.controllers').controller('ImportController', controllerUtils.setFocusedWallet(w); return; } - + // if it was used, we need to scan for indices w.updateIndexes(function(err) { updateStatus('Importing wallet - We are almost there...'); @@ -50,7 +50,7 @@ angular.module('copayApp.controllers').controller('ImportController', controllerUtils.installWalletHandlers($scope, w); controllerUtils.setFocusedWallet(w); }); - }); + }); }; $scope.openFileDialog = function() { @@ -65,7 +65,17 @@ angular.module('copayApp.controllers').controller('ImportController', reader.onloadend = function(evt) { if (evt.target.readyState == FileReader.DONE) { // DONE == 2 var encryptedObj = evt.target.result; - _importBackup(encryptedObj); + Compatibility.importEncryptedWallet($rootScope.iden, encryptedObj, $scope.password, {}, + function(err, wallet){ + if (err) { + notification.error('Error', 'Could not read wallet. Please check your password'); + } else { + controllerUtils.installWalletHandlers($scope, wallet); + controllerUtils.setFocusedWallet(wallet); + return; + } + } + ); } }; }; @@ -94,10 +104,21 @@ angular.module('copayApp.controllers').controller('ImportController', reader.readAsBinaryString(backupFile); } else { + Compatibility.importEncryptedWallet($rootScope.iden, backupText, $scope.password, {}, + function(err, wallet){ + if (err) { + notification.error('Error', 'Could not read wallet. Please check your password'); + } else { + controllerUtils.installWalletHandlers($scope, wallet); + controllerUtils.setFocusedWallet(wallet); + return; + } + } + ); try { _importBackup(backupText); } catch(e) { - Compatibility.preDotEightImportWalletToStorage(backupText, $scope.password, $scope.skipPublicKeyRing, $scope.skipTxProposals); + Compatibility.importEncryptedWallet(backupText, $scope.password, $scope.skipPublicKeyRing, $scope.skipTxProposals); } } }; diff --git a/js/models/Compatibility.js b/js/models/Compatibility.js index a569e8db4..4a1d292a7 100644 --- a/js/models/Compatibility.js +++ b/js/models/Compatibility.js @@ -4,8 +4,13 @@ var Identity = require('./Identity'); var Wallet = require('./Wallet'); var cryptoUtils = require('../util/crypto'); var CryptoJS = require('node-cryptojs-aes').CryptoJS; +var sjcl = require('../../lib/sjcl'); +var preconditions = require('preconditions').instance(); +var _ = require('lodash'); var Compatibility = {}; +Compatibility.iterations = 100; +Compatibility.salt = 'mjuBtGybi/4='; /** * Reads from localstorage wallets saved previously to 0.8 @@ -41,10 +46,9 @@ Compatibility._getWalletIds = function(cb) { * @returns {Object} */ Compatibility.importLegacy = function(encryptedWallet, passphrase) { + passphrase = this.kdf(passphrase); var ret = Compatibility._decrypt(encryptedWallet, passphrase); if (!ret) return null; - ret = ret.toString(CryptoJS.enc.Utf8); - ret = JSON.parse(ret); return ret; }; @@ -183,4 +187,47 @@ Compatibility.readWalletPre8 = function(walletId, password, cb) { } }; +Compatibility.importEncryptedWallet = function(identity, cypherText, password, opts, cb) { + var crypto = opts.cryptoUtil || cryptoUtils; + var key = crypto.kdf(password); + var obj = crypto.decrypt(key, cypherText); + if (!obj) { + console.warn("Could not decrypt, trying legacy.."); + obj = Compatibility.importLegacy(cypherText, password); + if (!obj) { + return cb(new Error('Could not decrypt')) + } + }; + try { + obj = JSON.parse(obj); + } catch (e) { + return cb(new Error('Could not read encrypted wallet')); + } + return identity.importWalletFromObj(obj, opts, cb); +}; + +/** + * @desc Generate a WordArray expanding a password + * + * @param {string} password - the password to expand + * @returns WordArray 512 bits with the expanded key generated from password + */ +Compatibility.kdf = function(password) { + var hash = sjcl.hash.sha256.hash(sjcl.hash.sha256.hash(password)); + var salt = sjcl.codec.base64.toBits(this.salt); + + var crypto2 = function(key, salt, iterations, length, alg) { + return sjcl.codec.hex.fromBits(sjcl.misc.pbkdf2(key, salt, iterations, length * 8, + alg == 'sha1' ? function(key) { + return new sjcl.misc.hmac(key, sjcl.hash.sha1) + } : null + )) + }; + + var key512 = crypto2(hash, salt, this.iterations, 64, 'sha1'); + var sbase64 = sjcl.codec.base64.fromBits(sjcl.codec.hex.toBits(key512)); + return sbase64; +}; + + module.exports = Compatibility; diff --git a/js/services/compatibility.js b/js/services/compatibility.js index cb09fa7ce..3eec17b51 100644 --- a/js/services/compatibility.js +++ b/js/services/compatibility.js @@ -1,5 +1,5 @@ 'use strict'; -angular.module('copayApp.services').value('Compatibility', function() { +angular.module('copayApp.services').factory('Compatibility', function() { return require('copay').Compatibility; });