diff --git a/lib/crypto/siphash.js b/lib/crypto/siphash.js index 4261173a..bd149c9b 100644 --- a/lib/crypto/siphash.js +++ b/lib/crypto/siphash.js @@ -145,84 +145,94 @@ if (native) { } /* - * Helpers + * U64 + * @constructor + * @ignore */ function U64(hi, lo) { if (!(this instanceof U64)) return new U64(hi, lo); - this.hi = hi || 0; - this.lo = lo || 0; + this.hi = 0; + this.lo = 0; + this.join(hi, lo); } -U64.prototype.add = function add(b) { - var r, carry; - - r = this.lo + b.lo; - carry = (r - (r % 0x100000000)) / 0x100000000; - this.hi = (this.hi + b.hi + carry) & 0xffffffff; - this.lo = r & 0xffffffff; - - if (this.hi < 0) - this.hi += 0x100000000; - - if (this.lo < 0) - this.lo += 0x100000000; - +U64.prototype.join = function join(hi, lo) { + this.hi = hi >>> 0; + this.lo = lo >>> 0; 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) { - this.hi ^= b.hi; - this.lo ^= b.lo; - - if (this.hi < 0) - this.hi += 0x100000000; - - if (this.lo < 0) - this.lo += 0x100000000; - - return this; + return this.join(this.hi ^ b.hi, this.lo ^ b.lo); }; -U64.prototype.rotl = function rotl(b) { - var h1, l1, h2, l2, c; +U64.prototype.rotl = function rotl(bits) { + var ahi = this.hi; + var alo = this.lo; + var bhi = this.hi; + var blo = this.lo; - // v1 = x << b - if (b < 32) { - h1 = this.hi << b; - c = this.lo >>> (32 - b); - l1 = this.lo << b; - h1 |= c; + // a = x << b + if (bits < 32) { + ahi <<= bits; + ahi |= alo >>> (32 - bits); + alo <<= bits; } else { - h1 = this.lo << (b - 32); - l1 = 0; + ahi = alo << (bits - 32); + alo = 0; } - // v2 = x >> (64 - b) - b = 64 - b; - if (b < 32) { - h2 = this.hi >>> b; - c = this.hi & (0xffffffff >>> (32 - b)); - l2 = this.lo >>> b; - l2 |= c << (32 - b); + bits = 64 - bits; + + // b = x >> (64 - b) + if (bits < 32) { + blo >>>= bits; + blo |= bhi << (32 - bits); + bhi >>>= bits; } else { - h2 = 0; - l2 = this.hi >>> (b - 32); + blo = bhi >>> (bits - 32); + bhi = 0; } - // v1 | v2 - this.hi = h1 | h2; - this.lo = l1 | l2; - - if (this.hi < 0) - this.hi += 0x100000000; - - if (this.lo < 0) - this.lo += 0x100000000; - - return this; + // a | b + return this.join(ahi | bhi, alo | blo); }; U64.prototype.toRaw = function toRaw() {