diff --git a/crypto_shorthash.js b/crypto_shorthash.js index 6699605..5563f89 100644 --- a/crypto_shorthash.js +++ b/crypto_shorthash.js @@ -1,169 +1,17 @@ -var fs = require('fs') -var toUint8Array = require('base64-to-uint8array') -var assert = require('nanoassert') +var siphash = require('siphash24') -var WASM = toUint8Array(fs.readFileSync(__dirname + '/wasm/siphash.wasm', 'base64')) -var mod -var mem -var rdy - -var BYTES = exports.crypto_shorthash_BYTES = 8 -var KEYBYTES = exports.crypto_shorthash_KEYBYTES = 16 exports.crypto_shorthash_PRIMITIVE = 'siphash24' -exports.crypto_shorthash_WASM_SUPPORTED = typeof WebAssembly !== 'undefined' -exports.crypto_shorthash_WASM_LOADED = false -exports.crypto_shorthash_ready = ready +exports.crypto_shorthash_BYTES = siphash.BYTES +exports.crypto_shorthash_KEYBYTES = siphash.KEYBYTES +exports.crypto_shorthash_WASM_SUPPORTED = siphash.WASM_SUPPORTED +exports.crypto_shorthash_WASM_LOADED = siphash.WASM_LOADED +exports.crypto_shorthash_ready = siphash.ready exports.crypto_shorthash = shorthash -ready(function (err) { - if (!err) exports.crypto_shorthash_WASM_LOADED = true +siphash.ready(function () { + exports.crypto_shorthash_WASM_LOADED = siphash.WASM_LOADED }) -function ready (cb) { - if (!cb) cb = noop - if (!exports.crypto_shorthash_WASM_SUPPORTED) return cb(new Error('WebAssembly not supported')) - if (!rdy) rdy = WebAssembly.instantiate(WASM).then(setup) - return rdy.then(cb).catch(cb) -} - function shorthash (out, data, key, noAssert) { - if (noAssert !== true) { - assert(out.length >= BYTES, 'output must be at least crypto_shorthash_BYTES') - assert(key.length >= KEYBYTES, 'output must be at least crypto_shorthash_KEYBYTES') - } - - if (mod) { - mem.set(key, 8) - mem.set(data, 24) - mod.siphash(24, data.length) - out.set(mem.subarray(0, 8)) - } else { - fallback(out, data, key) - } -} - -function noop () {} - -function setup (w) { - mod = w.instance.exports - mem = new Uint8Array(w.instance.exports.siphash_memory.buffer) -} - -function _add(a, b) { - var rl = a.l + b.l - var a2 = { - h: a.h + b.h + (rl / 2 >>> 31) >>> 0, - l: rl >>> 0 - } - a.h = a2.h - a.l = a2.l -} - -function _xor(a, b) { - a.h ^= b.h - a.h >>>= 0 - a.l ^= b.l - a.l >>>= 0 -} - -function _rotl(a, n) { - var a2 = { - h: a.h << n | a.l >>> (32 - n), - l: a.l << n | a.h >>> (32 - n) - } - a.h = a2.h - a.l = a2.l -} - -function _rotl32(a) { - var al = a.l - a.l = a.h - a.h = al -} - -function _compress(v0, v1, v2, v3) { - _add(v0, v1) - _add(v2, v3) - _rotl(v1, 13) - _rotl(v3, 16) - _xor(v1, v0) - _xor(v3, v2) - _rotl32(v0) - _add(v2, v1) - _add(v0, v3) - _rotl(v1, 17) - _rotl(v3, 21) - _xor(v1, v2) - _xor(v3, v0) - _rotl32(v2) -} - -function _get_int(a, offset) { - return (a[offset + 3] << 24) | (a[offset + 2] << 16) | (a[offset + 1] << 8) | a[offset] -} - -function fallback (out, m, key) { // modified from https://github.com/jedisct1/siphash-js to use uint8arrays - var k0 = {h: _get_int(key, 4), l: _get_int(key, 0)} - var k1 = {h: _get_int(key, 12), l: _get_int(key, 8)} - var v0 = {h: k0.h, l: k0.l} - var v2 = k0 - var v1 = {h: k1.h, l: k1.l} - var v3 = k1 - var mi - var mp = 0 - var ml = m.length - var ml7 = ml - 7 - var buf = new Uint8Array(new ArrayBuffer(8)) - - _xor(v0, {h: 0x736f6d65, l: 0x70736575}) - _xor(v1, {h: 0x646f7261, l: 0x6e646f6d}) - _xor(v2, {h: 0x6c796765, l: 0x6e657261}) - _xor(v3, {h: 0x74656462, l: 0x79746573}) - - while (mp < ml7) { - mi = {h: _get_int(m, mp + 4), l: _get_int(m, mp)} - _xor(v3, mi) - _compress(v0, v1, v2, v3) - _compress(v0, v1, v2, v3) - _xor(v0, mi) - mp += 8 - } - - buf[7] = ml - var ic = 0 - while (mp < ml) { - buf[ic++] = m[mp++] - } - while (ic < 7) { - buf[ic++] = 0 - } - - mi = { - h: buf[7] << 24 | buf[6] << 16 | buf[5] << 8 | buf[4], - l: buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0] - } - - _xor(v3, mi) - _compress(v0, v1, v2, v3) - _compress(v0, v1, v2, v3) - _xor(v0, mi) - _xor(v2, { h: 0, l: 0xff }) - _compress(v0, v1, v2, v3) - _compress(v0, v1, v2, v3) - _compress(v0, v1, v2, v3) - _compress(v0, v1, v2, v3) - - var h = v0 - _xor(h, v1) - _xor(h, v2) - _xor(h, v3) - - out[0] = h.l & 0xff - out[1] = (h.l >> 8) & 0xff - out[2] = (h.l >> 16) & 0xff - out[3] = (h.l >> 24) & 0xff - out[4] = h.h & 0xff - out[5] = (h.h >> 8) & 0xff - out[6] = (h.h >> 16) & 0xff - out[7] = (h.h >> 24) & 0xff + siphash(data, key, out, noAssert) } diff --git a/package.json b/package.json index 35781c6..da65c6d 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,9 @@ "description": "WIP - a pure javascript version of sodium-native", "main": "index.js", "dependencies": { - "base64-to-uint8array": "^1.0.0", "blake2b": "^2.1.1", - "brfs": "^1.4.3", - "nanoassert": "^1.0.0" + "nanoassert": "^1.0.0", + "siphash24": "^1.0.1" }, "devDependencies": { "sodium-test": "^0.4.0" diff --git a/wasm/siphash.wasm b/wasm/siphash.wasm deleted file mode 100644 index c1c0cde..0000000 Binary files a/wasm/siphash.wasm and /dev/null differ diff --git a/wasm/siphash.wat b/wasm/siphash.wat deleted file mode 100644 index fb9b322..0000000 --- a/wasm/siphash.wat +++ /dev/null @@ -1,348 +0,0 @@ -(module - (memory (export "siphash_memory") 10 10) - - (func (export "siphash") (param $ptr i32) (param $ptr_len i32) - (local $v0 i64) - (local $v1 i64) - (local $v2 i64) - (local $v3 i64) - (local $b i64) - (local $k0 i64) - (local $k1 i64) - (local $m i64) - (local $end i32) - (local $left i32) - - (set_local $v0 (i64.const 0x736f6d6570736575)) - (set_local $v1 (i64.const 0x646f72616e646f6d)) - (set_local $v2 (i64.const 0x6c7967656e657261)) - (set_local $v3 (i64.const 0x7465646279746573)) - - (set_local $k0 (i64.load (i32.const 8))) - (set_local $k1 (i64.load (i32.const 16))) - - ;; b = ((uint64_t) inlen) << 56; - (set_local $b (i64.shl (i64.extend_u/i32 (get_local $ptr_len)) (i64.const 56))) - - ;; left = inlen & 7; - (set_local $left (i32.and (get_local $ptr_len) (i32.const 7))) - - ;; end = in + inlen - left; - (set_local $end (i32.sub (i32.add (get_local $ptr) (get_local $ptr_len)) (get_local $left))) - - ;; v3 ^= k1; - (set_local $v3 (i64.xor (get_local $v3) (get_local $k1))) - - ;; v2 ^= k0; - (set_local $v2 (i64.xor (get_local $v2) (get_local $k0))) - - ;; v1 ^= k1; - (set_local $v1 (i64.xor (get_local $v1) (get_local $k1))) - - ;; v0 ^= k0; - (set_local $v0 (i64.xor (get_local $v0) (get_local $k0))) - - (block $end_loop - (loop $start_loop - (br_if $end_loop (i32.eq (get_local $ptr) (get_local $end))) - - ;; m = LOAD64_LE(in); - (set_local $m (i64.load (get_local $ptr))) - - ;; v3 ^= m - (set_local $v3 (i64.xor (get_local $v3) (get_local $m))) - - ;; SIPROUND - ;; v0 += v1; - (set_local $v0 (i64.add (get_local $v0) (get_local $v1))) - ;; v1 = ROTL64(v1, 13); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 13))) - ;; v1 ^= v0; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v0))) - ;; v0 = ROTL64(v0, 32) - (set_local $v0 (i64.rotl (get_local $v0) (i64.const 32))) - ;; v2 += v3; - (set_local $v2 (i64.add (get_local $v2) (get_local $v3))) - ;; v3 = ROTL64(v3, 16); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 16))) - ;; v3 ^= v2; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v2))) - ;; v0 += v3; - (set_local $v0 (i64.add (get_local $v0) (get_local $v3))) - ;; v3 = ROTL64(v3, 21); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 21))) - ;; v3 ^= v0; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v0))) - ;; v2 += v1; - (set_local $v2 (i64.add (get_local $v2) (get_local $v1))) - ;; v1 = ROTL64(v1, 17); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 17))) - ;; v1 ^= v2; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v2))) - ;; v2 = ROTL64(v2, 32); - (set_local $v2 (i64.rotl (get_local $v2) (i64.const 32))) - - ;; SIPROUND - ;; v0 += v1; - (set_local $v0 (i64.add (get_local $v0) (get_local $v1))) - ;; v1 = ROTL64(v1, 13); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 13))) - ;; v1 ^= v0; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v0))) - ;; v0 = ROTL64(v0, 32) - (set_local $v0 (i64.rotl (get_local $v0) (i64.const 32))) - ;; v2 += v3; - (set_local $v2 (i64.add (get_local $v2) (get_local $v3))) - ;; v3 = ROTL64(v3, 16); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 16))) - ;; v3 ^= v2; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v2))) - ;; v0 += v3; - (set_local $v0 (i64.add (get_local $v0) (get_local $v3))) - ;; v3 = ROTL64(v3, 21); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 21))) - ;; v3 ^= v0; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v0))) - ;; v2 += v1; - (set_local $v2 (i64.add (get_local $v2) (get_local $v1))) - ;; v1 = ROTL64(v1, 17); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 17))) - ;; v1 ^= v2; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v2))) - ;; v2 = ROTL64(v2, 32); - (set_local $v2 (i64.rotl (get_local $v2) (i64.const 32))) - - ;; v0 ^= m; - (set_local $v0 (i64.xor (get_local $v0) (get_local $m))) - - ;; ptr += 8 - (set_local $ptr (i32.add (get_local $ptr) (i32.const 8))) - (br $start_loop) - ) - ) - - (block $0 - (block $1 - (block $2 - (block $3 - (block $4 - (block $5 - (block $6 - (block $7 - (br_table $0 $1 $2 $3 $4 $5 $6 $7 (get_local $left)) - ) - ;; b |= ((uint64_t) in[6]) << 48; - (set_local $b (i64.or (get_local $b) (i64.shl (i64.load8_u (i32.add (get_local $ptr) (i32.const 6))) (i64.const 48)))) - ) - ;; b |= ((uint64_t) in[5]) << 40; - (set_local $b (i64.or (get_local $b) (i64.shl (i64.load8_u (i32.add (get_local $ptr) (i32.const 5))) (i64.const 40)))) - ) - ;; b |= ((uint64_t) in[4]) << 32; - (set_local $b (i64.or (get_local $b) (i64.shl (i64.load8_u (i32.add (get_local $ptr) (i32.const 4))) (i64.const 32)))) - ) - ;; b |= ((uint64_t) in[3]) << 24; - (set_local $b (i64.or (get_local $b) (i64.shl (i64.load8_u (i32.add (get_local $ptr) (i32.const 3))) (i64.const 24)))) - ) - ;; b |= ((uint64_t) in[2]) << 16; - (set_local $b (i64.or (get_local $b) (i64.shl (i64.load8_u (i32.add (get_local $ptr) (i32.const 2))) (i64.const 16)))) - ) - ;; b |= ((uint64_t) in[1]) << 8; - (set_local $b (i64.or (get_local $b) (i64.shl (i64.load8_u (i32.add (get_local $ptr) (i32.const 1))) (i64.const 8)))) - ) - ;; b |= ((uint64_t) in[0]); - (set_local $b (i64.or (get_local $b) (i64.load8_u (get_local $ptr)))) - ) - - ;; v3 ^= b; - (set_local $v3 (i64.xor (get_local $v3) (get_local $b))) - - ;; SIPROUND - ;; v0 += v1; - (set_local $v0 (i64.add (get_local $v0) (get_local $v1))) - ;; v1 = ROTL64(v1, 13); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 13))) - ;; v1 ^= v0; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v0))) - ;; v0 = ROTL64(v0, 32) - (set_local $v0 (i64.rotl (get_local $v0) (i64.const 32))) - ;; v2 += v3; - (set_local $v2 (i64.add (get_local $v2) (get_local $v3))) - ;; v3 = ROTL64(v3, 16); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 16))) - ;; v3 ^= v2; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v2))) - ;; v0 += v3; - (set_local $v0 (i64.add (get_local $v0) (get_local $v3))) - ;; v3 = ROTL64(v3, 21); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 21))) - ;; v3 ^= v0; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v0))) - ;; v2 += v1; - (set_local $v2 (i64.add (get_local $v2) (get_local $v1))) - ;; v1 = ROTL64(v1, 17); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 17))) - ;; v1 ^= v2; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v2))) - ;; v2 = ROTL64(v2, 32); - (set_local $v2 (i64.rotl (get_local $v2) (i64.const 32))) - - ;; SIPROUND - ;; v0 += v1; - (set_local $v0 (i64.add (get_local $v0) (get_local $v1))) - ;; v1 = ROTL64(v1, 13); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 13))) - ;; v1 ^= v0; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v0))) - ;; v0 = ROTL64(v0, 32) - (set_local $v0 (i64.rotl (get_local $v0) (i64.const 32))) - ;; v2 += v3; - (set_local $v2 (i64.add (get_local $v2) (get_local $v3))) - ;; v3 = ROTL64(v3, 16); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 16))) - ;; v3 ^= v2; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v2))) - ;; v0 += v3; - (set_local $v0 (i64.add (get_local $v0) (get_local $v3))) - ;; v3 = ROTL64(v3, 21); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 21))) - ;; v3 ^= v0; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v0))) - ;; v2 += v1; - (set_local $v2 (i64.add (get_local $v2) (get_local $v1))) - ;; v1 = ROTL64(v1, 17); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 17))) - ;; v1 ^= v2; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v2))) - ;; v2 = ROTL64(v2, 32); - (set_local $v2 (i64.rotl (get_local $v2) (i64.const 32))) - - ;; v0 ^= b; - (set_local $v0 (i64.xor (get_local $v0) (get_local $b))) - - ;; v2 ^= 0xff; - (set_local $v2 (i64.xor (get_local $v2) (i64.const 0xff))) - - ;; SIPROUND - ;; v0 += v1; - (set_local $v0 (i64.add (get_local $v0) (get_local $v1))) - ;; v1 = ROTL64(v1, 13); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 13))) - ;; v1 ^= v0; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v0))) - ;; v0 = ROTL64(v0, 32) - (set_local $v0 (i64.rotl (get_local $v0) (i64.const 32))) - ;; v2 += v3; - (set_local $v2 (i64.add (get_local $v2) (get_local $v3))) - ;; v3 = ROTL64(v3, 16); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 16))) - ;; v3 ^= v2; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v2))) - ;; v0 += v3; - (set_local $v0 (i64.add (get_local $v0) (get_local $v3))) - ;; v3 = ROTL64(v3, 21); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 21))) - ;; v3 ^= v0; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v0))) - ;; v2 += v1; - (set_local $v2 (i64.add (get_local $v2) (get_local $v1))) - ;; v1 = ROTL64(v1, 17); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 17))) - ;; v1 ^= v2; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v2))) - ;; v2 = ROTL64(v2, 32); - (set_local $v2 (i64.rotl (get_local $v2) (i64.const 32))) - - ;; SIPROUND - ;; v0 += v1; - (set_local $v0 (i64.add (get_local $v0) (get_local $v1))) - ;; v1 = ROTL64(v1, 13); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 13))) - ;; v1 ^= v0; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v0))) - ;; v0 = ROTL64(v0, 32) - (set_local $v0 (i64.rotl (get_local $v0) (i64.const 32))) - ;; v2 += v3; - (set_local $v2 (i64.add (get_local $v2) (get_local $v3))) - ;; v3 = ROTL64(v3, 16); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 16))) - ;; v3 ^= v2; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v2))) - ;; v0 += v3; - (set_local $v0 (i64.add (get_local $v0) (get_local $v3))) - ;; v3 = ROTL64(v3, 21); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 21))) - ;; v3 ^= v0; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v0))) - ;; v2 += v1; - (set_local $v2 (i64.add (get_local $v2) (get_local $v1))) - ;; v1 = ROTL64(v1, 17); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 17))) - ;; v1 ^= v2; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v2))) - ;; v2 = ROTL64(v2, 32); - (set_local $v2 (i64.rotl (get_local $v2) (i64.const 32))) - - ;; SIPROUND - ;; v0 += v1; - (set_local $v0 (i64.add (get_local $v0) (get_local $v1))) - ;; v1 = ROTL64(v1, 13); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 13))) - ;; v1 ^= v0; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v0))) - ;; v0 = ROTL64(v0, 32) - (set_local $v0 (i64.rotl (get_local $v0) (i64.const 32))) - ;; v2 += v3; - (set_local $v2 (i64.add (get_local $v2) (get_local $v3))) - ;; v3 = ROTL64(v3, 16); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 16))) - ;; v3 ^= v2; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v2))) - ;; v0 += v3; - (set_local $v0 (i64.add (get_local $v0) (get_local $v3))) - ;; v3 = ROTL64(v3, 21); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 21))) - ;; v3 ^= v0; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v0))) - ;; v2 += v1; - (set_local $v2 (i64.add (get_local $v2) (get_local $v1))) - ;; v1 = ROTL64(v1, 17); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 17))) - ;; v1 ^= v2; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v2))) - ;; v2 = ROTL64(v2, 32); - (set_local $v2 (i64.rotl (get_local $v2) (i64.const 32))) - - ;; SIPROUND - ;; v0 += v1; - (set_local $v0 (i64.add (get_local $v0) (get_local $v1))) - ;; v1 = ROTL64(v1, 13); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 13))) - ;; v1 ^= v0; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v0))) - ;; v0 = ROTL64(v0, 32) - (set_local $v0 (i64.rotl (get_local $v0) (i64.const 32))) - ;; v2 += v3; - (set_local $v2 (i64.add (get_local $v2) (get_local $v3))) - ;; v3 = ROTL64(v3, 16); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 16))) - ;; v3 ^= v2; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v2))) - ;; v0 += v3; - (set_local $v0 (i64.add (get_local $v0) (get_local $v3))) - ;; v3 = ROTL64(v3, 21); - (set_local $v3 (i64.rotl (get_local $v3) (i64.const 21))) - ;; v3 ^= v0; - (set_local $v3 (i64.xor (get_local $v3) (get_local $v0))) - ;; v2 += v1; - (set_local $v2 (i64.add (get_local $v2) (get_local $v1))) - ;; v1 = ROTL64(v1, 17); - (set_local $v1 (i64.rotl (get_local $v1) (i64.const 17))) - ;; v1 ^= v2; - (set_local $v1 (i64.xor (get_local $v1) (get_local $v2))) - ;; v2 = ROTL64(v2, 32); - (set_local $v2 (i64.rotl (get_local $v2) (i64.const 32))) - - ;; b = v0 ^ v1 ^ v2 ^ v3; - (i64.store (i32.const 0) (i64.xor (get_local $v0) (i64.xor (get_local $v1) (i64.xor (get_local $v2) (get_local $v3))))) - ) -)