This commit is contained in:
2022-07-21 03:28:35 +00:00
parent d7c883d6df
commit 51b34b0e1d
30103 changed files with 4152204 additions and 23 deletions
+427
View File
@@ -0,0 +1,427 @@
"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;
+43
View File
@@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "encrypt", {
enumerable: true,
get: function get() {
return _aes.encrypt;
}
});
Object.defineProperty(exports, "decrypt", {
enumerable: true,
get: function get() {
return _aes.decrypt;
}
});
Object.defineProperty(exports, "wrapKey", {
enumerable: true,
get: function get() {
return _aes.wrapKey;
}
});
Object.defineProperty(exports, "unwrapKey", {
enumerable: true,
get: function get() {
return _aes.unwrapKey;
}
});
exports.default = void 0;
var _aes = require("./aes.js");
/**
* index.js
*/
var _default = {
encrypt: _aes.encrypt,
decrypt: _aes.decrypt,
wrapKey: _aes.wrapKey,
unwrapKey: _aes.unwrapKey
};
exports.default = _default;
File diff suppressed because one or more lines are too long
+219
View File
@@ -0,0 +1,219 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.decrypt = exports.encrypt = exports.unwrapKey = exports.wrapKey = void 0;
var _params = _interopRequireDefault(require("./params.js"));
/**
* nodeapi.js
*/
/**
* Node.js KeyWrapping function simply uses encrypt function.
* @param keyToBeWrapped {Uint8Array} - plaintext key
* @param wrappingKey {Uint8Array} - wrapping key
* @param name {string} - 'AES-KW'
* @param iv {Uint8Array} - default is '0xA6A6A6A6A6A6A6A6'
* @param nodeCrypto {Object} - NodeCrypto object
* @return {Uint8Array} - Unwrapped Key
*/
var wrapKey = function wrapKey(keyToBeWrapped, wrappingKey, _ref, nodeCrypto) {
var _ref$name = _ref.name,
name = _ref$name === void 0 ? 'AES-KW' : _ref$name,
iv = _ref.iv;
return encrypt(keyToBeWrapped, wrappingKey, {
name: name,
iv: iv
}, nodeCrypto, true);
};
/**
* Node.js KeyUnwrapping function as well as keyWrapping
* @param wrappedKey {Uint8Array} - Wrapped key
* @param unwrappingKey {Uint8Array} - Key used for wrapping
* @param name {string} - 'AES-KW'
* @param iv {Uint8Array} - default is '0xA6A6A6A6A6A6A6A6'
* @param nodeCrypto {Object} - NodeCrypto object
* @return {Uint8Array} - Unwrapped Key
*/
exports.wrapKey = wrapKey;
var unwrapKey = function unwrapKey(wrappedKey, unwrappingKey, _ref2, nodeCrypto) {
var _ref2$name = _ref2.name,
name = _ref2$name === void 0 ? 'AES-KW' : _ref2$name,
iv = _ref2.iv;
return decrypt(wrappedKey, unwrappingKey, {
name: name,
iv: iv
}, nodeCrypto, true);
};
/**
* Encrypt plaintext message via AES Node.js crypto API
* @param {Uint8Array} msg - Plaintext message to be encrypted.
* @param {Uint8Array} key - Byte array of symmetric key.
* @param {String} name - Name of AES algorithm like 'AES-GCM'.
* @param {Uint8Array} [iv] - Byte array of initial vector if required.
* @param {Uint8Array} [additionalData] - Byte array of additional data if required.
* @param {Number} [tagLength] - Authentication tag length if required.
* @param {Object} nodeCrypto - NodeCrypto object, i.e., require(crypto) in Node.js.
* @param wrapKey {Boolean} [false] - true if called as AES-KW
* @return {Uint8Array} - Encrypted message byte array.
* @throws {Error} - Throws error if UnsupportedCipher.
*/
exports.unwrapKey = unwrapKey;
var encrypt = function encrypt(msg, key, _ref3, nodeCrypto) {
var name = _ref3.name,
iv = _ref3.iv,
additionalData = _ref3.additionalData,
tagLength = _ref3.tagLength;
var wrapKey = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
var alg = getNodeName(name, key.byteLength, wrapKey ? _params.default.wrapKeys : _params.default.ciphers);
var cipher;
switch (name) {
case 'AES-GCM':
{
cipher = nodeCrypto.createCipheriv(alg, key, iv, {
authTagLength: tagLength
});
cipher.setAAD(additionalData);
break;
}
case 'AES-CTR':
{
if (iv.length === 0 || iv.length > 16) throw new Error('InvalidIVLength');
var counter = new Uint8Array(16);
counter.set(iv);
counter[15] += 1;
cipher = nodeCrypto.createCipheriv(alg, key, counter);
break;
}
default:
{
// AES-CBC or AES-KW
cipher = nodeCrypto.createCipheriv(alg, key, iv);
break;
}
}
var body;
var final;
var tag;
try {
body = new Uint8Array(cipher.update(msg));
final = new Uint8Array(cipher.final());
tag = new Uint8Array([]);
if (name === 'AES-GCM') tag = new Uint8Array(cipher.getAuthTag());
} catch (e) {
throw new Error('NodeCrypto_EncryptionFailure');
}
var data = new Uint8Array(body.length + final.length + tag.length);
data.set(body);
data.set(final, body.length);
data.set(tag, body.length + final.length);
return data;
};
/**
* Decrypt data through AES Node.js crypto API.
* @param {Uint8Array} data - Encrypted message to be decrypted.
* @param {Uint8Array} key - Byte array of symmetric key.
* @param {String} name - Name of AES algorithm like 'AES-GCM'.
* @param {Uint8Array} [iv] - Byte array of initial vector if required.
* @param {Uint8Array} [additionalData] - Byte array of additional data if required.
* @param {Number} [tagLength] - Authentication tag length if required.
* @param {Object} nodeCrypto - NodeCrypto object, i.e., require(crypto) in Node.js.
* @return {Uint8Array} - Decrypted message byte array.
* @param unwrapKey {Boolean} [false] - true if called as AES-KW
* @throws {Error} - Throws error if UnsupportedCipher or DecryptionFailure.
*/
exports.encrypt = encrypt;
var decrypt = function decrypt(data, key, _ref4, nodeCrypto) {
var name = _ref4.name,
iv = _ref4.iv,
additionalData = _ref4.additionalData,
tagLength = _ref4.tagLength;
var unwrapKey = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
var alg = getNodeName(name, key.byteLength, unwrapKey ? _params.default.wrapKeys : _params.default.ciphers);
var decipher;
var body;
switch (name) {
case 'AES-GCM':
{
decipher = nodeCrypto.createDecipheriv(alg, key, iv, {
authTagLength: tagLength
});
decipher.setAAD(additionalData);
body = data.slice(0, data.length - tagLength);
var tag = data.slice(data.length - tagLength);
decipher.setAuthTag(tag);
break;
}
case 'AES-CTR':
{
if (iv.length === 0 || iv.length > 16) throw new Error('InvalidIVLength');
var counter = new Uint8Array(16);
counter.set(iv);
counter[15] += 1;
decipher = nodeCrypto.createDecipheriv(alg, key, counter);
body = data;
break;
}
default:
{
// AES-CBC or AES-KW
decipher = nodeCrypto.createDecipheriv(alg, key, iv);
body = data;
break;
}
}
var decryptedBody;
var final;
try {
decryptedBody = decipher.update(body);
final = decipher.final();
} catch (e) {
throw new Error('NodeCrypto_DecryptionFailure');
}
var msg = new Uint8Array(final.length + decryptedBody.length);
msg.set(decryptedBody);
msg.set(final, decryptedBody.length);
return msg;
};
/**
* get node algorithm name
* @param name {string} - name of webcrypto alg like AES-GCM
* @param keyLength {number} - aes encryption key
* @param dict {object} - params.ciphers or params.wrapKeys
* @return {string} - node algorithm name
*/
exports.decrypt = decrypt;
var getNodeName = function getNodeName(name, keyLength, dict) {
var alg = dict[name].nodePrefix;
alg = "".concat(alg).concat((keyLength * 8).toString());
return alg + dict[name].nodeSuffix;
};
+48
View File
@@ -0,0 +1,48 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
/**
* params.js
*/
var _default = {
// encryption parameters
ciphers: {
'AES-GCM': {
nodePrefix: 'aes-',
nodeSuffix: '-gcm',
ivLength: 12,
// default value of iv length, 12 bytes is recommended for AES-GCM
tagLength: 16,
staticIvLength: true // if true, IV length must be always ivLength.
},
'AES-CBC': {
nodePrefix: 'aes-',
nodeSuffix: '-cbc',
ivLength: 16,
staticIvLength: true
},
'AES-CTR': {
nodePrefix: 'aes-',
nodeSuffix: '-ctr',
ivLength: 12,
// default value
staticIvLength: false
}
},
// key wrapping parameters
wrapKeys: {
'AES-KW': {
nodePrefix: 'id-aes',
nodeSuffix: '-wrap',
ivLength: 8,
staticIvLength: true,
defaultIV: new Uint8Array([0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6])
}
}
};
exports.default = _default;
+501
View File
@@ -0,0 +1,501 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.decrypt = exports.encrypt = exports.unwrapKey = exports.wrapKey = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
/**
* webapi.js
*/
/**
* WebCrypto KeyWrapping function simply uses encrypt function.
* @param keyToBeWrapped {Uint8Array} - plaintext key
* @param wrappingKey {Uint8Array} - wrapping key
* @param name {string} - 'AES-KW'
* @param iv {Uint8Array} - default is '0xA6A6A6A6A6A6A6A6'
* @param nodeCrypto {Object} - crypto.subtle object
* @return {Uint8Array} - Unwrapped Key
*/
var wrapKey =
/*#__PURE__*/
function () {
var _ref2 = (0, _asyncToGenerator2.default)(
/*#__PURE__*/
_regenerator.default.mark(function _callee(keyToBeWrapped, wrappingKey, _ref, webCrypto) {
var _ref$name, name, iv, kek, cek, data;
return _regenerator.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_ref$name = _ref.name, name = _ref$name === void 0 ? 'AES-KW' : _ref$name, iv = _ref.iv;
if (!(typeof window.msCrypto === 'undefined')) {
_context.next = 20;
break;
}
_context.prev = 2;
_context.next = 5;
return webCrypto.importKey('raw', wrappingKey, {
name: name
}, false, ['wrapKey', 'unwrapKey']);
case 5:
kek = _context.sent;
_context.next = 8;
return webCrypto.importKey('raw', keyToBeWrapped, {
name: name
}, true, ['wrapKey', 'unwrapKey']);
case 8:
cek = _context.sent;
_context.next = 11;
return webCrypto.wrapKey('raw', cek, kek, {
name: name,
iv: iv
});
case 11:
data = _context.sent;
return _context.abrupt("return", new Uint8Array(data));
case 15:
_context.prev = 15;
_context.t0 = _context["catch"](2);
throw new Error("WebCrypto_FailedToWrapKey - ".concat(_context.t0.message));
case 18:
_context.next = 21;
break;
case 20:
throw new Error('ThrowAwayIeAsap');
case 21:
case "end":
return _context.stop();
}
}
}, _callee, null, [[2, 15]]);
}));
return function wrapKey(_x, _x2, _x3, _x4) {
return _ref2.apply(this, arguments);
};
}();
/**
* WebCrypto KeyUnwrapping function as well as keyWrapping
* @param wrappedKey {Uint8Array} - Wrapped key
* @param unwrappingKey {Uint8Array} - Key used for wrapping
* @param name {string} - 'AES-KW'
* @param iv {Uint8Array} - default is '0xA6A6A6A6A6A6A6A6'
* @param nodeCrypto {Object} - crypto.subtle object
* @return {Uint8Array} - Unwrapped Key
*/
exports.wrapKey = wrapKey;
var unwrapKey =
/*#__PURE__*/
function () {
var _ref4 = (0, _asyncToGenerator2.default)(
/*#__PURE__*/
_regenerator.default.mark(function _callee2(wrappedKey, unwrappingKey, _ref3, webCrypto) {
var _ref3$name, name, iv, kek, cek;
return _regenerator.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
_ref3$name = _ref3.name, name = _ref3$name === void 0 ? 'AES-KW' : _ref3$name, iv = _ref3.iv;
if (!(typeof window.msCrypto === 'undefined')) {
_context2.next = 21;
break;
}
_context2.prev = 2;
_context2.next = 5;
return webCrypto.importKey('raw', unwrappingKey, {
name: name
}, false, ['wrapKey', 'unwrapKey']);
case 5:
kek = _context2.sent;
_context2.next = 8;
return webCrypto.unwrapKey('raw', wrappedKey, kek, {
name: name,
iv: iv
}, {
name: 'AES-GCM'
}, true, ['encrypt', 'decrypt']);
case 8:
cek = _context2.sent;
_context2.t0 = Uint8Array;
_context2.next = 12;
return webCrypto.exportKey('raw', cek);
case 12:
_context2.t1 = _context2.sent;
return _context2.abrupt("return", new _context2.t0(_context2.t1));
case 16:
_context2.prev = 16;
_context2.t2 = _context2["catch"](2);
throw new Error("WebCrypto_FailedToUnwrapKey - ".concat(_context2.t2.message));
case 19:
_context2.next = 22;
break;
case 21:
throw new Error('ThrowAwayMsIeAsap');
case 22:
case "end":
return _context2.stop();
}
}
}, _callee2, null, [[2, 16]]);
}));
return function unwrapKey(_x5, _x6, _x7, _x8) {
return _ref4.apply(this, arguments);
};
}();
/**
* Encrypt data through AES of WebCrypto API.
* @param {Uint8Array} msg - Plaintext message to be encrypted.
* @param {Uint8Array} key - Byte array of symmetric key.
* @param {String} name - Name of AES algorithm like 'AES-GCM'.
* @param {Uint8Array} [iv] - Byte array of initial vector if required.
* @param {Uint8Array} [additionalData] - Byte array of additional data if required.
* @param {Number} [tagLength] - Authentication tag length if required.
* @param {Object} webCrypto - WebCrypto object, i.e., window.crypto.subtle or window.msCrypto.subtle
* @return {Promise<Uint8Array>} - Encrypted data byte array.
* @throws {Error} - Throws if UnsupportedCipher.
*/
exports.unwrapKey = unwrapKey;
var encrypt =
/*#__PURE__*/
function () {
var _ref6 = (0, _asyncToGenerator2.default)(
/*#__PURE__*/
_regenerator.default.mark(function _callee3(msg, key, _ref5, webCrypto) {
var _ref5$name, name, iv, additionalData, tagLength, encryptionConfig, sessionKeyObj, data, _sessionKeyObj, encryptedObj, _data;
return _regenerator.default.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
_ref5$name = _ref5.name, name = _ref5$name === void 0 ? 'AES-GCM' : _ref5$name, iv = _ref5.iv, additionalData = _ref5.additionalData, tagLength = _ref5.tagLength;
encryptionConfig = setCipherParams({
name: name,
iv: iv,
additionalData: additionalData,
tagLength: tagLength
});
if (!(typeof window.msCrypto === 'undefined')) {
_context3.next = 18;
break;
}
_context3.prev = 3;
_context3.next = 6;
return webCrypto.importKey('raw', key, encryptionConfig, false, ['encrypt', 'decrypt']);
case 6:
sessionKeyObj = _context3.sent;
_context3.next = 9;
return webCrypto.encrypt(encryptionConfig, sessionKeyObj, msg);
case 9:
data = _context3.sent;
return _context3.abrupt("return", new Uint8Array(data));
case 13:
_context3.prev = 13;
_context3.t0 = _context3["catch"](3);
throw new Error("WebCrypto_EncryptionFailure: ".concat(_context3.t0.message));
case 16:
_context3.next = 38;
break;
case 18:
_context3.prev = 18;
_context3.next = 21;
return msImportKey('raw', key, encryptionConfig, false, ['encrypt', 'decrypt'], webCrypto);
case 21:
_sessionKeyObj = _context3.sent;
_context3.next = 24;
return msEncrypt(encryptionConfig, _sessionKeyObj, msg, webCrypto);
case 24:
encryptedObj = _context3.sent;
if (!(name === 'AES-GCM')) {
_context3.next = 32;
break;
}
_data = new Uint8Array(encryptedObj.ciphertext.byteLength + encryptedObj.tag.byteLength);
_data.set(new Uint8Array(encryptedObj.ciphertext));
_data.set(new Uint8Array(encryptedObj.tag), encryptedObj.ciphertext.byteLength);
return _context3.abrupt("return", _data);
case 32:
return _context3.abrupt("return", new Uint8Array(encryptedObj));
case 33:
_context3.next = 38;
break;
case 35:
_context3.prev = 35;
_context3.t1 = _context3["catch"](18);
throw new Error("ThrowAwayMsIeAsap: ".concat(_context3.t1.message));
case 38:
case "end":
return _context3.stop();
}
}
}, _callee3, null, [[3, 13], [18, 35]]);
}));
return function encrypt(_x9, _x10, _x11, _x12) {
return _ref6.apply(this, arguments);
};
}();
/**
* Decrypt data through AES of WebCrypto API.
* @param {Uint8Array} data - Encrypted message to be decrypted.
* @param {Uint8Array} key - Byte array of symmetric key.
* @param {String} name - Name of AES algorithm like 'AES-GCM'.
* @param {Uint8Array} [iv] - Byte array of initial vector if required.
* @param {Uint8Array} [additionalData] - Byte array of additional data if required.
* @param {Number} [tagLength] - Authentication tag length if required.
* @param {Object} webCrypto - WebCrypto object, i.e., window.crypto.subtle or window.msCrypto.subtle
* @return {Promise<Uint8Array>} - Decrypted plaintext message.
* @throws {Error} - Throws if UnsupportedCipher or DecryptionFailure.
*/
exports.encrypt = encrypt;
var decrypt =
/*#__PURE__*/
function () {
var _ref8 = (0, _asyncToGenerator2.default)(
/*#__PURE__*/
_regenerator.default.mark(function _callee4(data, key, _ref7, webCrypto) {
var name, iv, additionalData, tagLength, decryptionConfig, sessionKeyObj, msg, _sessionKeyObj2, _msg, ciphertext, tag;
return _regenerator.default.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
name = _ref7.name, iv = _ref7.iv, additionalData = _ref7.additionalData, tagLength = _ref7.tagLength;
decryptionConfig = setCipherParams({
name: name,
iv: iv,
additionalData: additionalData,
tagLength: tagLength
});
if (window.msCrypto) {
_context4.next = 18;
break;
}
_context4.prev = 3;
_context4.next = 6;
return webCrypto.importKey('raw', key, decryptionConfig, false, ['encrypt', 'decrypt']);
case 6:
sessionKeyObj = _context4.sent;
_context4.next = 9;
return webCrypto.decrypt(decryptionConfig, sessionKeyObj, data);
case 9:
msg = _context4.sent;
return _context4.abrupt("return", new Uint8Array(msg));
case 13:
_context4.prev = 13;
_context4.t0 = _context4["catch"](3);
throw new Error("WebCrypto_DecryptionFailure: ".concat(_context4.t0.message));
case 16:
_context4.next = 39;
break;
case 18:
_context4.prev = 18;
_context4.next = 21;
return msImportKey('raw', key, decryptionConfig, false, ['encrypt', 'decrypt'], webCrypto);
case 21:
_sessionKeyObj2 = _context4.sent;
if (!(name === 'AES-GCM')) {
_context4.next = 30;
break;
}
ciphertext = data.slice(0, data.length - tagLength);
tag = data.slice(data.length - tagLength, data.length);
_context4.next = 27;
return msDecrypt(Object.assign(decryptionConfig, {
tag: tag
}), _sessionKeyObj2, ciphertext, webCrypto);
case 27:
_msg = _context4.sent;
_context4.next = 33;
break;
case 30:
_context4.next = 32;
return msDecrypt(decryptionConfig, _sessionKeyObj2, data, webCrypto);
case 32:
_msg = _context4.sent;
case 33:
return _context4.abrupt("return", new Uint8Array(_msg));
case 36:
_context4.prev = 36;
_context4.t1 = _context4["catch"](18);
throw new Error("ThrowAwayMsIeAsap: ".concat(_context4.t1.message));
case 39:
case "end":
return _context4.stop();
}
}
}, _callee4, null, [[3, 13], [18, 36]]);
}));
return function decrypt(_x13, _x14, _x15, _x16) {
return _ref8.apply(this, arguments);
};
}();
/**
* Set params for encryption algorithms.
* @param {String} name - Name of AES algorithm like 'AES-GCM'.
* @param {Uint8Array} [iv] - Byte array of initial vector if required.
* @param {Uint8Array} [additionalData] - Byte array of additional data if required.
* @param {Number} [tagLength] - Authentication tag length if required.
*/
exports.decrypt = decrypt;
var setCipherParams = function setCipherParams(_ref9) {
var name = _ref9.name,
iv = _ref9.iv,
additionalData = _ref9.additionalData,
tagLength = _ref9.tagLength;
var alg = {};
switch (name) {
case 'AES-GCM':
{
Object.assign(alg, {
name: name,
iv: iv,
tagLength: tagLength * 8
});
Object.assign(alg, additionalData.length > 0 ? {
additionalData: additionalData
} : {});
break;
}
case 'AES-CBC':
{
alg.name = name;
alg.iv = iv;
break;
}
case 'AES-CTR':
{
if (iv.length === 0 || iv.length > 16) throw new Error('InvalidIVLength');
alg.name = name;
alg.counter = new Uint8Array(16);
alg.counter.set(iv);
alg.counter[15] += 1;
alg.length = 128; // todo: this might be (16 - iv.length) * 8.
break;
}
}
return alg;
}; // function definitions for IE
var msImportKey = function msImportKey(type, key, alg, ext, use, webCrypto) {
return new Promise(function (resolve, reject) {
var op = webCrypto.importKey(type, key, alg, ext, use);
op.oncomplete = function (evt) {
resolve(evt.target.result);
};
op.onerror = function () {
reject('KeyImportingFailed');
};
});
};
var msEncrypt = function msEncrypt(alg, key, msg, webCrypto) {
return new Promise(function (resolve, reject) {
var op = webCrypto.encrypt(alg, key, msg);
op.oncomplete = function (evt) {
resolve(evt.target.result);
};
op.onerror = function () {
reject('EncryptionFailure');
};
});
};
var msDecrypt = function msDecrypt(alg, key, data, webCrypto) {
return new Promise(function (resolve, reject) {
var op = webCrypto.decrypt(alg, key, data);
op.oncomplete = function (evt) {
resolve(evt.target.result);
};
op.onerror = function () {
reject('DecryptionFailure');
};
});
};