Merge pull request #362 from ryanxcharles/feature/ECIES
add ECIES support
This commit is contained in:
commit
2dac2b1f47
|
@ -27,9 +27,11 @@ requireWhenAccessed('config', './config');
|
||||||
requireWhenAccessed('const', './const');
|
requireWhenAccessed('const', './const');
|
||||||
requireWhenAccessed('Curve', './lib/Curve');
|
requireWhenAccessed('Curve', './lib/Curve');
|
||||||
requireWhenAccessed('Deserialize', './lib/Deserialize');
|
requireWhenAccessed('Deserialize', './lib/Deserialize');
|
||||||
|
requireWhenAccessed('ECIES', './lib/ECIES');
|
||||||
requireWhenAccessed('log', './util/log');
|
requireWhenAccessed('log', './util/log');
|
||||||
requireWhenAccessed('networks', './networks');
|
requireWhenAccessed('networks', './networks');
|
||||||
requireWhenAccessed('SecureRandom', './lib/SecureRandom');
|
requireWhenAccessed('SecureRandom', './lib/SecureRandom');
|
||||||
|
requireWhenAccessed('sjcl', 'sjcl');
|
||||||
requireWhenAccessed('util', './util/util');
|
requireWhenAccessed('util', './util/util');
|
||||||
requireWhenAccessed('EncodedData', './util/EncodedData');
|
requireWhenAccessed('EncodedData', './util/EncodedData');
|
||||||
requireWhenAccessed('VersionedData', './util/VersionedData');
|
requireWhenAccessed('VersionedData', './util/VersionedData');
|
||||||
|
|
|
@ -11,6 +11,9 @@ var puts = function(error, stdout, stderr) {
|
||||||
//sys.puts(stderr);
|
//sys.puts(stderr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//compile sjcl
|
||||||
|
exec('cd node_modules/sjcl && ./configure --without-all --with-aes --with-convenience --with-cbc --with-codecHex --with-codecBase64 --with-sha512 --with-hmac && make && cd ../..;', puts);
|
||||||
|
|
||||||
var pack = function (params) {
|
var pack = function (params) {
|
||||||
var file = require.resolve('soop');
|
var file = require.resolve('soop');
|
||||||
var dir = file.substr(0, file.length - String('soop.js').length);
|
var dir = file.substr(0, file.length - String('soop.js').length);
|
||||||
|
@ -32,6 +35,7 @@ var modules = [
|
||||||
'lib/Connection',
|
'lib/Connection',
|
||||||
'lib/Curve',
|
'lib/Curve',
|
||||||
'lib/Deserialize',
|
'lib/Deserialize',
|
||||||
|
'lib/ECIES',
|
||||||
'lib/Electrum',
|
'lib/Electrum',
|
||||||
'lib/Message',
|
'lib/Message',
|
||||||
'lib/Opcode',
|
'lib/Opcode',
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1373,6 +1373,8 @@ exports.write = function(buffer, value, offset, isLE, mLen, nBytes) {
|
||||||
buffer[offset + i - d] |= s * 128;
|
buffer[offset + i - d] |= s * 128;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
},{}],"testdata":[function(require,module,exports){
|
||||||
|
module.exports=require('CoCQri');
|
||||||
},{}],"CoCQri":[function(require,module,exports){
|
},{}],"CoCQri":[function(require,module,exports){
|
||||||
(function (Buffer){
|
(function (Buffer){
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
@ -1413,6 +1415,4 @@ module.exports.dataRawBlock = buffer;
|
||||||
|
|
||||||
|
|
||||||
}).call(this,require("buffer").Buffer)
|
}).call(this,require("buffer").Buffer)
|
||||||
},{"buffer":2,"fs":1}],"testdata":[function(require,module,exports){
|
},{"buffer":2,"fs":1}]},{},[])
|
||||||
module.exports=require('CoCQri');
|
|
||||||
},{}]},{},[])
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
'use strict';
|
||||||
|
var imports = require('soop').imports();
|
||||||
|
var crypto = require('crypto');
|
||||||
|
var ECIES = require('./common/ECIES');
|
||||||
|
|
||||||
|
ECIES.symmetricEncrypt = function(key, iv, message) {
|
||||||
|
var cipheriv = crypto.createCipheriv('AES-256-CBC', key, iv);
|
||||||
|
var a = cipheriv.update(message);
|
||||||
|
var b = cipheriv.final();
|
||||||
|
var r = Buffer.concat([iv, a, b]);
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
ECIES.symmetricDecrypt = function(key, encrypted) {
|
||||||
|
var iv = encrypted.slice(0, 16);
|
||||||
|
var decipheriv = crypto.createDecipheriv('AES-256-CBC', key, iv);
|
||||||
|
var todecrypt = encrypted.slice(16, encrypted.length);
|
||||||
|
var a = decipheriv.update(todecrypt);
|
||||||
|
var b = decipheriv.final();
|
||||||
|
var r = Buffer.concat([a, b]);
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = require('soop')(ECIES);
|
|
@ -1,5 +1,4 @@
|
||||||
var imports = require('soop').imports();
|
var imports = require('soop').imports();
|
||||||
var _ = imports._ || require('underscore');
|
|
||||||
var log = imports.log || require('../util/log');
|
var log = imports.log || require('../util/log');
|
||||||
var bitcoreDefaults = imports.config || require('../config');
|
var bitcoreDefaults = imports.config || require('../config');
|
||||||
var Connection = imports.Connection || require ('./Connection');
|
var Connection = imports.Connection || require ('./Connection');
|
||||||
|
@ -12,7 +11,11 @@ GetAdjustedTime = imports.GetAdjustedTime || function () {
|
||||||
|
|
||||||
function PeerManager(config) {
|
function PeerManager(config) {
|
||||||
// extend defaults with config
|
// extend defaults with config
|
||||||
this.config = _.extend(bitcoreDefaults, config || {});
|
this.config = config || {};
|
||||||
|
for (var i in bitcoreDefaults)
|
||||||
|
if (bitcoreDefaults.hasOwnProperty(i) && this.config[i] === undefined)
|
||||||
|
this.config[i] = bitcoreDefaults[i];
|
||||||
|
|
||||||
this.active = false;
|
this.active = false;
|
||||||
this.timer = null;
|
this.timer = null;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
'use strict';
|
||||||
|
var imports = require('soop').imports();
|
||||||
|
var sjcl = require('sjcl');
|
||||||
|
var ECIES = require('../common/ECIES');
|
||||||
|
|
||||||
|
ECIES.symmetricEncrypt = function(key, iv, message) {
|
||||||
|
var skey = sjcl.codec.hex.toBits(key.toString('hex'));
|
||||||
|
var siv = sjcl.codec.hex.toBits(iv.toString('hex'));
|
||||||
|
var smessage = sjcl.codec.hex.toBits(message.toString('hex'));
|
||||||
|
|
||||||
|
sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."]();
|
||||||
|
var params = {iv: siv, ks: 256, ts: 128, iter: 1000, mode: 'cbc'};
|
||||||
|
var encrypted = sjcl.encrypt(skey, smessage, params);
|
||||||
|
var enchex = sjcl.codec.hex.fromBits(sjcl.codec.base64.toBits(JSON.parse(encrypted).ct));
|
||||||
|
|
||||||
|
var encbuf = new Buffer(enchex, 'hex');
|
||||||
|
|
||||||
|
var r = Buffer.concat([iv, encbuf]);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
ECIES.symmetricDecrypt = function(key, encrypted) {
|
||||||
|
var skey = sjcl.codec.hex.toBits(key.toString('hex'));
|
||||||
|
var iv = encrypted.slice(0, 16);
|
||||||
|
var todecrypt = encrypted.slice(16, encrypted.length);
|
||||||
|
|
||||||
|
var siv = sjcl.codec.base64.fromBits(sjcl.codec.hex.toBits(iv.toString('hex')));
|
||||||
|
var sct = sjcl.codec.base64.fromBits(sjcl.codec.hex.toBits(todecrypt.toString('hex')));
|
||||||
|
|
||||||
|
sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."]();
|
||||||
|
var obj = {iv: siv, v: 1, iter: 1000, ks: 256, ts: 128, mode: 'cbc', adata: '', cipher: 'aes', ct: sct};
|
||||||
|
var str = JSON.stringify(obj);
|
||||||
|
|
||||||
|
var decrypted = sjcl.decrypt(skey, str);
|
||||||
|
var decbuf = new Buffer(decrypted);
|
||||||
|
|
||||||
|
return decbuf;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = require('soop')(ECIES);
|
|
@ -0,0 +1,113 @@
|
||||||
|
'use strict';
|
||||||
|
var imports = require('soop').imports();
|
||||||
|
var coinUtil = imports.coinUtil || require('../../util');
|
||||||
|
var Point = imports.Point || require('../Point');
|
||||||
|
var SecureRandom = imports.SecureRandom || require('../SecureRandom');
|
||||||
|
var Key = imports.Key || require('../Key');
|
||||||
|
|
||||||
|
// http://en.wikipedia.org/wiki/Integrated_Encryption_Scheme
|
||||||
|
var ECIES = function() {
|
||||||
|
};
|
||||||
|
|
||||||
|
ECIES.encryptObj = function(pubkey, message, r, iv) {
|
||||||
|
var ecies = new ECIES();
|
||||||
|
ecies.KB = pubkey;
|
||||||
|
ecies.message = message;
|
||||||
|
r = ecies.getRandomSeed(r);
|
||||||
|
var R = ecies.R;
|
||||||
|
var S = ecies.S = ecies.getSfromPubkey();
|
||||||
|
var buf = ECIES.kdf(S);
|
||||||
|
var kE = ecies.kE = buf.slice(0, 32);
|
||||||
|
var kM = ecies.kM = buf.slice(32, 64);
|
||||||
|
iv = iv || SecureRandom.getRandomBuffer(16);
|
||||||
|
var c = ecies.c = ECIES.symmetricEncrypt(kE, iv, message);
|
||||||
|
var d = ecies.d = ECIES.mac(kM, c);
|
||||||
|
return ecies;
|
||||||
|
};
|
||||||
|
|
||||||
|
ECIES.encrypt = function(pubkey, message, r, iv) {
|
||||||
|
var ecies = ECIES.encryptObj(pubkey, message, r, iv);
|
||||||
|
var key = new Key();
|
||||||
|
key.compressed = false;
|
||||||
|
key.public = ecies.R.toUncompressedPubKey();
|
||||||
|
key.compressed = true;
|
||||||
|
var Rbuf = key.public;
|
||||||
|
var buf = Buffer.concat([Rbuf, ecies.c, ecies.d]);
|
||||||
|
return buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
ECIES.decryptObj = function(ecies) {
|
||||||
|
var kB = ecies.kB;
|
||||||
|
var R = ecies.R;
|
||||||
|
var c = ecies.c;
|
||||||
|
var d = ecies.d;
|
||||||
|
var P = Point.multiply(R, kB);
|
||||||
|
var S = P.x.toBuffer({size: 32});
|
||||||
|
var buf = ECIES.kdf(S);
|
||||||
|
var kE = ecies.kE = buf.slice(0, 32);
|
||||||
|
var kM = ecies.kM = buf.slice(32, 64);
|
||||||
|
var d2 = ECIES.mac(kM, c);
|
||||||
|
if (d.toString('hex') !== d2.toString('hex'))
|
||||||
|
throw new Error('MAC check incorrect. Data is invalid.');
|
||||||
|
var decrypted = ECIES.symmetricDecrypt(kE, c);
|
||||||
|
return decrypted;
|
||||||
|
};
|
||||||
|
|
||||||
|
ECIES.decrypt = function(privkey, buf) {
|
||||||
|
if (buf.length < 33 + 0 + 64)
|
||||||
|
throw new Error('invalid length of encrypted data');
|
||||||
|
var ecies = new ECIES();
|
||||||
|
ecies.kB = privkey;
|
||||||
|
var Rbuf = buf.slice(0, 33);
|
||||||
|
var key = new Key();
|
||||||
|
key.public = Rbuf;
|
||||||
|
key.compressed = false;
|
||||||
|
ecies.R = Point.fromUncompressedPubKey(key.public);
|
||||||
|
ecies.c = buf.slice(33, buf.length - 64);
|
||||||
|
ecies.d = buf.slice(buf.length - 64, buf.length);
|
||||||
|
return ECIES.decryptObj(ecies);
|
||||||
|
};
|
||||||
|
|
||||||
|
ECIES.kdf = function(S) {
|
||||||
|
var buf = coinUtil.sha512(S);
|
||||||
|
return buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
ECIES.mac = function(data, key) {
|
||||||
|
var buf = coinUtil.sha512hmac(data, key);
|
||||||
|
return buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
ECIES.prototype.getRandomSeed = function(r) {
|
||||||
|
if (r) {
|
||||||
|
this.key = new Key();
|
||||||
|
this.key.private = r;
|
||||||
|
this.key.regenerateSync();
|
||||||
|
} else {
|
||||||
|
this.key = Key.generateSync();
|
||||||
|
};
|
||||||
|
this.r = this.key.private;
|
||||||
|
this.key.compressed = false;
|
||||||
|
this.R = Point.fromUncompressedPubKey(this.key.public);
|
||||||
|
return this.r;
|
||||||
|
};
|
||||||
|
|
||||||
|
ECIES.prototype.getSfromPubkey = function() {
|
||||||
|
var key2 = new Key();
|
||||||
|
key2.public = this.KB;
|
||||||
|
key2.compressed = false;
|
||||||
|
var KBP = Point.fromUncompressedPubKey(key2.public);
|
||||||
|
this.P = Point.multiply(KBP, this.r);
|
||||||
|
this.S = this.P.x.toBuffer({size: 32});
|
||||||
|
return this.S;
|
||||||
|
};
|
||||||
|
|
||||||
|
ECIES.prototype.getSfromPrivkey = function() {
|
||||||
|
var R = this.R;
|
||||||
|
var kB = this.kB;
|
||||||
|
var SP = Point.multiply(R, kB);
|
||||||
|
var S = SP.x.toBuffer({size: 32});
|
||||||
|
return S;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = require('soop')(ECIES);
|
|
@ -52,7 +52,7 @@
|
||||||
"prepublish": "node browser/build.js -a"
|
"prepublish": "node browser/build.js -a"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jssha": "=1.5.0",
|
"sjcl": "=1.0.1",
|
||||||
"soop": "=0.1.5",
|
"soop": "=0.1.5",
|
||||||
"bindings": "=1.1.1",
|
"bindings": "=1.1.1",
|
||||||
"bufferput": "git://github.com/bitpay/node-bufferput.git",
|
"bufferput": "git://github.com/bitpay/node-bufferput.git",
|
||||||
|
@ -63,14 +63,12 @@
|
||||||
"buffertools": "=2.1.2",
|
"buffertools": "=2.1.2",
|
||||||
"browserify": "=3.40.0",
|
"browserify": "=3.40.0",
|
||||||
"browser-pack": "=2.0.1",
|
"browser-pack": "=2.0.1",
|
||||||
"commander": "=2.1.0",
|
|
||||||
"browserify-buffertools": "git://github.com/maraoz/browserify-buffertools.git",
|
"browserify-buffertools": "git://github.com/maraoz/browserify-buffertools.git",
|
||||||
"socks5-client": "~0.3.6",
|
"socks5-client": "~0.3.6",
|
||||||
"brfs": "=1.0.0",
|
"brfs": "=1.0.0",
|
||||||
"chai": "=1.9.1",
|
"chai": "=1.9.1",
|
||||||
"uglifyify": "=1.2.3",
|
"uglifyify": "=1.2.3",
|
||||||
"async": "~0.2.10",
|
"async": "~0.2.10"
|
||||||
"underscore": "~1.6.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"brfs": "~1.0.0",
|
"brfs": "~1.0.0",
|
||||||
|
@ -103,6 +101,7 @@
|
||||||
"bignum": "./lib/browser/Bignum.js",
|
"bignum": "./lib/browser/Bignum.js",
|
||||||
"./lib/Key.js": "./lib/browser/Key.js",
|
"./lib/Key.js": "./lib/browser/Key.js",
|
||||||
"./lib/Point.js": "./lib/browser/Point.js",
|
"./lib/Point.js": "./lib/browser/Point.js",
|
||||||
|
"./lib/ECIES.js": "./lib/browser/ECIES.js",
|
||||||
"./lib/SecureRandom.js": "./lib/browser/SecureRandom.js"
|
"./lib/SecureRandom.js": "./lib/browser/SecureRandom.js"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
<script src="test.Bloom.js"></script>
|
<script src="test.Bloom.js"></script>
|
||||||
<script src="test.Connection.js"></script>
|
<script src="test.Connection.js"></script>
|
||||||
<script src="test.Curve.js"></script>
|
<script src="test.Curve.js"></script>
|
||||||
|
<script src="test.ECIES.js"></script>
|
||||||
<script src="test.EncodedData.js"></script>
|
<script src="test.EncodedData.js"></script>
|
||||||
<script src="test.Electrum.js"></script>
|
<script src="test.Electrum.js"></script>
|
||||||
<script src="test.Key.js"></script>
|
<script src="test.Key.js"></script>
|
||||||
|
|
|
@ -0,0 +1,186 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var chai = chai || require('chai');
|
||||||
|
var bitcore = bitcore || require('../bitcore');
|
||||||
|
var should = chai.should();
|
||||||
|
var assert = chai.assert;
|
||||||
|
var ECIES = bitcore.ECIES;
|
||||||
|
var Point = bitcore.Point;
|
||||||
|
|
||||||
|
describe('ECIES', function() {
|
||||||
|
|
||||||
|
describe('#getRandomSeed', function() {
|
||||||
|
|
||||||
|
it('should set r and R', function() {
|
||||||
|
var ecies = new ECIES();
|
||||||
|
ecies.getRandomSeed();
|
||||||
|
ecies.r.length.should.equal(32);
|
||||||
|
ecies.R.toUncompressedPubKey().length.should.equal(65);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set the same r twice in a row', function() {
|
||||||
|
var ecies = new ECIES();
|
||||||
|
ecies.getRandomSeed();
|
||||||
|
var ecies2 = new ECIES();
|
||||||
|
ecies2.getRandomSeed();
|
||||||
|
ecies.r.toString('hex').should.not.equal(ecies2.r.toString('hex'));
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#encryptObj', function() {
|
||||||
|
|
||||||
|
it('should not fail', function() {
|
||||||
|
var key = new bitcore.Key();
|
||||||
|
key.private = bitcore.util.sha256('test');
|
||||||
|
key.regenerateSync();
|
||||||
|
|
||||||
|
var message = new Buffer('this is my message');
|
||||||
|
var ecies = ECIES.encryptObj(key.public, message);
|
||||||
|
|
||||||
|
should.exist(ecies.R);
|
||||||
|
should.exist(ecies.c);
|
||||||
|
should.exist(ecies.d);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#encrypt', function() {
|
||||||
|
|
||||||
|
it('should not fail', function() {
|
||||||
|
var key = new bitcore.Key();
|
||||||
|
key.private = bitcore.util.sha256('test');
|
||||||
|
key.regenerateSync();
|
||||||
|
|
||||||
|
var message = new Buffer('this is my message');
|
||||||
|
var encrypted = ECIES.encrypt(key.public, message);
|
||||||
|
|
||||||
|
should.exist(encrypted);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#decrypt', function() {
|
||||||
|
|
||||||
|
it('should not fail', function() {
|
||||||
|
var key = new bitcore.Key();
|
||||||
|
key.private = bitcore.util.sha256('test');
|
||||||
|
key.regenerateSync();
|
||||||
|
|
||||||
|
var message = new Buffer('this is my message');
|
||||||
|
var encrypted = ECIES.encrypt(key.public, message);
|
||||||
|
|
||||||
|
var decrypted = ECIES.decrypt(key.private, encrypted);
|
||||||
|
|
||||||
|
decrypted.toString().should.equal('this is my message');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not fail for long messages', function() {
|
||||||
|
var key = new bitcore.Key();
|
||||||
|
key.private = bitcore.util.sha256('test');
|
||||||
|
key.regenerateSync();
|
||||||
|
|
||||||
|
var message = new Buffer('this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message ');
|
||||||
|
|
||||||
|
var encrypted = ECIES.encrypt(key.public, message);
|
||||||
|
|
||||||
|
var decrypted = ECIES.decrypt(key.private, encrypted);
|
||||||
|
|
||||||
|
decrypted.toString().should.equal(message.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should encrypt this long message the same way every time when r and iv are specified', function() {
|
||||||
|
var key = new bitcore.Key();
|
||||||
|
key.private = bitcore.util.sha256('test');
|
||||||
|
key.regenerateSync();
|
||||||
|
|
||||||
|
var message = new Buffer('this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message this is my message ');
|
||||||
|
|
||||||
|
var encrypted = ECIES.encrypt(key.public, message, key.private, key.private.slice(0, 16));
|
||||||
|
|
||||||
|
encrypted.toString('hex').should.equal('025f81956d5826bad7d30daed2b5c8c98e72046c1ec8323da336445476183fb7ca9f86d081884c7d659a2feaa0c55ad015205e30d1ecdcfd17e437e91a7fef7859770462f56d111f979aa2d728ef9ccf206dd2f2db2e1f38ae4b2ab56cbee1401c4e9d63f0a44195224b5ae6b22e624ab0f5c6591de07c050751dce6e4137e2f1647990da4877e700f7669bb8644bcaac1cd794a00a4de248af4f86e94bc1aab8b873f5602a86c4b55546565948634f54ce22fd16c5eba57e412dfd518706152f457df1460f958f86a5952f48e64473b8abff30d25914f6240bd033f89e6b1c5365c12c4dd6d9bc8648b64c68f90de3f2fa70c1437a6b803213424f85c382e9d5c9d1027f46eb0d831d94a8986ed682d8265d73d40e3ca497536342a4144df9cb798c94a6f6cebaab8c12e3549e81fcf96dec1430f756c03d04b4727e12b46dc03d7ea64c21c8afb9a99d2a10ac4315e89a6e3a85994b359fd9fba8005e2c8a8b1bbb4b95f44a4a27332ea6b55de2599f1ead09cd57578b99e53344538261e7a01d8ed9f0d015f77ae9dea00a99f1d90654c5def58ecace0e18a50c29796716c16e52ba5a94200342d398318c2f3def1a86b75c0e7c44f629b83e7f3e907a90fceb7ac7f73e10a3baebf0defa08539f28f107e2b18e0419443188941fa4c354812fd07e38c35f35423c509c3fe728822618585a7cc69898f6f76f0426db547c06596472f13d5334b9c1382adca9350957f2120d038945b154b76e5e63283e501c5c7a0896ad98f5f844eb1244477651fccba214dff2c1b3849c0dc5d6141667f071a16715ae05e35cece182296f0d030392718199025aa01aec1b70ab218ffb2fe019d236456f0428e642d84529ab690df43945c112e12f3b4455a1eb7b9648246882eff3e2be69aeb8b2d4d826c8e7d1f96d8c8f0119e69da5a5ba92be2b3079477fb4046ffaa0528ff3c10414583b196fd893f504f6caaa4966ffc40b8ec92891bd60b6b094ae0fdbcd85e2ae88b6c1be083f600a3c996ad5c3f344154791488b0fa3cb42bb8234ff73edafc35b6f0b661aea1afa7c83dc4616e547c72ec3a81138a237f5c70f7a33881b1b298b425f6ed6b172eb2b947c294887d37decf9a5712f6df8c9b48cd6366a9f1f56baf71f26c76ac873a73e361664a7fc54be48840276e4a9190ce5431abbd31b221540928295f173958207b00b7b20d60dfca7abf68b11ff2f5661eb70056f70852cae812373e1fd4a3460e2df8117e814c89ba22e4ba91f65f9e1b1bb21cae43004183633e222b558aaa285cf46489b4d9b0af8c91bc77e70eb985c245651b6b6ff6fa098d362bb338f56bbd1dc37791ac058ff47809492cf7b6b2397141c4ce6ca0012416b0970e3d3dcd7273da3866271da086645fb42ade49334a2e160e801a8f3fbea7c9c040912a4f3b1d8e1e12c02adeacb94fcbecd015a1dc68dfb714a57466ae179007eb23f7215e6bd2918e3ee942c5c53808ec4c142b1e546608019e35835a8d32b03f4e7453ff5caf4b00c6741c72b0868e6012b3a05dff9ed8b3f0c1767b634e6229cf8c831036275920c34d3e5fbf123d1e743a17545f756ac7ceffc52b7e0fb85db566a4893086c96fe2dfbe87b50a2f61e8a0a52511a857d50a11a1a60b8ea7e8c1688e41c8fff7cdbe5ecab897b9ad043d4c460c9d181da9b0d5fa5fad6e47adbae858e3c5152c3355cc662490355629afd235d46677ab7cf76c998c1dece64b9c614327d9e0a79420b80bc6e98fe001f0457f98b0be0c95aa7272e775319489853bd3f7c526c64bf7f8b57a6d895c5db97096051654933cb8719a1c573ac023636fe4999a3b241cb99346d161e9d487142b10e8a881fcbfb014d04d661415b654655c587848a7b445e5120d8259dcf69238b6c21c27af40222fb7b3bf9ad7420d9e982ad0c4e5010830f00bf2173d4061bc91c9d36e116798e127041c96faa672bf699931fd5f4e6358b6653d3502c03fc3f6f31c5082b8bfd05edcf138f578b7cc1adf139369f7e1a7fe7902fb097d292bc5c67f70c2499878e85ffe59fbfa7ce4a566ea6e9d3d7ae1ff2c4d11078d5484df92fce815487243459a9214d8a2dea4e2044addf21888a88bc3ec9d6d25092a64a4ed830eed0b53d14f9ddce6e0973162c84b0b7b1a96dd3b89e3f5a46198763b28570d020d6cb7bb48ed8c60e13b2f3771e8446d6311b93ef8');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#symmetricEncrypt', function() {
|
||||||
|
|
||||||
|
it('should not fail', function() {
|
||||||
|
var data = new Buffer([1, 2, 3, 4, 5]);
|
||||||
|
var key = bitcore.util.sha256('test');
|
||||||
|
var iv = bitcore.util.sha256('test').slice(0, 16);
|
||||||
|
var encrypted = ECIES.symmetricEncrypt(key, iv, data);
|
||||||
|
encrypted.length.should.equal(16 + 16);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#symmetricDecrypt', function() {
|
||||||
|
|
||||||
|
it('should decrypt that which was encrypted', function() {
|
||||||
|
var data = new Buffer([1, 2, 3, 4, 5]);
|
||||||
|
var key = bitcore.util.sha256('test');
|
||||||
|
var iv = bitcore.util.sha256('test').slice(0, 16);
|
||||||
|
var encrypted = ECIES.symmetricEncrypt(key, iv, data);
|
||||||
|
var decrypted = ECIES.symmetricDecrypt(key, encrypted);
|
||||||
|
decrypted[0].should.equal(1);
|
||||||
|
decrypted[4].should.equal(5);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#getSfromPubkey', function() {
|
||||||
|
|
||||||
|
it('should find S correctly', function() {
|
||||||
|
var key = new bitcore.Key();
|
||||||
|
key.private = bitcore.util.sha256('test');
|
||||||
|
key.regenerateSync();
|
||||||
|
var ecies = new ECIES();
|
||||||
|
ecies.r = bitcore.util.sha256('test test');
|
||||||
|
ecies.KB = key.public;
|
||||||
|
var S = ecies.getSfromPubkey();
|
||||||
|
S.toString('hex').should.equal('9de4c42c4190fa987d84ce735a0370f7bb42f8646cec6274c5420f5af8fbfdbc');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#getSfromPrivkey', function() {
|
||||||
|
|
||||||
|
it('should find S the same as getSfromPubkey', function() {
|
||||||
|
var key = new bitcore.Key();
|
||||||
|
key.private = bitcore.util.sha256('test');
|
||||||
|
key.regenerateSync();
|
||||||
|
|
||||||
|
var r = bitcore.util.sha256('test test');
|
||||||
|
var key2 = new bitcore.Key();
|
||||||
|
key2.private = r;
|
||||||
|
key2.regenerateSync();
|
||||||
|
key2.compressed = false;
|
||||||
|
var R = Point.fromUncompressedPubKey(key2.public);
|
||||||
|
|
||||||
|
var ecies = new ECIES();
|
||||||
|
ecies.r = r;
|
||||||
|
ecies.KB = key.public;
|
||||||
|
var S = ecies.getSfromPubkey();
|
||||||
|
|
||||||
|
var ecies2 = new ECIES();
|
||||||
|
ecies2.R = R;
|
||||||
|
ecies2.kB = key.private;
|
||||||
|
var S2 = ecies2.getSfromPrivkey();
|
||||||
|
|
||||||
|
S.toString('hex').should.equal(S2.toString('hex'));
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#kdf', function() {
|
||||||
|
|
||||||
|
it('should be sha512', function() {
|
||||||
|
var data = new Buffer([0, 1, 2, 3, 4, 5, 6]);
|
||||||
|
ECIES.kdf(data).toString('hex').should.equal(bitcore.util.sha512(data).toString('hex'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -7,6 +7,21 @@ var should = chai.should();
|
||||||
var buffertools = require('buffertools');
|
var buffertools = require('buffertools');
|
||||||
|
|
||||||
describe('util', function() {
|
describe('util', function() {
|
||||||
|
describe('sha512', function() {
|
||||||
|
it('should calculate this particular hash correctly', function() {
|
||||||
|
var data = new Buffer('test data');
|
||||||
|
var hash = coinUtil.sha512(data);
|
||||||
|
hash.toString('hex').should.equal('0e1e21ecf105ec853d24d728867ad70613c21663a4693074b2a3619c1bd39d66b588c33723bb466c72424e80e3ca63c249078ab347bab9428500e7ee43059d0d');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('sha512hmac', function() {
|
||||||
|
it('should calculate the value of this sha512hmac correctly', function() {
|
||||||
|
var data = new Buffer('data');
|
||||||
|
var key = new Buffer('key');
|
||||||
|
var mac = coinUtil.sha512hmac(data, key);
|
||||||
|
mac.toString('hex').should.equal('3c5953a18f7303ec653ba170ae334fafa08e3846f2efe317b87efce82376253cb52a8c31ddcde5a3a2eee183c2b34cb91f85e64ddbc325f7692b199473579c58');
|
||||||
|
});
|
||||||
|
});
|
||||||
describe('exist', function() {
|
describe('exist', function() {
|
||||||
it('should initialze the util object', function() {
|
it('should initialze the util object', function() {
|
||||||
should.exist(bitcore.util);
|
should.exist(bitcore.util);
|
||||||
|
|
25
util/util.js
25
util/util.js
|
@ -3,7 +3,7 @@ var bignum = require('bignum');
|
||||||
var Binary = require('binary');
|
var Binary = require('binary');
|
||||||
var Put = require('bufferput');
|
var Put = require('bufferput');
|
||||||
var buffertools = require('buffertools');
|
var buffertools = require('buffertools');
|
||||||
var jssha = require('jssha');
|
var sjcl = require('sjcl');
|
||||||
var browser;
|
var browser;
|
||||||
var inBrowser = !process.versions;
|
var inBrowser = !process.versions;
|
||||||
if (inBrowser) {
|
if (inBrowser) {
|
||||||
|
@ -14,12 +14,27 @@ var sha256 = exports.sha256 = function(data) {
|
||||||
return new Buffer(crypto.createHash('sha256').update(data).digest('binary'), 'binary');
|
return new Buffer(crypto.createHash('sha256').update(data).digest('binary'), 'binary');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var sha512 = exports.sha512 = function(data) {
|
||||||
|
if (inBrowser) {
|
||||||
|
var datahex = data.toString('hex');
|
||||||
|
var databits = sjcl.codec.hex.toBits(datahex);
|
||||||
|
var hashbits = sjcl.hash.sha512.hash(databits);
|
||||||
|
var hashhex = sjcl.codec.hex.fromBits(hashbits);
|
||||||
|
var hash = new Buffer(hashhex, 'hex');
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
|
return new Buffer(crypto.createHash('sha512').update(data).digest('binary'), 'binary');
|
||||||
|
};
|
||||||
|
|
||||||
var sha512hmac = exports.sha512hmac = function (data, key) {
|
var sha512hmac = exports.sha512hmac = function (data, key) {
|
||||||
if (inBrowser) {
|
if (inBrowser) {
|
||||||
var j = new jssha(data.toString('hex'), 'HEX');
|
var skey = sjcl.codec.hex.toBits(key.toString('hex'));
|
||||||
var hash = j.getHMAC(key.toString('hex'), "HEX", "SHA-512", "HEX");
|
var sdata = sjcl.codec.hex.toBits(data.toString('hex'));
|
||||||
hash = new Buffer(hash, 'hex');
|
var hmac = new sjcl.misc.hmac(skey, sjcl.hash.sha512);
|
||||||
return hash;
|
var encrypted = hmac.encrypt(sdata);
|
||||||
|
var enchex = sjcl.codec.hex.fromBits(encrypted);
|
||||||
|
var encbuf = new Buffer(enchex, 'hex');
|
||||||
|
return encbuf;
|
||||||
};
|
};
|
||||||
var hmac = crypto.createHmac('sha512', key);
|
var hmac = crypto.createHmac('sha512', key);
|
||||||
var hash = hmac.update(data).digest();
|
var hash = hmac.update(data).digest();
|
||||||
|
|
Loading…
Reference in New Issue