From 69c5c3bc2e8675951b6e4477a976d93fdffe8ee2 Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Thu, 17 Apr 2014 18:04:56 -0300 Subject: [PATCH] add setFromObj and getEncryptedObj to storage classes This is so that you can export the file from the browser and use the same file in the wallet file from the command-line. I have made encryption work equivalently between the browser and node. --- js/models/storage/Base.js | 13 +++++++++- js/models/storage/File.js | 24 ++++++++++++++++++ js/models/storage/LocalEncrypted.js | 21 +++++++++++++++- js/models/storage/LocalPlain.js | 24 ++++++++++++++++++ package.json | 3 ++- test/test.storage.File.js | 39 ++++++++++++++++++++++++++--- test/test.storage.LocalEncrypted.js | 12 +++++++++ test/test.storage.LocalPlain.js | 10 ++++++++ 8 files changed, 140 insertions(+), 6 deletions(-) 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'); + }); + }); }); }