diff --git a/lib/crypto/siphash.js b/lib/crypto/siphash.js index bd149c9b..66160234 100644 --- a/lib/crypto/siphash.js +++ b/lib/crypto/siphash.js @@ -37,19 +37,19 @@ function siphash24(data, key, shift) { var i, d, v0, v1, v2, v3; // Init - v0 = c0.xor(k0); - v1 = c1.xor(k1); - v2 = c2.xor(k0); - v3 = c3.xor(k1); + v0 = c0.ixor(k0); + v1 = c1.ixor(k1); + v2 = c2.ixor(k0); + v3 = c3.ixor(k1); // Blocks for (i = 0; i < blocks; i++) { d = U64.fromRaw(data, p); p += 8; - v3.xor(d); + v3.ixor(d); sipround(v0, v1, v2, v3); sipround(v0, v1, v2, v3); - v0.xor(d); + v0.ixor(d); } switch (data.length & 7) { @@ -58,7 +58,7 @@ function siphash24(data, key, shift) { case 6: f0.hi |= data[p + 5] << 8; case 5: - f0.hi |= data[p + 4] << 0; + f0.hi |= data[p + 4]; case 4: f0.lo |= data[p + 3] << 24; case 3: @@ -66,53 +66,46 @@ function siphash24(data, key, shift) { case 2: f0.lo |= data[p + 1] << 8; case 1: - f0.lo |= data[p + 0] << 0; - if (f0.lo < 0) - f0.lo += 0x100000000; - if (f0.hi < 0) - f0.hi += 0x100000000; - break; - case 0: - break; + f0.lo |= data[p]; } // Finalization - v3.xor(f0); + v3.ixor(f0); sipround(v0, v1, v2, v3); sipround(v0, v1, v2, v3); - v0.xor(f0); - v2.xor(f1); + v0.ixor(f0); + v2.ixor(f1); sipround(v0, v1, v2, v3); sipround(v0, v1, v2, v3); sipround(v0, v1, v2, v3); sipround(v0, v1, v2, v3); - v0.xor(v1); - v0.xor(v2); - v0.xor(v3); + v0.ixor(v1); + v0.ixor(v2); + v0.ixor(v3); return v0.toRaw(); } function sipround(v0, v1, v2, v3) { - v0.add(v1); - v1.rotl(13); - v1.xor(v0); + v0.iadd(v1); + v1.irotl(13); + v1.ixor(v0); - v0.rotl(32); + v0.irotl(32); - v2.add(v3); - v3.rotl(16); - v3.xor(v2); + v2.iadd(v3); + v3.irotl(16); + v3.ixor(v2); - v0.add(v3); - v3.rotl(21); - v3.xor(v0); + v0.iadd(v3); + v3.irotl(21); + v3.ixor(v0); - v2.add(v1); - v1.rotl(17); - v1.xor(v2); + v2.iadd(v1); + v1.irotl(17); + v1.ixor(v2); - v2.rotl(32); + v2.irotl(32); } /** @@ -154,56 +147,31 @@ function U64(hi, lo) { if (!(this instanceof U64)) return new U64(hi, lo); - this.hi = 0; - this.lo = 0; - this.join(hi, lo); + this.hi = hi | 0; + this.lo = lo | 0; } -U64.prototype.join = function join(hi, lo) { - this.hi = hi >>> 0; - this.lo = lo >>> 0; +U64.prototype.iadd = function iadd(b) { + var a = this; + var sum, c; + + // Credit to @indutny for this method. + sum = (a.lo >>> 0) + (b.lo >>> 0); + c = (sum >= 0x100000000) | 0; + + a.hi = (((a.hi + b.hi) | 0) + c) | 0; + a.lo = sum | 0; + + return a; +}; + +U64.prototype.ixor = function ixor(b) { + this.hi ^= b.hi; + this.lo ^= b.lo; return this; }; -U64.prototype.add = function add(b) { - var a = this; - var a48 = a.hi >>> 16; - var a32 = a.hi & 0xffff; - var a16 = a.lo >>> 16; - var a00 = a.lo & 0xffff; - var b48 = b.hi >>> 16; - var b32 = b.hi & 0xffff; - var b16 = b.lo >>> 16; - var b00 = b.lo & 0xffff; - var c48 = 0; - var c32 = 0; - var c16 = 0; - var c00 = 0; - var hi, lo; - - c00 += a00 + b00; - c16 += c00 >>> 16; - c00 &= 0xffff; - c16 += a16 + b16; - c32 += c16 >>> 16; - c16 &= 0xffff; - c32 += a32 + b32; - c48 += c32 >>> 16; - c32 &= 0xffff; - c48 += a48 + b48; - c48 &= 0xffff; - - hi = (c48 << 16) | c32; - lo = (c16 << 16) | c00; - - return a.join(hi, lo); -}; - -U64.prototype.xor = function xor(b) { - return this.join(this.hi ^ b.hi, this.lo ^ b.lo); -}; - -U64.prototype.rotl = function rotl(bits) { +U64.prototype.irotl = function irotl(bits) { var ahi = this.hi; var alo = this.lo; var bhi = this.hi; @@ -232,13 +200,16 @@ U64.prototype.rotl = function rotl(bits) { } // a | b - return this.join(ahi | bhi, alo | blo); + this.hi = ahi | bhi; + this.lo = alo | blo; + + return this; }; U64.prototype.toRaw = function toRaw() { var data = Buffer.allocUnsafe(8); - data.writeUInt32LE(this.hi, 4, true); - data.writeUInt32LE(this.lo, 0, true); + data.writeUInt32LE(this.hi >>> 0, 4, true); + data.writeUInt32LE(this.lo >>> 0, 0, true); return data; };