Skip to content

Commit

Permalink
siphash: fix siphash length commitment. add more variations. see #1.
Browse files Browse the repository at this point in the history
  • Loading branch information
chjj committed Dec 31, 2017
1 parent 7c3c3c7 commit 2b03bab
Show file tree
Hide file tree
Showing 8 changed files with 533 additions and 154 deletions.
5 changes: 4 additions & 1 deletion lib/bcrypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,12 @@ exports.SHA256 = require('./sha256');
exports.SHA3 = require('./sha3');
exports.SHA512 = require('./sha512');
exports.siphash = siphash.siphash;
exports.siphash256 = siphash.siphash256;
exports.siphash256 = siphash.siphash256; // compat
exports.siphash32 = siphash.siphash32;
exports.siphash64 = siphash.siphash64;
exports.siphash32k256 = siphash.siphash32k256;
exports.siphash64k256 = siphash.siphash64k256;
exports.sipmod = siphash.sipmod;

exports.get = digest.get;
exports.hash = digest.hash;
Expand Down
206 changes: 181 additions & 25 deletions lib/js/siphash.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
/*!
* siphash.js - siphash for bcoin
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
* Copyright (c) 2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*
* Ported from:
* https://github.com/bitcoin/bitcoin/blob/master/src/hash.cpp
*/

'use strict';

const assert = require('assert');

/*
* Constants
*/

const HI = 1 / 0x100000000;

/**
* Javascript siphash 2-4 implementation.
* @private
* @param {Buffer} data
* @param {Buffer} key - 128 bit key.
* @param {Number} shift
* @returns {Array} [hi, lo]
*/

