forked from daren.hsu/line_push
219 lines
6.7 KiB
JavaScript
219 lines
6.7 KiB
JavaScript
"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;
|
|
}; |