151 lines
3.3 KiB
JavaScript
151 lines
3.3 KiB
JavaScript
|
/*!
|
||
|
* 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;
|
||
|
};
|