function _siphash(data, key, shift) {
const blocks = Math.floor(data.length / 8);
function _siphash(data, key) {
assert(Buffer.isBuffer(data));
assert(Buffer.isBuffer(key) && key.length >= 16);

const blocks = data.length >>> 3;
const c0 = new U64(0x736f6d65, 0x70736575);
const c1 = new U64(0x646f7261, 0x6e646f6d);
const c2 = new U64(0x6c796765, 0x6e657261);
const c3 = new U64(0x74656462, 0x79746573);
const f0 = new U64(blocks << (shift - 32), 0);
const f0 = new U64(data.length << 24, 0);
const f1 = new U64(0, 0xff);
const k0 = U64.fromRaw(key, 0);
const k1 = U64.fromRaw(key, 8);
Expand Down Expand Up @@ -63,9 +70,6 @@ function _siphash(data, key, shift) {
f0.lo |= data[p];
}

f0.hi &= -1 >>> 8;
f0.hi |= data.length << 24;

// Finalization
v3.ixor(f0);
sipround(v0, v1, v2, v3);
Expand Down Expand Up @@ -93,6 +97,10 @@ function _siphash(data, key, shift) {
*/

function _siphash64(hi, lo, key) {
assert(typeof hi === 'number');
assert(typeof lo === 'number');
assert(Buffer.isBuffer(key) && key.length >= 16);

const c0 = new U64(0x736f6d65, 0x70736575);
const c1 = new U64(0x646f7261, 0x6e646f6d);
const c2 = new U64(0x6c796765, 0x6e657261);
Expand Down Expand Up @@ -126,32 +134,65 @@ function _siphash64(hi, lo, key) {
}

/**
* Javascript siphash 2-4 implementation (shift=56).
* @alias module:crypto/siphash.siphash
* @param {Buffer} data
* Javascript siphash 2-4 implementation
* (64 bit ints with a 256 bit key).
* @private
* @param {Number} hi
* @param {Number} lo
* @param {Buffer} key - 128 bit key.
* @returns {Array} [hi, lo]
*/

function siphash(data, key) {
return _siphash(data, key, 56);
function _siphash64k256(hi, lo, key) {
assert(typeof hi === 'number');
assert(typeof lo === 'number');
assert(Buffer.isBuffer(key) && key.length >= 32);

const f0 = new U64(hi, lo);
const f1 = new U64(0, 0xff);
const k0 = U64.fromRaw(key, 0);
const k1 = U64.fromRaw(key, 8);
const k2 = U64.fromRaw(key, 16);
const k3 = U64.fromRaw(key, 24);

// Init
const v0 = k0;
const v1 = k1;
const v2 = k2;
const v3 = k3;

// Finalization
v3.ixor(f0);
sipround(v0, v1, v2, v3);
sipround(v0, v1, v2, v3);
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.ixor(v1);
v0.ixor(v2);
v0.ixor(v3);

return [v0.hi, v0.lo];
}

/**
* Javascript siphash 2-4 implementation (shift=59).
* @alias module:crypto/siphash.siphash256
* Javascript siphash 2-4 implementation.
* Used by bitcoin for compact block relay.
* @param {Buffer} data
* @param {Buffer} key - 128 bit key.
* @returns {Array} [hi, lo]
*/

function siphash256(data, key) {
return _siphash(data, key, 59);
function siphash(data, key) {
return _siphash(data, key);
}

/**
* Javascript siphash 2-4 implementation (32 bit ints).
* @alias module:crypto/siphash.siphash32
* Used by legacy cuckoo cycle.
* @param {Number} num
* @param {Buffer} key - 128 bit key.
* @returns {Number}
Expand All @@ -163,7 +204,7 @@ function siphash32(num, key) {

/**
* Javascript siphash 2-4 implementation (64 bit ints).
* @alias module:crypto/siphash.siphash64
* Used by legacy cuckoo cycle.
* @param {Number} hi
* @param {Number} lo
* @param {Buffer} key - 128 bit key.
Expand All @@ -174,9 +215,51 @@ function siphash64(hi, lo, key) {
return _siphash64(hi, lo, key);
}

/*
/**
* Javascript siphash 2-4 implementation
* (32 bit ints with a 256 bit key).
* Used by cuckoo cycle.
* @param {Number} num
* @param {Buffer} key - 256 bit key.
* @returns {Number}
*/

function siphash32k256(num, key) {
return _siphash64k256(0, num, key)[1];
}

/**
* Javascript siphash 2-4 implementation
* (64 bit ints with a 256 bit key).
* Used by cuckoo cycle.
* @param {Number} hi
* @param {Number} lo
* @param {Buffer} key - 256 bit key.
* @returns {Array} [hi, lo]
*/

function siphash64k256(hi, lo, key) {
return _siphash64k256(hi, lo, key);
}

/**
* Javascript siphash 2-4 implementation
* plus 128 bit reduction by a modulus.
* Used by the neutrino protocol.
* @param {Buffer} data
* @param {Buffer} key - 128 bit key.
* @param {Number} mhi - Modulus hi bits.
* @param {Number} mlo - Modulus lo bits.
* @returns {Array} [hi, lo]
*/

function sipmod(data, key, mhi, mlo) {
const [hi, lo] = _siphash(data, key);
return reduce64(hi, lo, mhi, mlo);
}

/**
* U64
* @constructor
* @ignore
*/

Expand Down Expand Up @@ -280,11 +363,84 @@ function sipround(v0, v1, v2, v3) {
v2.irotl(32);
}

// Compute `((uint128_t)a * b) >> 64`
function reduce64(ahi, alo, bhi, blo) {
const axbhi = mul64(ahi, bhi);
const axbmid = mul64(ahi, blo);
const bxamid = mul64(bhi, alo);
const axblo = mul64(alo, blo);

// Hack:
const c = (axbmid.lo >>> 0) + (bxamid.lo >>> 0) + (axblo.hi >>> 0);
const m = (axbmid.hi >>> 0) + (bxamid.hi >>> 0) + ((c * HI) >>> 0);

// More hacks:
const mhi = (m * HI) | 0;
const mlo = m | 0;

const {hi, lo} = sum64(axbhi.hi, axbhi.lo, mhi, mlo);

return [hi, lo];
}

function sum64(ahi, alo, bhi, blo) {
// Credit to @indutny for this method.
const lo = (alo + blo) | 0;

const s = lo >> 31;
const as = alo >> 31;
const bs = blo >> 31;

const c = ((as & bs) | (~s & (as ^ bs))) & 1;

const hi = (((ahi + bhi) | 0) + c) | 0;

return { hi, lo };
}

function mul64(alo, blo) {
const a16 = alo >>> 16;
const a00 = alo & 0xffff;

const b16 = blo >>> 16;
const b00 = blo & 0xffff;

let c48 = 0;
let c32 = 0;
let c16 = 0;
let c00 = 0;

c00 += a00 * b00;
c16 += c00 >>> 16;
c00 &= 0xffff;
c16 += a16 * b00;
c32 += c16 >>> 16;
c16 &= 0xffff;
c16 += a00 * b16;
c32 += c16 >>> 16;
c16 &= 0xffff;
c48 += c32 >>> 16;
c32 &= 0xffff;
c32 += a16 * b16;
c48 += c32 >>> 16;
c32 &= 0xffff;
c48 += c32 >>> 16;
c48 &= 0xffff;

const hi = (c48 << 16) | c32;
const lo = (c16 << 16) | c00;

return { hi, lo };
}

/*
* Expose
*/

exports.siphash = siphash;
exports.siphash256 = siphash256;
exports.siphash256 = siphash; // compat
exports.siphash32 = siphash32;
exports.siphash64 = siphash64;
exports.siphash32k256 = siphash32k256;
exports.siphash64k256 = siphash64k256;
exports.sipmod = sipmod;
5 changes: 4 additions & 1 deletion lib/native/siphash.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
const binding = require('./binding');

exports.siphash = binding.siphash;
exports.siphash256 = binding.siphash256;
exports.siphash256 = binding.siphash256; // compat
exports.siphash32 = binding.siphash32;
exports.siphash64 = binding.siphash64;
exports.siphash32k256 = binding.siphash32k256;
exports.siphash64k256 = binding.siphash64k256;
exports.sipmod = binding.sipmod;
Loading

0 comments on commit 2b03bab

Please sign in to comment.