diff --git a/js/models/storage/Base.js b/js/models/storage/Base.js index 29ca2564c..c023efe14 100644 --- a/js/models/storage/Base.js +++ b/js/models/storage/Base.js @@ -10,7 +10,7 @@ Storage.prototype.get = function(walletId,k) { }; // set value for key -Storage.prototype.set = function(walletId,v) { +Storage.prototype.set = function(walletId, k, v) { }; // remove value for key @@ -20,6 +20,17 @@ Storage.prototype.remove = function(walletId, k) { Storage.prototype.getWalletIds = function() { }; +// obj contains keys to be set +Storage.prototype.setFromObj = function(walletId, obj) { +}; + +Storage.prototype.setFromEncryptedObj = function(walletId, obj) { +}; + +// wallet export - hex of encrypted wallet object +Storage.prototype.getEncryptedObj = function(walletId) { +}; + // remove all values Storage.prototype.clearAll = function() { }; diff --git a/js/models/storage/File.js b/js/models/storage/File.js index 2c07b7010..3fca9154a 100644 --- a/js/models/storage/File.js +++ b/js/models/storage/File.js @@ -1,12 +1,19 @@ 'use strict'; var imports = require('soop').imports(); var fs = imports.fs || require('fs'); +var parent = imports.parent || require('./Base'); +var crypto = imports.crypto || require('crypto'); +var CryptoJS = require('node-cryptojs-aes').CryptoJS; + +var passwords = []; function Storage(opts) { opts = opts || {}; this.data = {}; + passwords[0] = opts.password; } +Storage.parent = parent; Storage.prototype.load = function(walletId, callback) { fs.readFile(walletId, function(err, data) { @@ -93,6 +100,23 @@ Storage.prototype.getWalletIds = function() { return []; }; +Storage.prototype.setFromObj = function(walletId, obj, callback) { + this.data[walletId] = obj; + this.save(walletId, callback); +}; + +Storage.prototype.setFromEncryptedObj = function(walletId) { + //TODO: implement +}; + +Storage.prototype.getEncryptedObj = function(walletId) { + var data = JSON.stringify(this.data[walletId]); + var encrypted = CryptoJS.AES.encrypt(data, passwords[0]); + var hex = CryptoJS.enc.Hex.stringify(CryptoJS.enc.Base64.parse(encrypted.toString())); + + return hex; +}; + // remove all values Storage.prototype.clearAll = function(callback) { this.data = {}; diff --git a/js/models/storage/LocalEncrypted.js b/js/models/storage/LocalEncrypted.js index 0ce45a915..b730b7bce 100644 --- a/js/models/storage/LocalEncrypted.js +++ b/js/models/storage/LocalEncrypted.js @@ -5,8 +5,13 @@ var imports = require('soop').imports(); var parent = imports.parent || require('./LocalPlain'); var id = 0; -function Storage() { +function Storage(opts) { + opts = opts || {}; + this.__uniqueid = ++id; + + if (opts.password) + this._setPassphrase(opts.password); } Storage.parent = parent; @@ -48,4 +53,18 @@ Storage.prototype._write = function(k,v) { localStorage.setItem(k, v); }; +Storage.prototype.getEncryptedObj = function(walletId) { + var keys = this._getWalletKeys(); + var obj = {}; + for (var i in keys) { + var key = keys[0]; + obj[key] = this.get(walletId, key); + } + + var str = JSON.stringify(obj); + var hex = CryptoJS.enc.Hex.stringify(CryptoJS.enc.Base64.parse(this._encrypt(str).toString())); + + return hex; +}; + module.exports = require('soop')(Storage); diff --git a/js/models/storage/LocalPlain.js b/js/models/storage/LocalPlain.js index d32234899..718636142 100644 --- a/js/models/storage/LocalPlain.js +++ b/js/models/storage/LocalPlain.js @@ -1,9 +1,11 @@ 'use strict'; var imports = require('soop').imports(); +var parent = imports.parent || require('./Base'); function Storage() { } +Storage.parent = parent; Storage.prototype._read = function(k) { var ret; @@ -17,6 +19,21 @@ Storage.prototype._write = function(k,v) { localStorage.setItem(k, JSON.stringify(v)); }; +Storage.prototype._getWalletKeys = function(walletId) { + var keys = []; + + for (var i = 0; i < localStorage.length; i++) { + var key = localStorage.key(i); + var split = key.split('::'); + if (split.length == 2) { + if (walletId = split[0]) + keys.push(split[1]); + } + } + + return keys; +}; + // get value by key Storage.prototype.getGlobal = function(k) { return this._read(k); @@ -67,6 +84,13 @@ Storage.prototype.getWalletIds = function() { return walletIds; }; +//obj contains keys to be set +Storage.prototype.setFromObj = function(walletId, obj) { + for (var k in obj) { + this.set(walletId, k, obj[k]); + } +}; + // remove all values Storage.prototype.clearAll = function() { localStorage.clear(); diff --git a/package.json b/package.json index 7e0cbdd62..99b94e0ee 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "soop": "~0.1.5", "bitcore": "git://github.com/maraoz/bitcore.git#5e636f6b9c7f8e629b1a502025556e886c3b75e1", "chai": "~1.9.1", - "sinon": "~1.9.1" + "sinon": "~1.9.1", + "node-cryptojs-aes": "=0.4.0" } } diff --git a/test/test.storage.File.js b/test/test.storage.File.js index b54a34215..20da9cbba 100644 --- a/test/test.storage.File.js +++ b/test/test.storage.File.js @@ -1,9 +1,11 @@ 'use strict'; -var chai = chai || require('chai'); +var chai = require('chai'); var should = chai.should(); -var Storage = Storage || require('../js/models/storage/File.js'); -var sinon = sinon || require('sinon'); +var Storage = require('../js/models/storage/File.js'); +var sinon = require('sinon'); +var crypto = require('crypto'); +var CryptoJS = require('node-cryptojs-aes').CryptoJS; describe('Storage/File', function() { it('should exist', function() { @@ -135,6 +137,37 @@ describe('Storage/File', function() { }); }); + describe('#setFromObj', function() { + it('should set this object for a wallet', function(done) { + var obj = {test:'testval'}; + var storage = new Storage(); + storage.save = function(walletId, callback) { + callback(); + }; + storage.setFromObj('walletId', obj, function() { + storage.data.walletId.test.should.equal('testval'); + done(); + }); + }); + }); + + describe('#getEncryptedObj', function() { + it('should give an encrypted object', function() { + var obj = {test:'testval'}; + var data = JSON.stringify(obj); + var encrypted = CryptoJS.AES.encrypt(data, 'password'); + var hex = CryptoJS.enc.Hex.stringify(CryptoJS.enc.Base64.parse(encrypted.toString())); + + var storage = new Storage({password: 'password'}); + storage.data['walletId'] = obj; + + var enc = storage.getEncryptedObj('walletId'); + enc.length.should.equal(96); + enc.slice(0,10).should.equal(hex.slice(0,10)); + enc.slice(0,6).should.equal("53616c"); + }); + }); + describe('#clearAll', function() { it('should set data to {}', function() { diff --git a/test/test.storage.LocalEncrypted.js b/test/test.storage.LocalEncrypted.js index 47e0b3858..80854b524 100644 --- a/test/test.storage.LocalEncrypted.js +++ b/test/test.storage.LocalEncrypted.js @@ -45,5 +45,17 @@ if (typeof process === 'undefined' || !process.version) { JSON.stringify(obj2).should.equal(JSON.stringify(obj)); }); }); + + describe('#getEncryptedObj', function() { + it('should encrypt the wallet', function() { + localStorage.clear(); + var storage = new LocalEncrypted({password: 'password'}); + storage.set('walletId', 'test', 'testval'); + var obj = {test:'testval'}; + var encrypted = storage.getEncryptedObj('walletId'); + encrypted.length.should.equal(96); + encrypted.slice(0,6).should.equal("53616c"); + }); + }); }); } diff --git a/test/test.storage.LocalPlain.js b/test/test.storage.LocalPlain.js index f600aa0e3..8c5dd3290 100644 --- a/test/test.storage.LocalPlain.js +++ b/test/test.storage.LocalPlain.js @@ -13,5 +13,15 @@ if (typeof process === 'undefined' || !process.version) { var s = new LocalPlain(); should.exist(s); }); + + describe('#setFromObj', function() { + it('should set keys from an object', function() { + localStorage.clear(); + var obj = {test:'testval'}; + var storage = new LocalPlain(); + storage.setFromObj('walletId', obj); + storage.get('walletId', 'test').should.equal('testval'); + }); + }); }); }