/*! * algorithms/helpers.js - Internal functions and fields used in Cryptographic * Algorithms * * Copyright (c) 2015 Cisco Systems, Inc. See LICENSE file. */ "use strict"; if (typeof Promise === "undefined") { require("es6-promise").polyfill(); } // ### exports.int32ToBuffer = function(v, b) { b = b || Buffer.alloc(4); b[0] = (v >>> 24) & 0xff; b[1] = (v >>> 16) & 0xff; b[2] = (v >>> 8) & 0xff; b[3] = v & 0xff; return b; }; var MAX_INT32 = Math.pow(2, 32); exports.int64ToBuffer = function(v, b) { b = b || Buffer.alloc(8); var hi = Math.floor(v / MAX_INT32), lo = v % MAX_INT32; hi = exports.int32ToBuffer(hi); lo = exports.int32ToBuffer(lo); b = Buffer.concat([hi, lo]); return b; }; // ### crypto and DOMException in browsers ### /* global crypto:false, DOMException:false */ function getCryptoSubtle() { if ("undefined" !== typeof crypto) { if ("undefined" !== typeof crypto.subtle) { return crypto.subtle; } } return undefined; } function getCryptoNodeJS() { var crypto; try { crypto = require("crypto"); } catch (err) { return undefined; } if (!Object.keys(crypto).length) { // treat empty the same as missing return undefined; } return crypto; } var supported = {}; Object.defineProperty(exports, "subtleCrypto", { get: function() { var result; if ("subtleCrypto" in supported) { result = supported.subtleCrypto; } else { result = supported.subtleCrypto = getCryptoSubtle(); } return result; }, enumerable: true }); Object.defineProperty(exports, "nodeCrypto", { get: function() { var result; if ("nodeCrypto" in supported) { result = supported.nodeCrypto; } else { result = supported.nodeCrypto = getCryptoNodeJS(); } return result; }, enumerable: true }); exports.setupFallback = function(nodejs, webcrypto, fallback) { var impl; if (nodejs && exports.nodeCrypto) { impl = function main() { var args = arguments, promise; function check(err) { if (0 === err.message.indexOf("unsupported algorithm:")) { impl = fallback; return impl.apply(null, args); } return Promise.reject(err); } try { promise = Promise.resolve(nodejs.apply(null, args)); } catch(err) { promise = check(err); } return promise; }; } else if (webcrypto && exports.subtleCrypto) { impl = function main() { var args = arguments, promise; function check(err) { if (err.code === DOMException.NOT_SUPPORTED_ERR || // Firefox rejects some operations erroneously complaining about inputs err.message === "Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData" || // MS Edge rejects with not an Error !(err instanceof Error)) { // not actually supported -- always use fallback impl = fallback; return impl.apply(null, args); } return Promise.reject(err); } try { promise = webcrypto.apply(null, args); promise = promise.catch(check); } catch(err) { promise = check(err); } return promise; }; } else { impl = fallback; } return impl; };