forked from daren.hsu/line_push
427 lines
14 KiB
JavaScript
427 lines
14 KiB
JavaScript
"use strict";
|
|
|
|
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
|
|
|
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.unwrapKey = exports.wrapKey = exports.decrypt = exports.encrypt = void 0;
|
|
|
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
|
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
|
|
var util = _interopRequireWildcard(require("js-crypto-env"));
|
|
|
|
var nodeapi = _interopRequireWildcard(require("./nodeapi.js"));
|
|
|
|
var webapi = _interopRequireWildcard(require("./webapi.js"));
|
|
|
|
var _params = _interopRequireDefault(require("./params.js"));
|
|
|
|
/**
|
|
* aes.js
|
|
*/
|
|
|
|
/**
|
|
* Check if the given algorithm spec is valid.
|
|
* @param {String} name - Name of the specified algorithm like 'AES-GCM'.
|
|
* @param {Uint8Array} iv - IV byte array if required
|
|
* @param {Number} tagLength - Authentication tag length if required
|
|
* @throws {Error} - Throws if UnsupportedAlgorithm, InvalidArguments, InvalidIVLength, or InvalidTagLength.
|
|
*/
|
|
var assertAlgorithms = function assertAlgorithms(_ref) {
|
|
var name = _ref.name,
|
|
iv = _ref.iv,
|
|
tagLength = _ref.tagLength;
|
|
if (Object.keys(_params.default.ciphers).indexOf(name) < 0) throw new Error('UnsupportedAlgorithm');
|
|
|
|
if (_params.default.ciphers[name].ivLength) {
|
|
if (!(iv instanceof Uint8Array)) throw new Error('InvalidArguments');
|
|
if (iv.byteLength < 2 || iv.byteLength > 16) throw new Error('InvalidIVLength');
|
|
if (_params.default.ciphers[name].staticIvLength && _params.default.ciphers[name].ivLength !== iv.byteLength) throw new Error('InvalidIVLength');
|
|
}
|
|
|
|
if (_params.default.ciphers[name].tagLength && tagLength) {
|
|
if (!Number.isInteger(tagLength)) throw new Error('InvalidArguments');
|
|
if (tagLength < 4 || tagLength > 16) throw new Error('InvalidTagLength');
|
|
}
|
|
};
|
|
/**
|
|
* Encrypt data with AES
|
|
* @param {Uint8Array} msg - Message to be encrypted.
|
|
* @param {Uint8Array} key - The symmetric key used to encrypt the message.
|
|
* @param {String} [name = 'AES-GCM'] - Name of the specified algorithm like 'AES-GCM'.
|
|
* @param {Uint8Array} [iv] - Byte array of the initial vector if required.
|
|
* @param {Uint8Array} [additionalData = new Uint8Array([])] - Byte array of additional data if required.
|
|
* @param {Number} [tagLength = params.ciphers[name].tagLength] - Authentication tag length if required.
|
|
* @return {Promise<Uint8Array>} - Encrypted message.
|
|
* @throws {Error} - Throws if InvalidArguments, FaildToEncryptWeb/Node, or UnsupportedEnvironment (no webcrypto/nodecrypto).
|
|
*/
|
|
|
|
|
|
var encrypt =
|
|
/*#__PURE__*/
|
|
function () {
|
|
var _ref3 = (0, _asyncToGenerator2.default)(
|
|
/*#__PURE__*/
|
|
_regenerator.default.mark(function _callee(msg, key, _ref2) {
|
|
var _ref2$name, name, iv, _ref2$additionalData, additionalData, tagLength, webCrypto, nodeCrypto;
|
|
|
|
return _regenerator.default.wrap(function _callee$(_context) {
|
|
while (1) {
|
|
switch (_context.prev = _context.next) {
|
|
case 0:
|
|
_ref2$name = _ref2.name, name = _ref2$name === void 0 ? 'AES-GCM' : _ref2$name, iv = _ref2.iv, _ref2$additionalData = _ref2.additionalData, additionalData = _ref2$additionalData === void 0 ? new Uint8Array([]) : _ref2$additionalData, tagLength = _ref2.tagLength;
|
|
|
|
if (!(!(msg instanceof Uint8Array) || !(key instanceof Uint8Array))) {
|
|
_context.next = 3;
|
|
break;
|
|
}
|
|
|
|
throw new Error('InvalidArguments');
|
|
|
|
case 3:
|
|
assertAlgorithms({
|
|
name: name,
|
|
iv: iv,
|
|
tagLength: tagLength
|
|
});
|
|
if (_params.default.ciphers[name].tagLength && !tagLength) tagLength = _params.default.ciphers[name].tagLength;
|
|
_context.next = 7;
|
|
return util.getWebCryptoAll();
|
|
|
|
case 7:
|
|
webCrypto = _context.sent;
|
|
_context.next = 10;
|
|
return util.getNodeCrypto();
|
|
|
|
case 10:
|
|
nodeCrypto = _context.sent;
|
|
|
|
if (!(typeof webCrypto !== 'undefined' && typeof webCrypto.importKey === 'function' && typeof webCrypto.encrypt === 'function')) {
|
|
_context.next = 15;
|
|
break;
|
|
}
|
|
|
|
return _context.abrupt("return", webapi.encrypt(msg, key, {
|
|
name: name,
|
|
iv: iv,
|
|
additionalData: additionalData,
|
|
tagLength: tagLength
|
|
}, webCrypto));
|
|
|
|
case 15:
|
|
if (!(typeof nodeCrypto !== 'undefined')) {
|
|
_context.next = 19;
|
|
break;
|
|
}
|
|
|
|
return _context.abrupt("return", nodeapi.encrypt(msg, key, {
|
|
name: name,
|
|
iv: iv,
|
|
additionalData: additionalData,
|
|
tagLength: tagLength
|
|
}, nodeCrypto));
|
|
|
|
case 19:
|
|
throw new Error('UnsupportedEnvironment');
|
|
|
|
case 20:
|
|
case "end":
|
|
return _context.stop();
|
|
}
|
|
}
|
|
}, _callee);
|
|
}));
|
|
|
|
return function encrypt(_x, _x2, _x3) {
|
|
return _ref3.apply(this, arguments);
|
|
};
|
|
}();
|
|
/**
|
|
* Decrypt data with AES
|
|
* @param {Uint8Array} data - Byte array of encrypted data.
|
|
* @param {Uint8Array} key - Byte array of symmetric key to be used for decryption.
|
|
* @param {String} [name = 'AES-GCM'] - Name of the specified algorithm like 'AES-GCM'.
|
|
* @param {Uint8Array} [iv] - Byte array of the initial vector if required.
|
|
* @param {Uint8Array} [additionalData = new Uint8Array([])] - Byte array of additional data if required.
|
|
* @param {Number} [tagLength = params.ciphers[name].tagLength] - Authentication tag length if required.
|
|
* @return {Promise<Uint8Array>} - Decrypted plaintext message.
|
|
* @throws {Error} - Throws if InvalidArguments, FailedToDecryptWeb/Node, or UnsupportedEnvironment (no webcrypto/nodecrypto).
|
|
*/
|
|
|
|
|
|
exports.encrypt = encrypt;
|
|
|
|
var decrypt =
|
|
/*#__PURE__*/
|
|
function () {
|
|
var _ref5 = (0, _asyncToGenerator2.default)(
|
|
/*#__PURE__*/
|
|
_regenerator.default.mark(function _callee2(data, key, _ref4) {
|
|
var _ref4$name, name, iv, _ref4$additionalData, additionalData, tagLength, webCrypto, nodeCrypto;
|
|
|
|
return _regenerator.default.wrap(function _callee2$(_context2) {
|
|
while (1) {
|
|
switch (_context2.prev = _context2.next) {
|
|
case 0:
|
|
_ref4$name = _ref4.name, name = _ref4$name === void 0 ? 'AES-GCM' : _ref4$name, iv = _ref4.iv, _ref4$additionalData = _ref4.additionalData, additionalData = _ref4$additionalData === void 0 ? new Uint8Array([]) : _ref4$additionalData, tagLength = _ref4.tagLength;
|
|
|
|
if (!(!(data instanceof Uint8Array) || !(key instanceof Uint8Array))) {
|
|
_context2.next = 3;
|
|
break;
|
|
}
|
|
|
|
throw new Error('InvalidArguments');
|
|
|
|
case 3:
|
|
assertAlgorithms({
|
|
name: name,
|
|
iv: iv,
|
|
tagLength: tagLength
|
|
});
|
|
if (_params.default.ciphers[name].tagLength && !tagLength) tagLength = _params.default.ciphers[name].tagLength;
|
|
_context2.next = 7;
|
|
return util.getWebCryptoAll();
|
|
|
|
case 7:
|
|
webCrypto = _context2.sent;
|
|
_context2.next = 10;
|
|
return util.getNodeCrypto();
|
|
|
|
case 10:
|
|
nodeCrypto = _context2.sent;
|
|
|
|
if (!(typeof webCrypto !== 'undefined' && typeof webCrypto.importKey === 'function' && typeof webCrypto.encrypt === 'function')) {
|
|
_context2.next = 15;
|
|
break;
|
|
}
|
|
|
|
return _context2.abrupt("return", webapi.decrypt(data, key, {
|
|
name: name,
|
|
iv: iv,
|
|
additionalData: additionalData,
|
|
tagLength: tagLength
|
|
}, webCrypto));
|
|
|
|
case 15:
|
|
if (!(typeof nodeCrypto !== 'undefined')) {
|
|
_context2.next = 19;
|
|
break;
|
|
}
|
|
|
|
return _context2.abrupt("return", nodeapi.decrypt(data, key, {
|
|
name: name,
|
|
iv: iv,
|
|
additionalData: additionalData,
|
|
tagLength: tagLength
|
|
}, nodeCrypto));
|
|
|
|
case 19:
|
|
throw new Error('UnsupportedEnvironment');
|
|
|
|
case 20:
|
|
case "end":
|
|
return _context2.stop();
|
|
}
|
|
}
|
|
}, _callee2);
|
|
}));
|
|
|
|
return function decrypt(_x4, _x5, _x6) {
|
|
return _ref5.apply(this, arguments);
|
|
};
|
|
}();
|
|
/**
|
|
* AES-KW wrapping
|
|
* @param keyToBeWrapped {Uint8Array} - key bytes to be wrapped
|
|
* @param wrappingKey {Uint8Array} - wrapping key encryption key
|
|
* @param name {'AES-KW'} - this is simply for future extension
|
|
* @return {Promise<Uint8Array>} - output wrapped key
|
|
*/
|
|
|
|
|
|
exports.decrypt = decrypt;
|
|
|
|
var wrapKey =
|
|
/*#__PURE__*/
|
|
function () {
|
|
var _ref7 = (0, _asyncToGenerator2.default)(
|
|
/*#__PURE__*/
|
|
_regenerator.default.mark(function _callee3(keyToBeWrapped, wrappingKey, _ref6) {
|
|
var _ref6$name, name, webCrypto, nodeCrypto, iv;
|
|
|
|
return _regenerator.default.wrap(function _callee3$(_context3) {
|
|
while (1) {
|
|
switch (_context3.prev = _context3.next) {
|
|
case 0:
|
|
_ref6$name = _ref6.name, name = _ref6$name === void 0 ? 'AES-KW' : _ref6$name;
|
|
|
|
if (keyToBeWrapped instanceof Uint8Array) {
|
|
_context3.next = 3;
|
|
break;
|
|
}
|
|
|
|
throw new Error('NonUint8ArrayData');
|
|
|
|
case 3:
|
|
if (wrappingKey instanceof Uint8Array) {
|
|
_context3.next = 5;
|
|
break;
|
|
}
|
|
|
|
throw new Error('NonUint8ArrayKey');
|
|
|
|
case 5:
|
|
if (!(keyToBeWrapped.length % 8 > 0)) {
|
|
_context3.next = 7;
|
|
break;
|
|
}
|
|
|
|
throw new Error('WrappedKeyMustBeMultipleOf8');
|
|
|
|
case 7:
|
|
_context3.next = 9;
|
|
return util.getWebCryptoAll();
|
|
|
|
case 9:
|
|
webCrypto = _context3.sent;
|
|
_context3.next = 12;
|
|
return util.getNodeCrypto();
|
|
|
|
case 12:
|
|
nodeCrypto = _context3.sent;
|
|
// node crypto
|
|
iv = _params.default.wrapKeys['AES-KW'].defaultIV;
|
|
|
|
if (!(typeof webCrypto !== 'undefined' && typeof webCrypto.importKey === 'function' && typeof webCrypto.wrapKey === 'function')) {
|
|
_context3.next = 18;
|
|
break;
|
|
}
|
|
|
|
return _context3.abrupt("return", webapi.wrapKey(keyToBeWrapped, wrappingKey, {
|
|
name: name,
|
|
iv: iv
|
|
}, webCrypto));
|
|
|
|
case 18:
|
|
if (!(typeof nodeCrypto !== 'undefined')) {
|
|
_context3.next = 22;
|
|
break;
|
|
}
|
|
|
|
return _context3.abrupt("return", nodeapi.wrapKey(keyToBeWrapped, wrappingKey, {
|
|
name: name,
|
|
iv: iv
|
|
}, nodeCrypto));
|
|
|
|
case 22:
|
|
throw new Error('UnsupportedEnvironment');
|
|
|
|
case 23:
|
|
case "end":
|
|
return _context3.stop();
|
|
}
|
|
}
|
|
}, _callee3);
|
|
}));
|
|
|
|
return function wrapKey(_x7, _x8, _x9) {
|
|
return _ref7.apply(this, arguments);
|
|
};
|
|
}();
|
|
/**
|
|
* AES-KW unwrapping
|
|
* @param wrappedKey {Uint8Array} - wrapped key bytes
|
|
* @param wrappingKey {Uint8Array} - wrapping key encryption key
|
|
* @param name {'AES-KW'} - this is simply for future extension
|
|
* @return {Promise<Uint8Array>} - output unwrapped key
|
|
*/
|
|
|
|
|
|
exports.wrapKey = wrapKey;
|
|
|
|
var unwrapKey =
|
|
/*#__PURE__*/
|
|
function () {
|
|
var _ref9 = (0, _asyncToGenerator2.default)(
|
|
/*#__PURE__*/
|
|
_regenerator.default.mark(function _callee4(wrappedKey, wrappingKey, _ref8) {
|
|
var _ref8$name, name, webCrypto, nodeCrypto, iv;
|
|
|
|
return _regenerator.default.wrap(function _callee4$(_context4) {
|
|
while (1) {
|
|
switch (_context4.prev = _context4.next) {
|
|
case 0:
|
|
_ref8$name = _ref8.name, name = _ref8$name === void 0 ? 'AES-KW' : _ref8$name;
|
|
|
|
if (wrappedKey instanceof Uint8Array) {
|
|
_context4.next = 3;
|
|
break;
|
|
}
|
|
|
|
throw new Error('NonUint8ArrayData');
|
|
|
|
case 3:
|
|
if (wrappingKey instanceof Uint8Array) {
|
|
_context4.next = 5;
|
|
break;
|
|
}
|
|
|
|
throw new Error('NonUint8ArrayKey');
|
|
|
|
case 5:
|
|
_context4.next = 7;
|
|
return util.getWebCryptoAll();
|
|
|
|
case 7:
|
|
webCrypto = _context4.sent;
|
|
_context4.next = 10;
|
|
return util.getNodeCrypto();
|
|
|
|
case 10:
|
|
nodeCrypto = _context4.sent;
|
|
// node crypto
|
|
iv = _params.default.wrapKeys['AES-KW'].defaultIV;
|
|
|
|
if (!(typeof webCrypto !== 'undefined' && typeof webCrypto.importKey === 'function' && typeof webCrypto.wrapKey === 'function')) {
|
|
_context4.next = 16;
|
|
break;
|
|
}
|
|
|
|
return _context4.abrupt("return", webapi.unwrapKey(wrappedKey, wrappingKey, {
|
|
name: name,
|
|
iv: iv
|
|
}, webCrypto));
|
|
|
|
case 16:
|
|
if (!(typeof nodeCrypto !== 'undefined')) {
|
|
_context4.next = 20;
|
|
break;
|
|
}
|
|
|
|
return _context4.abrupt("return", nodeapi.unwrapKey(wrappedKey, wrappingKey, {
|
|
name: name,
|
|
iv: iv
|
|
}, nodeCrypto));
|
|
|
|
case 20:
|
|
throw new Error('UnsupportedEnvironment');
|
|
|
|
case 21:
|
|
case "end":
|
|
return _context4.stop();
|
|
}
|
|
}
|
|
}, _callee4);
|
|
}));
|
|
|
|
return function unwrapKey(_x10, _x11, _x12) {
|
|
return _ref9.apply(this, arguments);
|
|
};
|
|
}();
|
|
|
|
exports.unwrapKey = unwrapKey; |