From a14da39384a3e1731efe79b65ac9cb996f425ab6 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 26 Aug 2016 02:26:07 -0700 Subject: [PATCH] bip152: refactor siphash. --- lib/crypto/siphash.js | 12 +++++------- lib/net/bip152.js | 24 +++++++++++++----------- lib/utils/utils.js | 7 ++++++- test/siphash-test.js | 9 ++++++--- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/lib/crypto/siphash.js b/lib/crypto/siphash.js index 5b5e032c..8ea8a592 100644 --- a/lib/crypto/siphash.js +++ b/lib/crypto/siphash.js @@ -11,13 +11,12 @@ /** * Javascript siphash implementation. Used for compact block relay. - * @param {Buffer} data - Blocks are uint64le's. - * @param {Buffer} k0 - Must be encoded as a uint64le. - * @param {Buffer} k1 - Must be encoded as a uint64le. + * @param {Buffer} data + * @param {Buffer} key - 128 bit key. * @returns {Buffer} uint64le */ -function siphash(data, k0, k1) { +function siphash(data, key) { var blocks = Math.ceil(data.length / 8); var c0 = U64(0x736f6d65, 0x70736575); var c1 = U64(0x646f7261, 0x6e646f6d); @@ -25,11 +24,10 @@ function siphash(data, k0, k1) { var c3 = U64(0x74656462, 0x79746573); var f0 = U64(blocks << 27, 0); var f1 = U64(0, 0xff); + var k0 = U64.fromRaw(key, 0); + var k1 = U64.fromRaw(key, 8); var i, d, v0, v1, v2, v3; - k0 = U64.fromRaw(k0); - k1 = U64.fromRaw(k1); - // Init v0 = c0.xor(k0); v1 = c1.xor(k1); diff --git a/lib/net/bip152.js b/lib/net/bip152.js index 23839ebb..bae64f62 100644 --- a/lib/net/bip152.js +++ b/lib/net/bip152.js @@ -36,8 +36,7 @@ function CompactBlock(options) { this.available = []; this.idMap = {}; this.count = 0; - this.k0 = null; - this.k1 = null; + this.sipKey = null; this.timeout = null; if (options) @@ -68,8 +67,7 @@ CompactBlock.prototype.fromOptions = function fromOptions(options) { if (options.count) this.count = options.count; - this.k0 = options.k0; - this.k1 = options.k1; + this.sipKey = options.sipKey; this.initKey(); this.init(); @@ -230,7 +228,7 @@ CompactBlock.prototype.sid = function sid(hash) { if (typeof hash === 'string') hash = new Buffer(hash, 'hex'); - hash = siphash(hash, this.k0, this.k1); + hash = siphash(hash, this.sipKey); return hash.readUInt32LE(0, true) + hash.readUInt16LE(4, true) @@ -242,10 +240,15 @@ CompactBlock.prototype.hasIndex = function hasIndex(index) { }; CompactBlock.prototype.initKey = function initKey() { - var data = Buffer.concat([this.abbr(), this.keyNonce]); - var hash = utils.sha256(data); - this.k0 = hash.slice(0, 8); - this.k1 = hash.slice(8, 16); + var data = new Buffer(88); + var hash; + + this.abbr().copy(data, 0); + this.keyNonce.copy(data, 80); + + hash = utils.sha256(data); + + this.sipKey = hash.slice(0, 16); }; CompactBlock.prototype.init = function init() { @@ -329,7 +332,7 @@ CompactBlock.prototype.fromBlock = function fromBlock(block, nonce) { this.totalTX = block.totalTX; if (!nonce) - nonce = utils.nonce().toArrayLike(Buffer, 'be', 8); + nonce = utils.nonce(true); this.keyNonce = nonce; @@ -554,7 +557,6 @@ TXResponse.prototype.toRaw = function toRaw(witness, writer) { * @constructor */ -// NOTE TO SELF: Protocol version >= 70014 function SendCompact(mode, version) { if (!(this instanceof SendCompact)) return new SendCompact(mode, version); diff --git a/lib/utils/utils.js b/lib/utils/utils.js index 87920d09..7a4c4432 100644 --- a/lib/utils/utils.js +++ b/lib/utils/utils.js @@ -1068,10 +1068,15 @@ utils.U64 = new bn('ffffffffffffffff', 'hex'); * @returns {BN} */ -utils.nonce = function _nonce() { +utils.nonce = function _nonce(buffer) { var nonce = new Buffer(8); + nonce.writeUInt32LE((Math.random() * 0x100000000) >>> 0, 0, true); nonce.writeUInt32LE((Math.random() * 0x100000000) >>> 0, 4, true); + + if (buffer) + return nonce; + return new bn(nonce); }; diff --git a/test/siphash-test.js b/test/siphash-test.js index 4989f27f..a5282c31 100644 --- a/test/siphash-test.js +++ b/test/siphash-test.js @@ -8,20 +8,23 @@ describe('SipHash', function() { it('should perform siphash with no data', function() { var k0 = U64(0x07060504, 0x03020100).toRaw(); var k1 = U64(0x0f0e0d0c, 0x0b0a0908).toRaw(); - assert.equal(siphash(new Buffer(0), k0, k1).toString('hex'), '310e0edd47db6f72'); + var key = Buffer.concat([k0, k1]); + assert.equal(siphash(new Buffer(0), key).toString('hex'), '310e0edd47db6f72'); }); it('should perform siphash with data', function() { var k0 = U64(0x07060504, 0x03020100).toRaw(); var k1 = U64(0x0f0e0d0c, 0x0b0a0908).toRaw(); var data = U64(0x07060504, 0x03020100).toRaw(); - assert.equal(siphash(data, k0, k1).toString('hex'), '6224939a79f5f593'); + var key = Buffer.concat([k0, k1]); + assert.equal(siphash(data, key).toString('hex'), '6224939a79f5f593'); }); it('should perform siphash with uint256', function() { var k0 = U64(0x07060504, 0x03020100).toRaw(); var k1 = U64(0x0f0e0d0c, 0x0b0a0908).toRaw(); var hash = new Buffer('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', 'hex'); - assert.equal(siphash(hash, k0, k1).toString('hex'), 'ce7cf2722f512771'); + var key = Buffer.concat([k0, k1]); + assert.equal(siphash(hash, key).toString('hex'), 'ce7cf2722f512771'); }); });