UNPKG

xsalsa20

Version:

XSalsa20 implemented in Javascript and WebAssembly

456 lines (389 loc) 13 kB
var xsalsa20 = typeof WebAssembly !== "undefined" && require('./xsalsa20')() var SIGMA = new Uint8Array([101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107]) var head = 144 var top = head var free = [] module.exports = XSalsa20 XSalsa20.NONCEBYTES = 24 XSalsa20.KEYBYTES = 32 XSalsa20.core_hsalsa20 = core_hsalsa20 XSalsa20.SIGMA = SIGMA function XSalsa20 (nonce, key) { if (!(this instanceof XSalsa20)) return new XSalsa20(nonce, key) if (!nonce || nonce.length < 24) throw new Error('nonce must be at least 24 bytes') if (!key || key.length < 32) throw new Error('key must be at least 32 bytes') this._xor = xsalsa20 ? new WASM(nonce, key) : new Fallback(nonce, key) } XSalsa20.prototype.update = function (input, output) { if (!input) throw new Error('input must be Uint8Array or Buffer') if (!output) output = new Uint8Array(input.length) if (input.length) this._xor.update(input, output) return output } XSalsa20.prototype.final = XSalsa20.prototype.finalize = function () { this._xor.finalize() this._xor = null } function WASM (nonce, key) { if (!free.length) { free.push(head) head += 64 } this._pointer = free.pop() this._nonce = this._pointer + 8 this._key = this._nonce + 24 this._overflow = 0 this._memory = new Uint8Array(xsalsa20.memory.buffer) this._memory.fill(0, this._pointer, this._pointer + 8) this._memory.set(nonce, this._nonce) this._memory.set(key, this._key) } WASM.prototype.realloc = function (size) { xsalsa20.memory.grow(Math.ceil(Math.abs(size - this._memory.length) / 65536)) this._memory = new Uint8Array(xsalsa20.memory.buffer) } WASM.prototype.update = function (input, output) { var len = this._overflow + input.length var start = head + this._overflow top = head + len if (top >= this._memory.length) this.realloc(top) this._memory.set(input, start) xsalsa20.xsalsa20_xor(this._pointer, head, head, len, this._nonce, this._key) output.set(this._memory.subarray(start, head + len)) this._overflow = len & 63 } WASM.prototype.finalize = function () { this._memory.fill(0, this._pointer, this._key + 32) if (top > head) { this._memory.fill(0, head, top) top = 0 } free.push(this._pointer) } function Fallback (nonce, key) { this._s = new Uint8Array(32) this._z = new Uint8Array(16) this._overflow = 0 core_hsalsa20(this._s, nonce, key, SIGMA) for (var i = 0; i < 8; i++) this._z[i] = nonce[i + 16] } Fallback.prototype.update = function (input, output) { var x = new Uint8Array(64) var u = 0 var i = this._overflow var b = input.length + this._overflow var z = this._z var mpos = -this._overflow var cpos = -this._overflow while (b >= 64) { core_salsa20(x, z, this._s, SIGMA) for (; i < 64; i++) output[cpos + i] = input[mpos + i] ^ x[i] u = 1 for (i = 8; i < 16; i++) { u += (z[i] & 0xff) | 0 z[i] = u & 0xff u >>>= 8 } b -= 64 cpos += 64 mpos += 64 i = 0 } if (b > 0) { core_salsa20(x, z, this._s, SIGMA) for (; i < b; i++) output[cpos + i] = input[mpos + i] ^ x[i] } this._overflow = b & 63 } Fallback.prototype.finalize = function () { this._s.fill(0) this._z.fill(0) } // below methods are ported from tweet nacl function core_salsa20(o, p, k, c) { var j0 = c[ 0] & 0xff | (c[ 1] & 0xff) << 8 | (c[ 2] & 0xff) << 16 | (c[ 3] & 0xff) << 24, j1 = k[ 0] & 0xff | (k[ 1] & 0xff) << 8 | (k[ 2] & 0xff) << 16 | (k[ 3] & 0xff) << 24, j2 = k[ 4] & 0xff | (k[ 5] & 0xff) << 8 | (k[ 6] & 0xff) << 16 | (k[ 7] & 0xff) << 24, j3 = k[ 8] & 0xff | (k[ 9] & 0xff) << 8 | (k[10] & 0xff) << 16 | (k[11] & 0xff) << 24, j4 = k[12] & 0xff | (k[13] & 0xff) << 8 | (k[14] & 0xff) << 16 | (k[15] & 0xff) << 24, j5 = c[ 4] & 0xff | (c[ 5] & 0xff) << 8 | (c[ 6] & 0xff) << 16 | (c[ 7] & 0xff) << 24, j6 = p[ 0] & 0xff | (p[ 1] & 0xff) << 8 | (p[ 2] & 0xff) << 16 | (p[ 3] & 0xff) << 24, j7 = p[ 4] & 0xff | (p[ 5] & 0xff) << 8 | (p[ 6] & 0xff) << 16 | (p[ 7] & 0xff) << 24, j8 = p[ 8] & 0xff | (p[ 9] & 0xff) << 8 | (p[10] & 0xff) << 16 | (p[11] & 0xff) << 24, j9 = p[12] & 0xff | (p[13] & 0xff) << 8 | (p[14] & 0xff) << 16 | (p[15] & 0xff) << 24, j10 = c[ 8] & 0xff | (c[ 9] & 0xff) << 8 | (c[10] & 0xff) << 16 | (c[11] & 0xff) << 24, j11 = k[16] & 0xff | (k[17] & 0xff) << 8 | (k[18] & 0xff) << 16 | (k[19] & 0xff) << 24, j12 = k[20] & 0xff | (k[21] & 0xff) << 8 | (k[22] & 0xff) << 16 | (k[23] & 0xff) << 24, j13 = k[24] & 0xff | (k[25] & 0xff) << 8 | (k[26] & 0xff) << 16 | (k[27] & 0xff) << 24, j14 = k[28] & 0xff | (k[29] & 0xff) << 8 | (k[30] & 0xff) << 16 | (k[31] & 0xff) << 24, j15 = c[12] & 0xff | (c[13] & 0xff) << 8 | (c[14] & 0xff) << 16 | (c[15] & 0xff) << 24 var x0 = j0, x1 = j1, x2 = j2, x3 = j3, x4 = j4, x5 = j5, x6 = j6, x7 = j7, x8 = j8, x9 = j9, x10 = j10, x11 = j11, x12 = j12, x13 = j13, x14 = j14, x15 = j15, u for (var i = 0; i < 20; i += 2) { u = x0 + x12 | 0 x4 ^= u << 7 | u >>> 25 u = x4 + x0 | 0 x8 ^= u << 9 | u >>> 23 u = x8 + x4 | 0 x12 ^= u << 13 | u >>> 19 u = x12 + x8 | 0 x0 ^= u << 18 | u >>> 14 u = x5 + x1 | 0 x9 ^= u << 7 | u >>> 25 u = x9 + x5 | 0 x13 ^= u << 9 | u >>> 23 u = x13 + x9 | 0 x1 ^= u << 13 | u >>> 19 u = x1 + x13 | 0 x5 ^= u << 18 | u >>> 14 u = x10 + x6 | 0 x14 ^= u << 7 | u >>> 25 u = x14 + x10 | 0 x2 ^= u << 9 | u >>> 23 u = x2 + x14 | 0 x6 ^= u << 13 | u >>> 19 u = x6 + x2 | 0 x10 ^= u << 18 | u >>> 14 u = x15 + x11 | 0 x3 ^= u << 7 | u >>> 25 u = x3 + x15 | 0 x7 ^= u << 9 | u >>> 23 u = x7 + x3 | 0 x11 ^= u << 13 | u >>> 19 u = x11 + x7 | 0 x15 ^= u << 18 | u >>> 14 u = x0 + x3 | 0 x1 ^= u << 7 | u >>> 25 u = x1 + x0 | 0 x2 ^= u << 9 | u >>> 23 u = x2 + x1 | 0 x3 ^= u << 13 | u >>> 19 u = x3 + x2 | 0 x0 ^= u << 18 | u >>> 14 u = x5 + x4 | 0 x6 ^= u << 7 | u >>> 25 u = x6 + x5 | 0 x7 ^= u << 9 | u >>> 23 u = x7 + x6 | 0 x4 ^= u << 13 | u >>> 19 u = x4 + x7 | 0 x5 ^= u << 18 | u >>> 14 u = x10 + x9 | 0 x11 ^= u << 7 | u >>> 25 u = x11 + x10 | 0 x8 ^= u << 9 | u >>> 23 u = x8 + x11 | 0 x9 ^= u << 13 | u >>> 19 u = x9 + x8 | 0 x10 ^= u << 18 | u >>> 14 u = x15 + x14 | 0 x12 ^= u << 7 | u >>> 25 u = x12 + x15 | 0 x13 ^= u << 9 | u >>> 23 u = x13 + x12 | 0 x14 ^= u << 13 | u >>> 19 u = x14 + x13 | 0 x15 ^= u << 18 | u >>> 14 } x0 = x0 + j0 | 0 x1 = x1 + j1 | 0 x2 = x2 + j2 | 0 x3 = x3 + j3 | 0 x4 = x4 + j4 | 0 x5 = x5 + j5 | 0 x6 = x6 + j6 | 0 x7 = x7 + j7 | 0 x8 = x8 + j8 | 0 x9 = x9 + j9 | 0 x10 = x10 + j10 | 0 x11 = x11 + j11 | 0 x12 = x12 + j12 | 0 x13 = x13 + j13 | 0 x14 = x14 + j14 | 0 x15 = x15 + j15 | 0 o[ 0] = x0 >>> 0 & 0xff o[ 1] = x0 >>> 8 & 0xff o[ 2] = x0 >>> 16 & 0xff o[ 3] = x0 >>> 24 & 0xff o[ 4] = x1 >>> 0 & 0xff o[ 5] = x1 >>> 8 & 0xff o[ 6] = x1 >>> 16 & 0xff o[ 7] = x1 >>> 24 & 0xff o[ 8] = x2 >>> 0 & 0xff o[ 9] = x2 >>> 8 & 0xff o[10] = x2 >>> 16 & 0xff o[11] = x2 >>> 24 & 0xff o[12] = x3 >>> 0 & 0xff o[13] = x3 >>> 8 & 0xff o[14] = x3 >>> 16 & 0xff o[15] = x3 >>> 24 & 0xff o[16] = x4 >>> 0 & 0xff o[17] = x4 >>> 8 & 0xff o[18] = x4 >>> 16 & 0xff o[19] = x4 >>> 24 & 0xff o[20] = x5 >>> 0 & 0xff o[21] = x5 >>> 8 & 0xff o[22] = x5 >>> 16 & 0xff o[23] = x5 >>> 24 & 0xff o[24] = x6 >>> 0 & 0xff o[25] = x6 >>> 8 & 0xff o[26] = x6 >>> 16 & 0xff o[27] = x6 >>> 24 & 0xff o[28] = x7 >>> 0 & 0xff o[29] = x7 >>> 8 & 0xff o[30] = x7 >>> 16 & 0xff o[31] = x7 >>> 24 & 0xff o[32] = x8 >>> 0 & 0xff o[33] = x8 >>> 8 & 0xff o[34] = x8 >>> 16 & 0xff o[35] = x8 >>> 24 & 0xff o[36] = x9 >>> 0 & 0xff o[37] = x9 >>> 8 & 0xff o[38] = x9 >>> 16 & 0xff o[39] = x9 >>> 24 & 0xff o[40] = x10 >>> 0 & 0xff o[41] = x10 >>> 8 & 0xff o[42] = x10 >>> 16 & 0xff o[43] = x10 >>> 24 & 0xff o[44] = x11 >>> 0 & 0xff o[45] = x11 >>> 8 & 0xff o[46] = x11 >>> 16 & 0xff o[47] = x11 >>> 24 & 0xff o[48] = x12 >>> 0 & 0xff o[49] = x12 >>> 8 & 0xff o[50] = x12 >>> 16 & 0xff o[51] = x12 >>> 24 & 0xff o[52] = x13 >>> 0 & 0xff o[53] = x13 >>> 8 & 0xff o[54] = x13 >>> 16 & 0xff o[55] = x13 >>> 24 & 0xff o[56] = x14 >>> 0 & 0xff o[57] = x14 >>> 8 & 0xff o[58] = x14 >>> 16 & 0xff o[59] = x14 >>> 24 & 0xff o[60] = x15 >>> 0 & 0xff o[61] = x15 >>> 8 & 0xff o[62] = x15 >>> 16 & 0xff o[63] = x15 >>> 24 & 0xff } function core_hsalsa20(o,p,k,c) { var j0 = c[ 0] & 0xff | (c[ 1] & 0xff) << 8 | (c[ 2] & 0xff) << 16 | (c[ 3] & 0xff) << 24, j1 = k[ 0] & 0xff | (k[ 1] & 0xff) << 8 | (k[ 2] & 0xff) << 16 | (k[ 3] & 0xff) << 24, j2 = k[ 4] & 0xff | (k[ 5] & 0xff) << 8 | (k[ 6] & 0xff) << 16 | (k[ 7] & 0xff) << 24, j3 = k[ 8] & 0xff | (k[ 9] & 0xff) << 8 | (k[10] & 0xff) << 16 | (k[11] & 0xff) << 24, j4 = k[12] & 0xff | (k[13] & 0xff) << 8 | (k[14] & 0xff) << 16 | (k[15] & 0xff) << 24, j5 = c[ 4] & 0xff | (c[ 5] & 0xff) << 8 | (c[ 6] & 0xff) << 16 | (c[ 7] & 0xff) << 24, j6 = p[ 0] & 0xff | (p[ 1] & 0xff) << 8 | (p[ 2] & 0xff) << 16 | (p[ 3] & 0xff) << 24, j7 = p[ 4] & 0xff | (p[ 5] & 0xff) << 8 | (p[ 6] & 0xff) << 16 | (p[ 7] & 0xff) << 24, j8 = p[ 8] & 0xff | (p[ 9] & 0xff) << 8 | (p[10] & 0xff) << 16 | (p[11] & 0xff) << 24, j9 = p[12] & 0xff | (p[13] & 0xff) << 8 | (p[14] & 0xff) << 16 | (p[15] & 0xff) << 24, j10 = c[ 8] & 0xff | (c[ 9] & 0xff) << 8 | (c[10] & 0xff) << 16 | (c[11] & 0xff) << 24, j11 = k[16] & 0xff | (k[17] & 0xff) << 8 | (k[18] & 0xff) << 16 | (k[19] & 0xff) << 24, j12 = k[20] & 0xff | (k[21] & 0xff) << 8 | (k[22] & 0xff) << 16 | (k[23] & 0xff) << 24, j13 = k[24] & 0xff | (k[25] & 0xff) << 8 | (k[26] & 0xff) << 16 | (k[27] & 0xff) << 24, j14 = k[28] & 0xff | (k[29] & 0xff) << 8 | (k[30] & 0xff) << 16 | (k[31] & 0xff) << 24, j15 = c[12] & 0xff | (c[13] & 0xff) << 8 | (c[14] & 0xff) << 16 | (c[15] & 0xff) << 24 var x0 = j0, x1 = j1, x2 = j2, x3 = j3, x4 = j4, x5 = j5, x6 = j6, x7 = j7, x8 = j8, x9 = j9, x10 = j10, x11 = j11, x12 = j12, x13 = j13, x14 = j14, x15 = j15, u for (var i = 0; i < 20; i += 2) { u = x0 + x12 | 0 x4 ^= u << 7 | u >>> 25 u = x4 + x0 | 0 x8 ^= u << 9 | u >>> 23 u = x8 + x4 | 0 x12 ^= u << 13 | u >>> 19 u = x12 + x8 | 0 x0 ^= u << 18 | u >>> 14 u = x5 + x1 | 0 x9 ^= u << 7 | u >>> 25 u = x9 + x5 | 0 x13 ^= u << 9 | u >>> 23 u = x13 + x9 | 0 x1 ^= u << 13 | u >>> 19 u = x1 + x13 | 0 x5 ^= u << 18 | u >>> 14 u = x10 + x6 | 0 x14 ^= u << 7 | u >>> 25 u = x14 + x10 | 0 x2 ^= u << 9 | u >>> 23 u = x2 + x14 | 0 x6 ^= u << 13 | u >>> 19 u = x6 + x2 | 0 x10 ^= u << 18 | u >>> 14 u = x15 + x11 | 0 x3 ^= u << 7 | u >>> 25 u = x3 + x15 | 0 x7 ^= u << 9 | u >>> 23 u = x7 + x3 | 0 x11 ^= u << 13 | u >>> 19 u = x11 + x7 | 0 x15 ^= u << 18 | u >>> 14 u = x0 + x3 | 0 x1 ^= u << 7 | u >>> 25 u = x1 + x0 | 0 x2 ^= u << 9 | u >>> 23 u = x2 + x1 | 0 x3 ^= u << 13 | u >>> 19 u = x3 + x2 | 0 x0 ^= u << 18 | u >>> 14 u = x5 + x4 | 0 x6 ^= u << 7 | u >>> 25 u = x6 + x5 | 0 x7 ^= u << 9 | u >>> 23 u = x7 + x6 | 0 x4 ^= u << 13 | u >>> 19 u = x4 + x7 | 0 x5 ^= u << 18 | u >>> 14 u = x10 + x9 | 0 x11 ^= u << 7 | u >>> 25 u = x11 + x10 | 0 x8 ^= u << 9 | u >>> 23 u = x8 + x11 | 0 x9 ^= u << 13 | u >>> 19 u = x9 + x8 | 0 x10 ^= u << 18 | u >>> 14 u = x15 + x14 | 0 x12 ^= u << 7 | u >>> 25 u = x12 + x15 | 0 x13 ^= u << 9 | u >>> 23 u = x13 + x12 | 0 x14 ^= u << 13 | u >>> 19 u = x14 + x13 | 0 x15 ^= u << 18 | u >>> 14 } o[ 0] = x0 >>> 0 & 0xff o[ 1] = x0 >>> 8 & 0xff o[ 2] = x0 >>> 16 & 0xff o[ 3] = x0 >>> 24 & 0xff o[ 4] = x5 >>> 0 & 0xff o[ 5] = x5 >>> 8 & 0xff o[ 6] = x5 >>> 16 & 0xff o[ 7] = x5 >>> 24 & 0xff o[ 8] = x10 >>> 0 & 0xff o[ 9] = x10 >>> 8 & 0xff o[10] = x10 >>> 16 & 0xff o[11] = x10 >>> 24 & 0xff o[12] = x15 >>> 0 & 0xff o[13] = x15 >>> 8 & 0xff o[14] = x15 >>> 16 & 0xff o[15] = x15 >>> 24 & 0xff o[16] = x6 >>> 0 & 0xff o[17] = x6 >>> 8 & 0xff o[18] = x6 >>> 16 & 0xff o[19] = x6 >>> 24 & 0xff o[20] = x7 >>> 0 & 0xff o[21] = x7 >>> 8 & 0xff o[22] = x7 >>> 16 & 0xff o[23] = x7 >>> 24 & 0xff o[24] = x8 >>> 0 & 0xff o[25] = x8 >>> 8 & 0xff o[26] = x8 >>> 16 & 0xff o[27] = x8 >>> 24 & 0xff o[28] = x9 >>> 0 & 0xff o[29] = x9 >>> 8 & 0xff o[30] = x9 >>> 16 & 0xff o[31] = x9 >>> 24 & 0xff }