siphash: refactor.
This commit is contained in:
parent
5fa102d5bd
commit
22e90303a2
@ -18,166 +18,177 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function siphash(data, k0, k1) {
|
function siphash(data, k0, k1) {
|
||||||
var out = new Buffer(8);
|
|
||||||
var blocks = Math.ceil(data.length / 8);
|
var blocks = Math.ceil(data.length / 8);
|
||||||
var c0 = { hi: 0x736f6d65, lo: 0x70736575 };
|
var c0 = U64(0x736f6d65, 0x70736575);
|
||||||
var c1 = { hi: 0x646f7261, lo: 0x6e646f6d };
|
var c1 = U64(0x646f7261, 0x6e646f6d);
|
||||||
var c2 = { hi: 0x6c796765, lo: 0x6e657261 };
|
var c2 = U64(0x6c796765, 0x6e657261);
|
||||||
var c3 = { hi: 0x74656462, lo: 0x79746573 };
|
var c3 = U64(0x74656462, 0x79746573);
|
||||||
var f0 = { hi: blocks << 27, lo: 0 };
|
var f0 = U64(blocks << 27, 0);
|
||||||
var f1 = { hi: 0, lo: 0xff };
|
var f1 = U64(0, 0xff);
|
||||||
var i, d, v0, v1, v2, v3;
|
var i, d, v0, v1, v2, v3;
|
||||||
|
|
||||||
k0 = read(k0, 0);
|
k0 = U64.fromRaw(k0);
|
||||||
k1 = read(k1, 0);
|
k1 = U64.fromRaw(k1);
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
v0 = xor64(c0, k0);
|
v0 = c0.xor(k0);
|
||||||
v1 = xor64(c1, k1);
|
v1 = c1.xor(k1);
|
||||||
v2 = xor64(c2, k0);
|
v2 = c2.xor(k0);
|
||||||
v3 = xor64(c3, k1);
|
v3 = c3.xor(k1);
|
||||||
|
|
||||||
// Blocks
|
// Blocks
|
||||||
for (i = 0; i < blocks; i++) {
|
for (i = 0; i < blocks; i++) {
|
||||||
d = read(data, i * 8);
|
d = U64.fromRaw(data, i * 8);
|
||||||
xor64(v3, d);
|
v3.xor(d);
|
||||||
sipround(v0, v1, v2, v3);
|
sipround(v0, v1, v2, v3);
|
||||||
sipround(v0, v1, v2, v3);
|
sipround(v0, v1, v2, v3);
|
||||||
xor64(v0, d);
|
v0.xor(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalization
|
// Finalization
|
||||||
xor64(v3, f0);
|
v3.xor(f0);
|
||||||
sipround(v0, v1, v2, v3);
|
sipround(v0, v1, v2, v3);
|
||||||
sipround(v0, v1, v2, v3);
|
sipround(v0, v1, v2, v3);
|
||||||
xor64(v0, f0);
|
v0.xor(f0);
|
||||||
xor64(v2, f1);
|
v2.xor(f1);
|
||||||
sipround(v0, v1, v2, v3);
|
sipround(v0, v1, v2, v3);
|
||||||
sipround(v0, v1, v2, v3);
|
sipround(v0, v1, v2, v3);
|
||||||
sipround(v0, v1, v2, v3);
|
sipround(v0, v1, v2, v3);
|
||||||
sipround(v0, v1, v2, v3);
|
sipround(v0, v1, v2, v3);
|
||||||
xor64(v0, v1);
|
v0.xor(v1);
|
||||||
xor64(v0, v2);
|
v0.xor(v2);
|
||||||
xor64(v0, v3);
|
v0.xor(v3);
|
||||||
|
|
||||||
write(out, v0, 0);
|
return v0.toRaw();
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sipround(v0, v1, v2, v3) {
|
function sipround(v0, v1, v2, v3) {
|
||||||
sum64(v0, v1);
|
v0.add(v1);
|
||||||
rotl64(v1, 13);
|
v1.rotl(13);
|
||||||
xor64(v1, v0);
|
v1.xor(v0);
|
||||||
|
|
||||||
rotl64(v0, 32);
|
v0.rotl(32);
|
||||||
|
|
||||||
sum64(v2, v3);
|
v2.add(v3);
|
||||||
rotl64(v3, 16);
|
v3.rotl(16);
|
||||||
xor64(v3, v2);
|
v3.xor(v2);
|
||||||
|
|
||||||
sum64(v0, v3);
|
v0.add(v3);
|
||||||
rotl64(v3, 21);
|
v3.rotl(21);
|
||||||
xor64(v3, v0);
|
v3.xor(v0);
|
||||||
|
|
||||||
sum64(v2, v1);
|
v2.add(v1);
|
||||||
rotl64(v1, 17);
|
v1.rotl(17);
|
||||||
xor64(v1, v2);
|
v1.xor(v2);
|
||||||
|
|
||||||
rotl64(v2, 32);
|
v2.rotl(32);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers
|
* Helpers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function sum64(a, b) {
|
function U64(hi, lo) {
|
||||||
var r, carry;
|
if (!(this instanceof U64))
|
||||||
|
return new U64(hi, lo);
|
||||||
|
|
||||||
r = a.lo + b.lo;
|
this.hi = hi || 0;
|
||||||
carry = (r - (r % 0x100000000)) / 0x100000000;
|
this.lo = lo || 0;
|
||||||
a.hi = (a.hi + b.hi + carry) & 0xffffffff;
|
|
||||||
a.lo = r & 0xffffffff;
|
|
||||||
|
|
||||||
if (a.hi < 0)
|
|
||||||
a.hi += 0x100000000;
|
|
||||||
|
|
||||||
if (a.lo < 0)
|
|
||||||
a.lo += 0x100000000;
|
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function rotl64(x, b) {
|
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;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
U64.prototype.rotl = function rotl(b) {
|
||||||
var h1, l1, h2, l2, c;
|
var h1, l1, h2, l2, c;
|
||||||
|
|
||||||
// v1 = x << b
|
// v1 = x << b
|
||||||
if (b < 32) {
|
if (b < 32) {
|
||||||
h1 = x.hi << b;
|
h1 = this.hi << b;
|
||||||
c = x.lo >>> (32 - b);
|
c = this.lo >>> (32 - b);
|
||||||
l1 = x.lo << b;
|
l1 = this.lo << b;
|
||||||
h1 |= c;
|
h1 |= c;
|
||||||
} else {
|
} else {
|
||||||
h1 = x.lo << (b - 32);
|
h1 = this.lo << (b - 32);
|
||||||
l1 = 0;
|
l1 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// v2 = x >> (64 - b)
|
// v2 = x >> (64 - b)
|
||||||
b = 64 - b;
|
b = 64 - b;
|
||||||
if (b < 32) {
|
if (b < 32) {
|
||||||
h2 = x.hi >>> b;
|
h2 = this.hi >>> b;
|
||||||
c = x.hi & (0xffffffff >>> (32 - b));
|
c = this.hi & (0xffffffff >>> (32 - b));
|
||||||
l2 = x.lo >>> b;
|
l2 = this.lo >>> b;
|
||||||
l2 |= c << (32 - b);
|
l2 |= c << (32 - b);
|
||||||
} else {
|
} else {
|
||||||
h2 = 0;
|
h2 = 0;
|
||||||
l2 = x.hi >>> (b - 32);
|
l2 = this.hi >>> (b - 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
// v1 | v2
|
// v1 | v2
|
||||||
x.hi = h1 | h2;
|
this.hi = h1 | h2;
|
||||||
x.lo = l1 | l2;
|
this.lo = l1 | l2;
|
||||||
|
|
||||||
if (x.hi < 0)
|
if (this.hi < 0)
|
||||||
x.hi += 0x100000000;
|
this.hi += 0x100000000;
|
||||||
|
|
||||||
if (x.lo < 0)
|
if (this.lo < 0)
|
||||||
x.lo += 0x100000000;
|
this.lo += 0x100000000;
|
||||||
|
|
||||||
return x;
|
return this;
|
||||||
}
|
};
|
||||||
|
|
||||||
function xor64(a, b) {
|
U64.prototype.toRaw = function toRaw() {
|
||||||
a.hi ^= b.hi;
|
var data = new Buffer(8);
|
||||||
a.lo ^= b.lo;
|
data.writeUInt32LE(this.hi, 4, true);
|
||||||
|
data.writeUInt32LE(this.lo, 0, true);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
if (a.hi < 0)
|
U64.fromRaw = function fromRaw(data, off) {
|
||||||
a.hi += 0x100000000;
|
var hi, lo;
|
||||||
|
|
||||||
if (a.lo < 0)
|
if (!off)
|
||||||
a.lo += 0x100000000;
|
off = 0;
|
||||||
|
|
||||||
return a;
|
hi = data.readUInt32LE(off + 4, true);
|
||||||
}
|
lo = data.readUInt32LE(off, true);
|
||||||
|
|
||||||
function read(data, off) {
|
return new U64(hi, lo);
|
||||||
return {
|
};
|
||||||
hi: data.readUInt32LE(off + 4, true),
|
|
||||||
lo: data.readUInt32LE(off, true)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function write(data, value, off) {
|
|
||||||
data.writeUInt32LE(value.hi, off + 4, true);
|
|
||||||
data.writeUInt32LE(value.lo, off, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports = siphash;
|
exports = siphash;
|
||||||
exports.write = write;
|
exports.U64 = U64;
|
||||||
exports.read = read;
|
|
||||||
|
|
||||||
module.exports = exports;
|
module.exports = exports;
|
||||||
|
|||||||
@ -2,41 +2,26 @@
|
|||||||
|
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var siphash = require('../lib/crypto/siphash');
|
var siphash = require('../lib/crypto/siphash');
|
||||||
|
var U64 = siphash.U64;
|
||||||
|
|
||||||
describe('SipHash', function() {
|
describe('SipHash', function() {
|
||||||
it('should perform siphash with no data', function() {
|
it('should perform siphash with no data', function() {
|
||||||
var k0 = new Buffer(8);
|
var k0 = U64(0x07060504, 0x03020100).toRaw();
|
||||||
var k1 = new Buffer(8);
|
var k1 = U64(0x0f0e0d0c, 0x0b0a0908).toRaw();
|
||||||
siphash.write(k0, { hi: 0x07060504, lo: 0x03020100 }, 0);
|
|
||||||
siphash.write(k1, { hi: 0x0F0E0D0C, lo: 0x0B0A0908 }, 0);
|
|
||||||
// be:
|
|
||||||
// assert.equal(siphash(k0, k1, new Buffer(0)).toString('hex'), '726fdb47dd0e0e31');
|
|
||||||
// le:
|
|
||||||
assert.equal(siphash(new Buffer(0), k0, k1).toString('hex'), '310e0edd47db6f72');
|
assert.equal(siphash(new Buffer(0), k0, k1).toString('hex'), '310e0edd47db6f72');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should perform siphash with data', function() {
|
it('should perform siphash with data', function() {
|
||||||
var k0 = new Buffer(8);
|
var k0 = U64(0x07060504, 0x03020100).toRaw();
|
||||||
var k1 = new Buffer(8);
|
var k1 = U64(0x0f0e0d0c, 0x0b0a0908).toRaw();
|
||||||
var data = new Buffer(8);
|
var data = U64(0x07060504, 0x03020100).toRaw();
|
||||||
siphash.write(k0, { hi: 0x07060504, lo: 0x03020100 }, 0);
|
|
||||||
siphash.write(k1, { hi: 0x0F0E0D0C, lo: 0x0B0A0908 }, 0);
|
|
||||||
siphash.write(data, { hi: 0x07060504, lo: 0x03020100 }, 0);
|
|
||||||
// be:
|
|
||||||
// assert.equal(siphash(k0, k1, data).toString('hex'), '93f5f5799a932462');
|
|
||||||
// le:
|
|
||||||
assert.equal(siphash(data, k0, k1).toString('hex'), '6224939a79f5f593');
|
assert.equal(siphash(data, k0, k1).toString('hex'), '6224939a79f5f593');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should perform siphash with uint256', function() {
|
it('should perform siphash with uint256', function() {
|
||||||
var k0 = new Buffer(8);
|
var k0 = U64(0x07060504, 0x03020100).toRaw();
|
||||||
var k1 = new Buffer(8);
|
var k1 = U64(0x0f0e0d0c, 0x0b0a0908).toRaw();
|
||||||
siphash.write(k0, { hi: 0x07060504, lo: 0x03020100 }, 0);
|
|
||||||
siphash.write(k1, { hi: 0x0F0E0D0C, lo: 0x0B0A0908 }, 0);
|
|
||||||
var hash = new Buffer('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', 'hex');
|
var hash = new Buffer('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', 'hex');
|
||||||
// be:
|
|
||||||
// assert.equal(siphash(k0, k1, hash).toString('hex'), '7127512f72f27cce');
|
|
||||||
// le:
|
|
||||||
assert.equal(siphash(hash, k0, k1).toString('hex'), 'ce7cf2722f512771');
|
assert.equal(siphash(hash, k0, k1).toString('hex'), 'ce7cf2722f512771');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user