Merge pull request #33 from isocolsky/encrypt

Encrypt/Decrypt
This commit is contained in:
Matias Alejo Garcia 2015-02-18 14:23:30 -03:00
commit 0dadfb2c2f
5 changed files with 84 additions and 10 deletions

View File

@ -18,9 +18,24 @@ var BASE_URL = 'http://localhost:3001/copay/api';
var WALLET_CRITICAL_DATA = ['xPrivKey', 'm', 'publicKeyRing'];
function _createProposalOpts(opts, signingKey) {
var hash = WalletUtils.getProposalHash(opts.toAddress, opts.amount, opts.message);
opts.proposalSignature = WalletUtils.signMessage(hash, signingKey);
return opts;
var args = {
toAddress: opts.toAddress,
amount: opts.amount,
message: _encryptProposalMessage(opts.message, signingKey),
};
var hash = WalletUtils.getProposalHash(args.toAddress, args.amount, args.message);
args.proposalSignature = WalletUtils.signMessage(hash, signingKey);
return args;
};
function _encryptProposalMessage(message, encryptingKey) {
if (!message) return null;
return WalletUtils.encryptMessage(message, encryptingKey);
};
function _decryptProposalMessage(message, encryptingKey) {
if (!message) return '';
return WalletUtils.decryptMessage(message, encryptingKey);
};
function _parseError(body) {
@ -392,7 +407,14 @@ API.prototype.getTxProposals = function(opts, cb) {
this._loadAndCheck(function(err, data) {
if (err) return cb(err);
var url = '/v1/txproposals/';
self._doGetRequest(url, data, cb);
self._doGetRequest(url, data, function(err, txps) {
if (err) return cb(err);
_.each(txps, function(txp) {
txp.message = self._decryptProposalMessage(txp.message, data.signingPrivKey);
});
return cb(null, txps);
});
});
};

View File

@ -5,6 +5,7 @@ var PrivateKey = Bitcore.PrivateKey;
var PublicKey = Bitcore.PublicKey;
var crypto = Bitcore.crypto;
var HDPath = require('./hdpath');
var sjcl = require('sjcl');
function WalletUtils() {};
@ -62,7 +63,7 @@ WalletUtils.xPubToCopayerId = function(xpub) {
};
WalletUtils.toSecret = function(walletId, walletPrivKey, network) {
return walletId + ':' + walletPrivKey.toWIF() + ':' + (network == 'testnet' ? 'T' : 'L');
return walletId + ':' + walletPrivKey.toWIF() + ':' + (network == 'testnet' ? 'T' : 'L');
};
WalletUtils.fromSecret = function(secret) {
@ -72,7 +73,7 @@ WalletUtils.fromSecret = function(secret) {
var networkChar = secretSplit[2];
return {
return {
walletId: walletId,
walletPrivKey: walletPrivKey,
network: networkChar == 'T' ? 'testnet' : 'livenet',
@ -80,6 +81,21 @@ WalletUtils.fromSecret = function(secret) {
};
WalletUtils.encryptMessage = function(message, privKey) {
var hash = sjcl.hash.sha256.hash(privKey);
var key = sjcl.codec.utf8String.toBits(hash);
key = sjcl.bitArray.clamp(key, 128);
return sjcl.encrypt(key, message, {
ks: 128,
iter: 1
});
};
WalletUtils.decryptMessage = function(cyphertextJson, privKey) {
var hash = sjcl.hash.sha256.hash(privKey);
var key = sjcl.codec.utf8String.toBits(hash);
key = sjcl.bitArray.clamp(key, 128);
return sjcl.decrypt(key, cyphertextJson);
};
module.exports = WalletUtils;

View File

@ -30,8 +30,9 @@
"morgan": "*",
"npmlog": "^0.1.1",
"preconditions": "^1.0.7",
"request": "^2.53.0",
"qr-image": "*",
"request": "^2.53.0",
"sjcl": "^1.0.2",
"uuid": "*"
},
"devDependencies": {

View File

@ -8,6 +8,7 @@ var Client = require('../../lib/client');
var API = Client.API;
var Bitcore = require('bitcore');
var TestData = require('./clienttestdata');
var WalletUtils = require('../../lib/walletutils');
describe('client API ', function() {
var client;
@ -156,14 +157,14 @@ describe('client API ', function() {
client.export(function(err, str) {
should.not.exist(err);
client.storage.fs.readFile = sinon.stub().yields(null);
client.import(str, function(err,wallet) {
client.storage.fs.readFile = sinon.stub().yields(null);
client.import(str, function(err, wallet) {
should.not.exist(err);
var wallet = JSON.parse(client.storage.fs.writeFile.getCall(0).args[1]);
TestData.storage.complete22.should.deep.equal(wallet);
done();
});
});
});
});
});
@ -172,6 +173,31 @@ describe('client API ', function() {
it.skip('Should recreate a wallet acording stored data', function(done) {});
});
describe('#sendTxProposal ', function() {
it('should send tx proposal with encrypted message', function(done) {
var response = {};
var request = sinon.mock().yields(null, {
statusCode: 200
}, response);
client.request = request;
var args = {
toAddress: '2N3fA6wDtnebzywPkGuNK9KkFaEzgbPRRTq',
amount: 100000,
message: 'some message',
};
client.sendTxProposal(args, function(err) {
var callArgs = request.getCall(0).args[0].body;
callArgs.toAddress.should.equal(args.toAddress);
callArgs.amount.should.equal(args.amount);
callArgs.message.should.not.equal(args.message);
var decryptedMsg = WalletUtils.decryptMessage(callArgs.message, '42798f82c4ed9ace4d66335165071edf180e70bc0fc08dacb3e35185a2141d5b');
decryptedMsg.should.equal(args.message);
done();
});
});
});
describe('#signTxProposal ', function() {
it.skip('should sign tx proposal', function(done) {});

View File

@ -65,4 +65,13 @@ describe('WalletUtils', function() {
WalletUtils.verifyMessage(aLongerText, sig, aPubKey).should.equal(true);
});
});
describe('#encryptMessage #decryptMessage round trip', function() {
it('should encrypt and decrypt', function() {
var pwd = '0dea92f1df6675085b5cdd965487bb862f84f2755bcb56fa45dbf5b387a6c4a0';
var ct = WalletUtils.encryptMessage('hello world', pwd);
var msg = WalletUtils.decryptMessage(ct, pwd);
msg.should.equal('hello world');
});
});
});