UNPKG

node-jose

Version:

A JavaScript implementation of the JSON Object Signing and Encryption (JOSE) for current web browsers and node.js-based servers

259 lines (239 loc) 5.88 kB
/*! * deps/ciphermodes/gcm/helpers.js - AES-GCM Helper Functions * * Copyright (c) 2015 Cisco Systems, Inc. See LICENSE file. */ "use strict"; var Long = require("long"), fill = require("lodash").fill, pack = require("../pack.js"); var E1 = 0xe1000000, E1B = 0xe1, E1L = new Long(E1 >> 8); function generateLookup() { var lookup = []; for (var c = 0; c < 256; ++c) { var v = 0; for (var i = 7; i >= 0; --i) { if ((c & (1 << i)) !== 0) { v ^= (E1 >>> (7 - i)); } } lookup.push(v); } return lookup; } var helpers = module.exports = { // ### Constants E1: E1, E1B: E1B, E1L: E1L, LOOKUP: generateLookup(), // ### Array Helpers arrayCopy: function(src, srcPos, dest, destPos, length) { // Start by checking for negatives since arrays in JS auto-expand if (srcPos < 0 || destPos < 0 || length < 0) { throw new TypeError("Invalid input."); } if (dest instanceof Uint8Array) { // Check for overflow if dest is a typed-array if (destPos >= dest.length || (destPos + length) > dest.length) { throw new TypeError("Invalid input."); } if (srcPos !== 0 || length < src.length) { if (src instanceof Uint8Array) { src = src.subarray(srcPos, srcPos + length); } else { src = src.slice(srcPos, srcPos + length); } } dest.set(src, destPos); } else { for (var i = 0; i < length; ++i) { dest[destPos + i] = src[srcPos + i]; } } }, arrayEqual: function(a1, a2) { a1 = a1 || []; a2 = a2 || []; var len = Math.min(a1.length, a2.length), result = (a1.length === a2.length); for (var idx = 0; idx < len; idx++) { result = result && ("undefined" !== typeof a1[idx]) && ("undefined" !== typeof a2[idx]) && (a1[idx] === a2[idx]); } return result; }, // ### Conversions asBytes: function(x, z) { switch (arguments.length) { case 1: z = Buffer.alloc(16); pack.intToBigEndian(x, z, 0); return z; case 2: pack.intToBigEndian(x, z, 0); break; default: throw new TypeError("Expected 1 or 2 arguments."); } }, asInts: function(x, z) { switch (arguments.length) { case 1: z = []; fill(z, 0, 0, 4); pack.bigEndianToInt(x, 0, z); return z; case 2: pack.bigEndianToInt(x, 0, z); break; default: throw new TypeError("Expected 1 or 2 arguments."); } }, oneAsInts: function() { var tmp = []; for (var c = 0; c < 4; ++c) { tmp.push(1 << 31); } return tmp; }, // ## Bit-wise shiftRight: function(x, z) { var b, c; switch (arguments.length) { case 1: b = x[0]; x[0] = b >>> 1; c = b << 31; b = x[1]; x[1] = (b >>> 1) | c; c = b << 31; b = x[2]; x[2] = (b >>> 1) | c; c = b << 31; b = x[3]; x[3] = (b >>> 1) | c; return (b << 31) & 0xffffffff; case 2: b = x[0]; z[0] = b >>> 1; c = b << 31; b = x[1]; z[1] = (b >>> 1) | c; c = b << 31; b = x[2]; z[2] = (b >>> 1) | c; c = b << 31; b = x[3]; z[3] = (b >>> 1) | c; return (b << 31) & 0xffffffff; default: throw new TypeError("Expected 1 or 2 arguments."); } }, shiftRightN: function(x, n, z) { var nInv, b, c; switch (arguments.length) { case 2: b = x[0]; nInv = 32 - n; x[0] = b >>> n; c = b << nInv; b = x[1]; x[1] = (b >>> n) | c; c = b << nInv; b = x[2]; x[2] = (b >>> n) | c; c = b << nInv; b = x[3]; x[3] = (b >>> n) | c; return b << nInv; case 3: b = x[0]; nInv = 32 - n; z[0] = b >>> n; c = b << nInv; b = x[1]; z[1] = (b >>> n) | c; c = b << nInv; b = x[2]; z[2] = (b >>> n) | c; c = b << nInv; b = x[3]; z[3] = (b >>> n) | c; return b << nInv; default: throw new TypeError("Expected 2 or 3 arguments."); } }, xor: function(x, y, z) { switch (arguments.length) { case 2: x[0] ^= y[0]; x[1] ^= y[1]; x[2] ^= y[2]; x[3] ^= y[3]; break; case 3: z[0] = x[0] ^ y[0]; z[1] = x[1] ^ y[1]; z[2] = x[2] ^ y[2]; z[3] = x[3] ^ y[3]; break; default: throw new TypeError("Expected 2 or 3 arguments."); } }, multiply: function(x, y) { var r0 = x.slice(); var r1 = []; for (var i = 0; i < 4; ++i) { var bits = y[i]; for (var j = 31; j >= 0; --j) { if ((bits & (1 << j)) !== 0) { helpers.xor(r1, r0); } if (helpers.shiftRight(r0) !== 0) { r0[0] ^= helpers.E1; } } } helpers.arrayCopy(r1, 0, x, 0, 4); }, multiplyP: function(x, y) { switch (arguments.length) { case 1: if (helpers.shiftRight(x) !== 0) { x[0] ^= helpers.E1; } break; case 2: if (helpers.shiftRight(x, y) !== 0) { y[0] ^= helpers.E1; } break; default: throw new TypeError("Expected 1 or 2 arguments."); } }, multiplyP8: function(x, y) { var c; switch (arguments.length) { case 1: c = helpers.shiftRightN(x, 8); x[0] ^= helpers.LOOKUP[c >>> 24]; break; case 2: c = helpers.shiftRightN(x, 8, y); y[0] ^= helpers.LOOKUP[c >>> 24]; break; default: throw new TypeError("Expected 1 or 2 arguments."); } } };