123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829 |
- import Utils from "../Utils.js";
- import CryptoJS from "crypto-js";
- import {blowfish as Blowfish} from "sladex-blowfish";
- /**
- * Cipher operations.
- *
- * @author n1474335 [n1474335@gmail.com]
- * @copyright Crown Copyright 2016
- * @license Apache-2.0
- *
- * @namespace
- */
- const Cipher = {
- /**
- * @constant
- * @default
- */
- IO_FORMAT1: ["Hex", "Base64", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1"],
- /**
- * @constant
- * @default
- */
- IO_FORMAT2: ["UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1", "Hex", "Base64"],
- /**
- * @constant
- * @default
- */
- IO_FORMAT3: ["Hex", "Base64", "UTF16", "UTF16LE", "UTF16BE", "Latin1"],
- /**
- * @constant
- * @default
- */
- IO_FORMAT4: ["Latin1", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Hex", "Base64"],
- /**
- * @constant
- * @default
- */
- MODES: ["CBC", "CFB", "CTR", "OFB", "ECB"],
- /**
- * @constant
- * @default
- */
- PADDING: ["Pkcs7", "Iso97971", "AnsiX923", "Iso10126", "ZeroPadding", "NoPadding"],
- /**
- * @constant
- * @default
- */
- RESULT_TYPE: ["Show all", "Ciphertext", "Key", "IV", "Salt"],
- /**
- * Runs encryption operations using the CryptoJS framework.
- *
- * @private
- * @param {function} algo - The CryptoJS algorithm to use
- * @param {byteArray} input
- * @param {function} args
- * @returns {string}
- */
- _enc: function (algo, input, args) {
- let key = Utils.format[args[0].option].parse(args[0].string || ""),
- iv = Utils.format[args[1].option].parse(args[1].string || ""),
- salt = Utils.format[args[2].option].parse(args[2].string || ""),
- mode = CryptoJS.mode[args[3]],
- padding = CryptoJS.pad[args[4]],
- resultOption = args[5].toLowerCase(),
- outputFormat = args[6];
- if (iv.sigBytes === 0) {
- // Use passphrase rather than key. Need to convert it to a string.
- key = key.toString(CryptoJS.enc.Latin1);
- }
- const encrypted = algo.encrypt(input, key, {
- salt: salt.sigBytes > 0 ? salt : false,
- iv: iv.sigBytes > 0 ? iv : null,
- mode: mode,
- padding: padding
- });
- let result = "";
- if (resultOption === "show all") {
- result += "Key: " + encrypted.key.toString(Utils.format[outputFormat]);
- result += "\nIV: " + encrypted.iv.toString(Utils.format[outputFormat]);
- if (encrypted.salt) result += "\nSalt: " + encrypted.salt.toString(Utils.format[outputFormat]);
- result += "\n\nCiphertext: " + encrypted.ciphertext.toString(Utils.format[outputFormat]);
- } else {
- result = encrypted[resultOption].toString(Utils.format[outputFormat]);
- }
- return result;
- },
- /**
- * Runs decryption operations using the CryptoJS framework.
- *
- * @private
- * @param {function} algo - The CryptoJS algorithm to use
- * @param {byteArray} input
- * @param {function} args
- * @returns {string}
- */
- _dec: function (algo, input, args) {
- let key = Utils.format[args[0].option].parse(args[0].string || ""),
- iv = Utils.format[args[1].option].parse(args[1].string || ""),
- salt = Utils.format[args[2].option].parse(args[2].string || ""),
- mode = CryptoJS.mode[args[3]],
- padding = CryptoJS.pad[args[4]],
- inputFormat = args[5],
- outputFormat = args[6];
- // The ZeroPadding option causes a crash when the input length is 0
- if (!input.length) {
- return "No input";
- }
- const ciphertext = Utils.format[inputFormat].parse(input);
- if (iv.sigBytes === 0) {
- // Use passphrase rather than key. Need to convert it to a string.
- key = key.toString(CryptoJS.enc.Latin1);
- }
- const decrypted = algo.decrypt({
- ciphertext: ciphertext,
- salt: salt.sigBytes > 0 ? salt : false
- }, key, {
- iv: iv.sigBytes > 0 ? iv : null,
- mode: mode,
- padding: padding
- });
- let result;
- try {
- result = decrypted.toString(Utils.format[outputFormat]);
- } catch (err) {
- result = "Decrypt error: " + err.message;
- }
- return result;
- },
- /**
- * AES Encrypt operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runAesEnc: function (input, args) {
- return Cipher._enc(CryptoJS.AES, input, args);
- },
- /**
- * AES Decrypt operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runAesDec: function (input, args) {
- return Cipher._dec(CryptoJS.AES, input, args);
- },
- /**
- * DES Encrypt operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runDesEnc: function (input, args) {
- return Cipher._enc(CryptoJS.DES, input, args);
- },
- /**
- * DES Decrypt operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runDesDec: function (input, args) {
- return Cipher._dec(CryptoJS.DES, input, args);
- },
- /**
- * Triple DES Encrypt operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runTripleDesEnc: function (input, args) {
- return Cipher._enc(CryptoJS.TripleDES, input, args);
- },
- /**
- * Triple DES Decrypt operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runTripleDesDec: function (input, args) {
- return Cipher._dec(CryptoJS.TripleDES, input, args);
- },
- /**
- * Rabbit Encrypt operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runRabbitEnc: function (input, args) {
- return Cipher._enc(CryptoJS.Rabbit, input, args);
- },
- /**
- * Rabbit Decrypt operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runRabbitDec: function (input, args) {
- return Cipher._dec(CryptoJS.Rabbit, input, args);
- },
- /**
- * @constant
- * @default
- */
- BLOWFISH_MODES: ["ECB", "CBC", "PCBC", "CFB", "OFB", "CTR"],
- /**
- * @constant
- * @default
- */
- BLOWFISH_OUTPUT_TYPES: ["Base64", "Hex", "String", "Raw"],
- /**
- * Blowfish Encrypt operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runBlowfishEnc: function (input, args) {
- let key = Utils.format[args[0].option].parse(args[0].string).toString(Utils.format.Latin1),
- mode = args[1],
- outputFormat = args[2];
- if (key.length === 0) return "Enter a key";
- let encHex = Blowfish.encrypt(input, key, {
- outputType: 1,
- cipherMode: Cipher.BLOWFISH_MODES.indexOf(mode)
- }),
- enc = CryptoJS.enc.Hex.parse(encHex);
- return enc.toString(Utils.format[outputFormat]);
- },
- /**
- * Blowfish Decrypt operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runBlowfishDec: function (input, args) {
- let key = Utils.format[args[0].option].parse(args[0].string).toString(Utils.format.Latin1),
- mode = args[1],
- inputFormat = args[2];
- if (key.length === 0) return "Enter a key";
- input = Utils.format[inputFormat].parse(input);
- return Blowfish.decrypt(input.toString(CryptoJS.enc.Base64), key, {
- outputType: 0, // This actually means inputType. The library is weird.
- cipherMode: Cipher.BLOWFISH_MODES.indexOf(mode)
- });
- },
- /**
- * @constant
- * @default
- */
- KDF_KEY_SIZE: 256,
- /**
- * @constant
- * @default
- */
- KDF_ITERATIONS: 1,
- /**
- * @constant
- * @default
- */
- HASHERS: ["MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "RIPEMD160"],
- /**
- * Derive PBKDF2 key operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runPbkdf2: function (input, args) {
- let keySize = args[0] / 32,
- iterations = args[1],
- hasher = args[2],
- salt = CryptoJS.enc.Hex.parse(args[3] || ""),
- inputFormat = args[4],
- outputFormat = args[5],
- passphrase = Utils.format[inputFormat].parse(input),
- key = CryptoJS.PBKDF2(passphrase, salt, {
- keySize: keySize,
- hasher: CryptoJS.algo[hasher],
- iterations: iterations,
- });
- return key.toString(Utils.format[outputFormat]);
- },
- /**
- * Derive EVP key operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runEvpkdf: function (input, args) {
- let keySize = args[0] / 32,
- iterations = args[1],
- hasher = args[2],
- salt = CryptoJS.enc.Hex.parse(args[3] || ""),
- inputFormat = args[4],
- outputFormat = args[5],
- passphrase = Utils.format[inputFormat].parse(input),
- key = CryptoJS.EvpKDF(passphrase, salt, {
- keySize: keySize,
- hasher: CryptoJS.algo[hasher],
- iterations: iterations,
- });
- return key.toString(Utils.format[outputFormat]);
- },
- /**
- * RC4 operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runRc4: function (input, args) {
- let message = Utils.format[args[1]].parse(input),
- passphrase = Utils.format[args[0].option].parse(args[0].string),
- encrypted = CryptoJS.RC4.encrypt(message, passphrase);
- return encrypted.ciphertext.toString(Utils.format[args[2]]);
- },
- /**
- * @constant
- * @default
- */
- RC4DROP_BYTES: 768,
- /**
- * RC4 Drop operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runRc4drop: function (input, args) {
- let message = Utils.format[args[1]].parse(input),
- passphrase = Utils.format[args[0].option].parse(args[0].string),
- drop = args[3],
- encrypted = CryptoJS.RC4Drop.encrypt(message, passphrase, { drop: drop });
- return encrypted.ciphertext.toString(Utils.format[args[2]]);
- },
- /**
- * Vigenère Encode operation.
- *
- * @author Matt C [matt@artemisbot.uk]
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runVigenereEnc: function (input, args) {
- let alphabet = "abcdefghijklmnopqrstuvwxyz",
- key = args[0].toLowerCase(),
- output = "",
- fail = 0,
- keyIndex,
- msgIndex,
- chr;
- if (!key) return "No key entered";
- if (!/^[a-zA-Z]+$/.test(key)) return "The key must consist only of letters";
- for (let i = 0; i < input.length; i++) {
- if (alphabet.indexOf(input[i]) >= 0) {
- // Get the corresponding character of key for the current letter, accounting
- // for chars not in alphabet
- chr = key[(i - fail) % key.length];
- // Get the location in the vigenere square of the key char
- keyIndex = alphabet.indexOf(chr);
- // Get the location in the vigenere square of the message char
- msgIndex = alphabet.indexOf(input[i]);
- // Get the encoded letter by finding the sum of indexes modulo 26 and finding
- // the letter corresponding to that
- output += alphabet[(keyIndex + msgIndex) % 26];
- } else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {
- chr = key[(i - fail) % key.length].toLowerCase();
- keyIndex = alphabet.indexOf(chr);
- msgIndex = alphabet.indexOf(input[i].toLowerCase());
- output += alphabet[(keyIndex + msgIndex) % 26].toUpperCase();
- } else {
- output += input[i];
- fail++;
- }
- }
- return output;
- },
- /**
- * Vigenère Decode operation.
- *
- * @author Matt C [matt@artemisbot.uk]
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runVigenereDec: function (input, args) {
- let alphabet = "abcdefghijklmnopqrstuvwxyz",
- key = args[0].toLowerCase(),
- output = "",
- fail = 0,
- keyIndex,
- msgIndex,
- chr;
- if (!key) return "No key entered";
- if (!/^[a-zA-Z]+$/.test(key)) return "The key must consist only of letters";
- for (let i = 0; i < input.length; i++) {
- if (alphabet.indexOf(input[i]) >= 0) {
- chr = key[(i - fail) % key.length];
- keyIndex = alphabet.indexOf(chr);
- msgIndex = alphabet.indexOf(input[i]);
- // Subtract indexes from each other, add 26 just in case the value is negative,
- // modulo to remove if neccessary
- output += alphabet[(msgIndex - keyIndex + alphabet.length) % 26];
- } else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {
- chr = key[(i - fail) % key.length].toLowerCase();
- keyIndex = alphabet.indexOf(chr);
- msgIndex = alphabet.indexOf(input[i].toLowerCase());
- output += alphabet[(msgIndex + alphabet.length - keyIndex) % 26].toUpperCase();
- } else {
- output += input[i];
- fail++;
- }
- }
- return output;
- },
- /**
- * @constant
- * @default
- */
- AFFINE_A: 1,
- /**
- * @constant
- * @default
- */
- AFFINE_B: 0,
- /**
- * Affine Cipher Encode operation.
- *
- * @author Matt C [matt@artemisbot.uk]
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runAffineEnc: function (input, args) {
- let alphabet = "abcdefghijklmnopqrstuvwxyz",
- a = args[0],
- b = args[1],
- output = "";
- if (!/^\+?(0|[1-9]\d*)$/.test(a) || !/^\+?(0|[1-9]\d*)$/.test(b)) {
- return "The values of a and b can only be integers.";
- }
- for (let i = 0; i < input.length; i++) {
- if (alphabet.indexOf(input[i]) >= 0) {
- // Uses the affine function ax+b % m = y (where m is length of the alphabet)
- output += alphabet[((a * alphabet.indexOf(input[i])) + b) % 26];
- } else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {
- // Same as above, accounting for uppercase
- output += alphabet[((a * alphabet.indexOf(input[i].toLowerCase())) + b) % 26].toUpperCase();
- } else {
- // Non-alphabetic characters
- output += input[i];
- }
- }
- return output;
- },
- /**
- * Affine Cipher Decode operation.
- *
- * @author Matt C [matt@artemisbot.uk]
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runAffineDec: function (input, args) {
- let alphabet = "abcdefghijklmnopqrstuvwxyz",
- a = args[0],
- b = args[1],
- output = "",
- aModInv;
- if (!/^\+?(0|[1-9]\d*)$/.test(a) || !/^\+?(0|[1-9]\d*)$/.test(b)) {
- return "The values of a and b can only be integers.";
- }
- if (Utils.gcd(a, 26) !== 1) {
- return "The value of a must be coprime to 26.";
- }
- // Calculates modular inverse of a
- aModInv = Utils.modInv(a, 26);
- for (let i = 0; i < input.length; i++) {
- if (alphabet.indexOf(input[i]) >= 0) {
- // Uses the affine decode function (y-b * A') % m = x (where m is length of the alphabet and A' is modular inverse)
- output += alphabet[Utils.mod((alphabet.indexOf(input[i]) - b) * aModInv, 26)];
- } else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) {
- // Same as above, accounting for uppercase
- output += alphabet[Utils.mod((alphabet.indexOf(input[i].toLowerCase()) - b) * aModInv, 26)].toUpperCase();
- } else {
- // Non-alphabetic characters
- output += input[i];
- }
- }
- return output;
- },
- /**
- * Atbash Cipher Encode operation.
- *
- * @author Matt C [matt@artemisbot.uk]
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runAtbash: function (input, args) {
- return Cipher.runAffineEnc(input, [25, 25]);
- },
- /**
- * Generates a polybius square for the given keyword
- *
- * @private
- * @author Matt C [matt@artemisbot.uk]
- * @param {string} keyword - Must be upper case
- * @returns {string}
- */
- _genPolybiusSquare: function (keyword) {
- const alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
- const polArray = `${keyword}${alpha}`.split("").unique();
- let polybius = [];
- for (let i = 0; i < 5; i++) {
- polybius[i] = polArray.slice(i*5, i*5 + 5);
- }
- return polybius;
- },
- /**
- * Bifid Cipher Encode operation
- *
- * @author Matt C [matt@artemisbot.uk]
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runBifidEnc: function (input, args) {
- const keywordStr = args[0].toUpperCase().replace("J", "I"),
- keyword = keywordStr.split("").unique(),
- alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
- let output = "",
- xCo = [],
- yCo = [],
- structure = [],
- count = 0;
- if (keyword.length > 25)
- return "The alphabet keyword must be less than 25 characters.";
- if (!/^[a-zA-Z]+$/.test(keywordStr) && keyword.length > 0)
- return "The key must consist only of letters";
- const polybius = Cipher._genPolybiusSquare(keywordStr);
- input.replace("J", "I").split("").forEach(letter => {
- let alpInd = alpha.split("").indexOf(letter.toLocaleUpperCase()) >= 0,
- polInd;
- if (alpInd) {
- for (let i = 0; i < 5; i++) {
- polInd = polybius[i].indexOf(letter.toLocaleUpperCase());
- if (polInd >= 0) {
- xCo.push(polInd);
- yCo.push(i);
- }
- }
- if (alpha.split("").indexOf(letter) >= 0) {
- structure.push(true);
- } else if (alpInd) {
- structure.push(false);
- }
- } else {
- structure.push(letter);
- }
- });
- const trans = `${yCo.join("")}${xCo.join("")}`;
- structure.forEach(pos => {
- if (typeof pos === "boolean") {
- let coords = trans.substr(2*count, 2).split("");
- output += pos ?
- polybius[coords[0]][coords[1]] :
- polybius[coords[0]][coords[1]].toLocaleLowerCase();
- count++;
- } else {
- output += pos;
- }
- });
- return output;
- },
- /**
- * Bifid Cipher Decode operation
- *
- * @author Matt C [matt@artemisbot.uk]
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runBifidDec: function (input, args) {
- const keywordStr = args[0].toUpperCase().replace("J", "I"),
- keyword = keywordStr.split("").unique(),
- alpha = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
- let output = "",
- structure = [],
- count = 0,
- trans = "";
- if (keyword.length > 25)
- return "The alphabet keyword must be less than 25 characters.";
- if (!/^[a-zA-Z]+$/.test(keywordStr) && keyword.length > 0)
- return "The key must consist only of letters";
- const polybius = Cipher._genPolybiusSquare(keywordStr);
- input.replace("J", "I").split("").forEach((letter) => {
- let alpInd = alpha.split("").indexOf(letter.toLocaleUpperCase()) >= 0,
- polInd;
- if (alpInd) {
- for (let i = 0; i < 5; i++) {
- polInd = polybius[i].indexOf(letter.toLocaleUpperCase());
- if (polInd >= 0) {
- trans += `${i}${polInd}`;
- }
- }
- if (alpha.split("").indexOf(letter) >= 0) {
- structure.push(true);
- } else if (alpInd) {
- structure.push(false);
- }
- } else {
- structure.push(letter);
- }
- });
- structure.forEach(pos => {
- if (typeof pos === "boolean") {
- let coords = [trans[count], trans[count+trans.length/2]];
- output += pos ?
- polybius[coords[0]][coords[1]] :
- polybius[coords[0]][coords[1]].toLocaleLowerCase();
- count++;
- } else {
- output += pos;
- }
- });
- return output;
- },
- /**
- * @constant
- * @default
- */
- SUBS_PLAINTEXT: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
- /**
- * @constant
- * @default
- */
- SUBS_CIPHERTEXT: "XYZABCDEFGHIJKLMNOPQRSTUVW",
- /**
- * Substitute operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runSubstitute: function (input, args) {
- let plaintext = Utils.expandAlphRange(args[0]).join(""),
- ciphertext = Utils.expandAlphRange(args[1]).join(""),
- output = "",
- index = -1;
- if (plaintext.length !== ciphertext.length) {
- output = "Warning: Plaintext and Ciphertext lengths differ\n\n";
- }
- for (let i = 0; i < input.length; i++) {
- index = plaintext.indexOf(input[i]);
- output += index > -1 && index < ciphertext.length ? ciphertext[index] : input[i];
- }
- return output;
- },
- };
- export default Cipher;
- /**
- * Overwriting the CryptoJS OpenSSL key derivation function so that it is possible to not pass a
- * salt in.
- * @param {string} password - The password to derive from.
- * @param {number} keySize - The size in words of the key to generate.
- * @param {number} ivSize - The size in words of the IV to generate.
- * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be
- * generated randomly. If set to false, no salt will be added.
- *
- * @returns {CipherParams} A cipher params object with the key, IV, and salt.
- *
- * @static
- *
- * @example
- * // Randomly generates a salt
- * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32);
- * // Uses the salt 'saltsalt'
- * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
- * // Does not use a salt
- * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, false);
- */
- CryptoJS.kdf.OpenSSL.execute = function (password, keySize, ivSize, salt) {
- // Generate random salt if no salt specified and not set to false
- // This line changed from `if (!salt) {` to the following
- if (salt === undefined || salt === null) {
- salt = CryptoJS.lib.WordArray.random(64/8);
- }
- // Derive key and IV
- const key = CryptoJS.algo.EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
- // Separate key and IV
- const iv = CryptoJS.lib.WordArray.create(key.words.slice(keySize), ivSize * 4);
- key.sigBytes = keySize * 4;
- // Return params
- return CryptoJS.lib.CipherParams.create({ key: key, iv: iv, salt: salt });
- };
|