Compare commits
9 commits
master
...
wallet/tas
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ef1bca911 | ||
|
|
fb88b05463 | ||
|
|
074e691cf9 | ||
|
|
a388e6deac | ||
|
|
63ddf545e4 | ||
|
|
f04417bc39 | ||
|
|
52b9a206c3 | ||
|
|
ecaa13f6d4 | ||
|
|
e215ecfb52 |
7 changed files with 401 additions and 43 deletions
11
Gruntfile.js
11
Gruntfile.js
|
|
@ -175,6 +175,17 @@ module.exports = function(grunt) {
|
||||||
'src/js/trezor-url.js',
|
'src/js/trezor-url.js',
|
||||||
'bower_components/trezor-connect/connect.js',
|
'bower_components/trezor-connect/connect.js',
|
||||||
'node_modules/bezier-easing/dist/bezier-easing.min.js',
|
'node_modules/bezier-easing/dist/bezier-easing.min.js',
|
||||||
|
|
||||||
|
'bower_components/crypto-js/core.js',
|
||||||
|
'bower_components/crypto-js/enc-base64.js',
|
||||||
|
'bower_components/crypto-js/hmac.js',
|
||||||
|
'bower_components/crypto-js/md5.js',
|
||||||
|
'bower_components/crypto-js/sha1.js',
|
||||||
|
'bower_components/crypto-js/evpkdf.js',
|
||||||
|
'bower_components/crypto-js/cipher-core.js',
|
||||||
|
'bower_components/crypto-js/aes.js',
|
||||||
|
'bower_components/crypto-js/pbkdf2.js',
|
||||||
|
|
||||||
'node_modules/cordova-plugin-qrscanner/dist/cordova-plugin-qrscanner-lib.min.js'
|
'node_modules/cordova-plugin-qrscanner/dist/cordova-plugin-qrscanner-lib.min.js'
|
||||||
],
|
],
|
||||||
dest: 'www/js/app.js'
|
dest: 'www/js/app.js'
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
"angular-gettext": "2.2.1",
|
"angular-gettext": "2.2.1",
|
||||||
"angular-moment": "0.10.1",
|
"angular-moment": "0.10.1",
|
||||||
"angular-qrcode": "bitpay/angular-qrcode#~6.3.0",
|
"angular-qrcode": "bitpay/angular-qrcode#~6.3.0",
|
||||||
|
"crypto-js": "^3.1.9",
|
||||||
"ionic": "https://github.com/ionic-team/ionic-v1.git",
|
"ionic": "https://github.com/ionic-team/ionic-v1.git",
|
||||||
"moment": "2.10.3",
|
"moment": "2.10.3",
|
||||||
"ng-lodash": "0.2.3",
|
"ng-lodash": "0.2.3",
|
||||||
|
|
|
||||||
164
src/js/services/encryptionService.js
Normal file
164
src/js/services/encryptionService.js
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
|
angular.module('copayApp.services').factory('encryptionService', function($log, secureStorageService) {
|
||||||
|
var keySize = 512;
|
||||||
|
var iterations = 1500;
|
||||||
|
var storageKey = 'encryptionKey';
|
||||||
|
|
||||||
|
var service = {
|
||||||
|
decrypt: decrypt,
|
||||||
|
encrypt: encrypt,
|
||||||
|
removeKeyIfExists: removeKeyIfExists
|
||||||
|
};
|
||||||
|
return service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a CryptoJS.WordArray
|
||||||
|
*/
|
||||||
|
function _generateKey() {
|
||||||
|
var salt = CryptoJS.lib.WordArray.random(128/8);
|
||||||
|
var passphrase = CryptoJS.lib.WordArray.random(128/8);
|
||||||
|
var key = CryptoJS.PBKDF2(passphrase, salt, { keySize: keySize/32, iterations: iterations });
|
||||||
|
|
||||||
|
$log.debug('Generated key: ' + key);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} cb
|
||||||
|
*/
|
||||||
|
function _getOrCreateKey(cb) {
|
||||||
|
|
||||||
|
secureStorageService.get(storageKey, function onKeyRetrieved(keyErr, keyHex) {
|
||||||
|
if (keyErr) {
|
||||||
|
cb(keyErr, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyHex) {
|
||||||
|
var key = CryptoJS.enc.Hex.parse(keyHex);
|
||||||
|
cb(null, key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = _generateKey();
|
||||||
|
var keyHex = CryptoJS.enc.Hex.stringify(key);
|
||||||
|
secureStorageService.set(storageKey, keyHex, function onKeyStored(storeErr) {
|
||||||
|
if (storeErr) {
|
||||||
|
$log.error('Error storing key.', storeErr);
|
||||||
|
cb(storeErr, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(null, key);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string, Base64 encoded} str
|
||||||
|
* @param {CryptoJS.WordArray} key
|
||||||
|
* @param {string, hex} iv
|
||||||
|
*/
|
||||||
|
function _decryptUsingCryptoJS(str, key, iv) {
|
||||||
|
$log.debug('decrypt() str: ' + str);
|
||||||
|
$log.debug('decrypt() using iv:' + iv + ', key: ' + JSON.stringify(key));
|
||||||
|
|
||||||
|
var ivWords = CryptoJS.enc.Hex.parse(iv);
|
||||||
|
var plaintext = CryptoJS.AES.decrypt(str, key, { iv: ivWords });
|
||||||
|
$log.debug('plaintext', JSON.stringify(plaintext));
|
||||||
|
|
||||||
|
var plaintextWords = CryptoJS.lib.WordArray.create();
|
||||||
|
plaintextWords.init(plaintext.words, plaintext.sigBytes);
|
||||||
|
$log.debug('plaintextWords', JSON.stringify(plaintextWords));
|
||||||
|
var plaintextString = plaintextWords.toString(CryptoJS.enc.Utf8);
|
||||||
|
$log.debug('plaintextString: ', JSON.stringify(plaintextString));
|
||||||
|
|
||||||
|
return plaintextString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates its own Initialization Vector, which is returned.
|
||||||
|
* @param {string, Base64 encoded} str
|
||||||
|
* @param {CryptoJS.WordArray} key
|
||||||
|
* @returns {*} The ciphertext created, and the IV used.
|
||||||
|
*/
|
||||||
|
function _encryptUsingCryptoJS(str, key) {
|
||||||
|
var iv = CryptoJS.lib.WordArray.random(16);
|
||||||
|
|
||||||
|
var cipherParams = CryptoJS.AES.encrypt(str, key, { iv: iv });
|
||||||
|
var ciphertextWords = cipherParams.ciphertext.toString(CryptoJS.enc.Base64);
|
||||||
|
var ivHex = iv.toString(CryptoJS.enc.Hex);
|
||||||
|
|
||||||
|
// Just for testing - do we get back what we put in?
|
||||||
|
/*
|
||||||
|
decrypt(ciphertext, {iv: ivHex}, function onDecryptionTest(err, decrypted){
|
||||||
|
if (err) {
|
||||||
|
$log.error('Failed to decrypt encrypted.', err);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$log.debug('Freshly decrypted:', JSON.stringify(decrypted));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
return {
|
||||||
|
ciphertext: ciphertextWords.toString(CryptoJS.enc.Base64),
|
||||||
|
opts: {
|
||||||
|
iv: ivHex
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function decrypt(str, opts, cb) {
|
||||||
|
_getOrCreateKey(function onKey(err, key) {
|
||||||
|
if (err) {
|
||||||
|
$log.error('Failed to get or create key.', err);
|
||||||
|
cb(err, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var decrypted;
|
||||||
|
try {
|
||||||
|
decrypted = _decryptUsingCryptoJS(str, key, opts.iv);
|
||||||
|
} catch (e) {
|
||||||
|
// Can get this when using the wrong key: Malformed UTF-8 data
|
||||||
|
$log.error('Error when decrypting.', e);
|
||||||
|
cb(e, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cb(null, decrypted);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function encrypt(str, cb) {
|
||||||
|
|
||||||
|
_getOrCreateKey(function onKey(err, key){
|
||||||
|
if (err) {
|
||||||
|
cb(err, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var encrypted = _encryptUsingCryptoJS(str, key);
|
||||||
|
cb(null, encrypted);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function removeKeyIfExists() {
|
||||||
|
secureStorageService.remove(storageKey, function onKeyRemoved(err){
|
||||||
|
if (err) {
|
||||||
|
$log.Error('Error removing key.', err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$log.debug('Key removed.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
})();
|
||||||
75
src/js/services/jsonEncryptionService.js
Normal file
75
src/js/services/jsonEncryptionService.js
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('copayApp.services')
|
||||||
|
.factory('jsonEncryptionService', jsonEncryptionService);
|
||||||
|
|
||||||
|
function jsonEncryptionService($log) {
|
||||||
|
var currentVersion = 1;
|
||||||
|
|
||||||
|
var service = {
|
||||||
|
isEncrypted: isEncrypted,
|
||||||
|
parse: parse,
|
||||||
|
stringify: stringify
|
||||||
|
};
|
||||||
|
return service;
|
||||||
|
|
||||||
|
function isEncrypted(jsonStr) {
|
||||||
|
try {
|
||||||
|
var jsonObj = JSON.parse(jsonStr);
|
||||||
|
} catch (e) {
|
||||||
|
$log.error('Failed to parse JSON when looking for encypted data.', e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return jsonObj.version && jsonObj.encryptedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse(jsonStr) {
|
||||||
|
|
||||||
|
var jsonObj = JSON.parse(jsonStr);
|
||||||
|
|
||||||
|
if (!(jsonObj.version && jsonObj.version === currentVersion)) {
|
||||||
|
throw new Error('Incompatible version.');
|
||||||
|
}
|
||||||
|
|
||||||
|
var encryptedData = jsonObj.encryptedData;
|
||||||
|
// extract ciphertext from json object, and create cipher params object
|
||||||
|
//var ciphertext = CryptoJS.enc.Base64.parse(encryptedData.ciphertext)
|
||||||
|
//var iv = CryptoJS.enc.Hex.parse(encryptedData.iv);
|
||||||
|
var ciphertext = encryptedData.ciphertext;
|
||||||
|
var iv = encryptedData.iv;
|
||||||
|
|
||||||
|
return {
|
||||||
|
ciphertext: ciphertext,
|
||||||
|
opts: {
|
||||||
|
iv: iv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string, Base64 encoded} ciphertext
|
||||||
|
* @param {*} opts So it flexible enough to handle other schemes in future.
|
||||||
|
* @throws If cipherParams does not include the iv.
|
||||||
|
*/
|
||||||
|
function stringify(ciphertext, opts) {
|
||||||
|
var iv = opts.iv;
|
||||||
|
|
||||||
|
if(!iv) {
|
||||||
|
throw new Error('Must include iv.');
|
||||||
|
}
|
||||||
|
|
||||||
|
var encryptedData = {
|
||||||
|
ciphertext: ciphertext,
|
||||||
|
iv: iv
|
||||||
|
};
|
||||||
|
|
||||||
|
return JSON.stringify({
|
||||||
|
version: currentVersion,
|
||||||
|
encryptedData: encryptedData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
@ -47,7 +47,7 @@ angular.module('copayApp.services').factory('mobileSecureStorageService', functi
|
||||||
function (error) {
|
function (error) {
|
||||||
$log.debug('mss get failed. ' + error);
|
$log.debug('mss get failed. ' + error);
|
||||||
if (error.message === 'Failure in SecureStorage.get() - The specified item could not be found in the keychain' || // iOS
|
if (error.message === 'Failure in SecureStorage.get() - The specified item could not be found in the keychain' || // iOS
|
||||||
error.message === 'Key [_SS_profile] not found.') { // Android
|
error.message === 'Key [_SS_' + key + '] not found.') { // Android
|
||||||
// The callback expects no error, but also no value, if it cannot be found.
|
// The callback expects no error, but also no value, if it cannot be found.
|
||||||
cb(null, null);
|
cb(null, null);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -57,6 +57,32 @@ angular.module('copayApp.services').factory('mobileSecureStorageService', functi
|
||||||
key);
|
key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
root.remove = function(key, cb) {
|
||||||
|
|
||||||
|
if (!platformInfo.isMobile) {
|
||||||
|
cb(new Error('mobileSecureStorageService is only available on mobile.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isReady) {
|
||||||
|
if (initialisationFailed) {
|
||||||
|
cb(new Error('mobileSecureStorageService initialisation failed.'));
|
||||||
|
} else {
|
||||||
|
pending.push(function(){ root.remove(key, cb); });
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
storage.remove(
|
||||||
|
function (value) {
|
||||||
|
cb();
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
cb(new Error(error));
|
||||||
|
},
|
||||||
|
key);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
root.set = function(key, value, cb) {
|
root.set = function(key, value, cb) {
|
||||||
|
|
||||||
if (!platformInfo.isMobile) {
|
if (!platformInfo.isMobile) {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,17 @@ angular.module('copayApp.services').factory('secureStorageService', function(des
|
||||||
} else { // Browser
|
} else { // Browser
|
||||||
localStorageService.get(alteredKeyIndicatingDesireForSecureStorage(k), cb);
|
localStorageService.get(alteredKeyIndicatingDesireForSecureStorage(k), cb);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
root.remove = function(k, cb) {
|
||||||
|
if (platformInfo.isMobile) {
|
||||||
|
mobileSecureStorageService.remove(k, cb);
|
||||||
|
} else if (platformInfo.isNW) {
|
||||||
|
desktopSecureStorageService.remove(k, cb);
|
||||||
|
} else { // Browser
|
||||||
|
localStorageService.remove(alteredKeyIndicatingDesireForSecureStorage(k), cb);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
root.set = function(k, v, cb) {
|
root.set = function(k, v, cb) {
|
||||||
if (platformInfo.isMobile) {
|
if (platformInfo.isMobile) {
|
||||||
|
|
@ -26,7 +36,7 @@ angular.module('copayApp.services').factory('secureStorageService', function(des
|
||||||
} else { // Browser
|
} else { // Browser
|
||||||
localStorageService.set(alteredKeyIndicatingDesireForSecureStorage(k), v, cb);
|
localStorageService.set(alteredKeyIndicatingDesireForSecureStorage(k), v, cb);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
});
|
});
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
angular.module('copayApp.services')
|
angular.module('copayApp.services')
|
||||||
.factory('storageService', function(appConfigService, logHeader, fileStorageService, localStorageService, sjcl, $log, lodash, platformInfo, secureStorageService, $timeout) {
|
.factory('storageService', function(appConfigService, encryptionService, jsonEncryptionService, logHeader, fileStorageService, localStorageService, sjcl, $log, lodash, platformInfo, secureStorageService, $timeout) {
|
||||||
|
|
||||||
var root = {};
|
var root = {};
|
||||||
var storage;
|
var storage;
|
||||||
|
|
@ -32,7 +32,7 @@ angular.module('copayApp.services')
|
||||||
// This is only used in Copay, we used to encrypt profile
|
// This is only used in Copay, we used to encrypt profile
|
||||||
// using device's UUID.
|
// using device's UUID.
|
||||||
|
|
||||||
var decryptOnMobile = function(text, cb) {
|
var copayDecryptOnMobile = function(text, cb) {
|
||||||
var json;
|
var json;
|
||||||
try {
|
try {
|
||||||
json = JSON.parse(text);
|
json = JSON.parse(text);
|
||||||
|
|
@ -121,11 +121,22 @@ angular.module('copayApp.services')
|
||||||
|
|
||||||
root.storeProfile = function(profile, cb) {
|
root.storeProfile = function(profile, cb) {
|
||||||
var profileString = profile.toObj();
|
var profileString = profile.toObj();
|
||||||
if (platformInfo.isNW) {
|
encryptionService.encrypt(profileString, function onProfileEncrypted(encryptionErr, encryptedProfile){
|
||||||
storage.set('profile', profileString, cb);
|
if (encryptionErr) {
|
||||||
} else {
|
$log.error('Failed to encrypt profile.', encryptionErr);
|
||||||
secureStorageService.set('profile', profileString, cb);
|
cb(encryptionErr, null);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$log.debug('storing profile ciphertext:', JSON.stringify(encryptedProfile.ciphertext));
|
||||||
|
var persistentProfileStr = jsonEncryptionService.stringify(
|
||||||
|
encryptedProfile.ciphertext,
|
||||||
|
encryptedProfile.opts
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
storage.set('profile', persistentProfileStr, cb);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -150,7 +161,7 @@ angular.module('copayApp.services')
|
||||||
return cb(null, null);
|
return cb(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptOnMobile(profileStr, function(decryptErr, decryptedStr) {
|
copayDecryptOnMobile(profileStr, function(decryptErr, decryptedStr) {
|
||||||
if (decryptErr) return cb(decryptErr, null);
|
if (decryptErr) return cb(decryptErr, null);
|
||||||
var profile;
|
var profile;
|
||||||
try {
|
try {
|
||||||
|
|
@ -200,53 +211,113 @@ angular.module('copayApp.services')
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function _migrateUnencryptedProfile(profileStr, cb) {
|
||||||
|
copayDecryptOnMobile(profileStr, function(decryptErr, decryptedStr) {
|
||||||
|
if (decryptErr) return cb(decryptErr, null);
|
||||||
|
var profile;
|
||||||
|
try {
|
||||||
|
profile = Profile.fromString(decryptedStr);
|
||||||
|
} catch (e) {
|
||||||
|
$log.error('Could not read profile:', e);
|
||||||
|
return cb(new Error('Could not read profile.'), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the only change to the contents of the profile.
|
||||||
|
profile.setAppVersion(appConfigService.version);
|
||||||
|
var newProfileStr = profile.toObj();
|
||||||
|
|
||||||
|
encryptionService.encrypt(newProfileStr, function onProfileEncrypted(encryptErr, encryptedProfile){
|
||||||
|
if (encryptErr) {
|
||||||
|
$log.error('Failed to encrypt profile.', encryptErr);
|
||||||
|
cb(encryptErr, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var persistentProfileStr;
|
||||||
|
try {
|
||||||
|
persistentProfileStr = jsonEncryptionService.stringify(encryptedProfile.ciphertext, encryptedProfile.opts);
|
||||||
|
} catch(e) {
|
||||||
|
$log.error('Failed to stringify to encrypted profile.', e);
|
||||||
|
cb(e, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
storage.set('profile', persistentProfileStr, function onEncryptedProfileStored(setErr) {
|
||||||
|
if (setErr) {
|
||||||
|
$log.error('Failed to store encrypted profile.', setErr);
|
||||||
|
cb(setErr, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cb (null, profile);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {getProfileCallback} cb
|
* @param {getProfileCallback} cb
|
||||||
*/
|
*/
|
||||||
root.getProfile = function(cb) {
|
root.getProfile = function(cb) {
|
||||||
if (platformInfo.isNW) {
|
$log.debug('getProfile()');
|
||||||
storage.get('profile', function(getErr, getStr) {
|
storage.get('profile', function onProfileRetrieved(getErr, profileStr){
|
||||||
_onOldProfileRetrieved(getErr, getStr, cb);
|
if (getErr) {
|
||||||
});
|
$log.error(getErr);
|
||||||
|
return cb(getErr, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!profileStr) {
|
||||||
|
$log.debug('No string loaded, returning nothing.');
|
||||||
|
// Don't want to use the same key as a previous installation
|
||||||
|
encryptionService.removeKeyIfExists();
|
||||||
|
return cb(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var isEncrypted = jsonEncryptionService.isEncrypted(profileStr);
|
||||||
|
if (isEncrypted) {
|
||||||
|
$log.debug('profile was encrypted.');
|
||||||
|
$log.debug('profileStr: ', profileStr);
|
||||||
|
|
||||||
|
var encryptedProfileObject;
|
||||||
|
try {
|
||||||
|
encryptedProfileObject = jsonEncryptionService.parse(profileStr);
|
||||||
|
} catch (e) {
|
||||||
|
$log.error('Failed to parse encrypted profile.', e);
|
||||||
|
cb(e, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$log.debug('profileStr after JSON: ', JSON.stringify(encryptedProfileObject));
|
||||||
|
|
||||||
|
encryptionService.decrypt(
|
||||||
|
encryptedProfileObject.ciphertext,
|
||||||
|
encryptedProfileObject.opts,
|
||||||
|
function onDecrypted(decryptionError, decryptedProfile) {
|
||||||
|
if (decryptionError) {
|
||||||
|
$log.error('Failed to decrypt profile');
|
||||||
|
cb(decryptionError, null);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
secureStorageService.get('profile', function(secureErr, secureStr) {
|
$log.debug('Decrypted profile:', JSON.stringify(decryptedProfile));
|
||||||
var secureProfile;
|
|
||||||
var oldProfile;
|
|
||||||
|
|
||||||
if (secureErr) {
|
var profileObj = Profile.fromString(decryptedProfile);
|
||||||
return cb(secureErr, null);
|
cb(null, profileObj);
|
||||||
}
|
});
|
||||||
|
|
||||||
if (secureStr) {
|
|
||||||
try {
|
|
||||||
secureProfile = Profile.fromString(secureStr);
|
|
||||||
$log.debug('profile: ' + JSON.stringify(secureProfile));
|
|
||||||
} catch (e) {
|
|
||||||
$log.error(e);
|
|
||||||
return cb(e, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
storage.get('profile', function(getErr, getStr) {
|
|
||||||
_onOldProfileRetrieved(getErr, getStr, function(oldErr, oldProfile){
|
|
||||||
if (oldErr) {
|
|
||||||
return cb(oldErr, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!oldProfile) {
|
|
||||||
if (secureProfile) {
|
|
||||||
return cb(null, secureProfile);
|
|
||||||
} else {
|
} else {
|
||||||
// No profiles found. No errors either.
|
_migrateUnencryptedProfile(profileStr, function onProfileMigrated(migrationErr, migratedProfile){
|
||||||
return cb(null, null);
|
if (migrationErr) {
|
||||||
|
$log.error('Failed to migrate the profile.', migrationErr);
|
||||||
|
cb(migraionErr, null);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cb(null, migratedProfile);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
_migrateProfiles(oldProfile, secureProfile, cb);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue