UNPKG

crypto-ts

Version:

Typescript library of crypto standards.

1,559 lines (1,539 loc) 72.3 kB
/** * @license crypto-ts * MIT license */ /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class Hex { /** * Converts a word array to a hex string. * * \@example * * let hexString = Hex.stringify(wordArray); * @param {?} wordArray The word array. * * @return {?} The hex string. * */ static stringify(wordArray) { // Convert const /** @type {?} */ hexChars = []; for (let /** @type {?} */ i = 0; i < wordArray.sigBytes; i++) { const /** @type {?} */ bite = (wordArray.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; hexChars.push((bite >>> 4).toString(16)); hexChars.push((bite & 0x0f).toString(16)); } return hexChars.join(''); } /** * Converts a hex string to a word array. * * \@example * * let wordArray = Hex.parse(hexString); * @param {?} hexStr The hex string. * * @return {?} The word array. * */ static parse(hexStr) { // Shortcut const /** @type {?} */ hexStrLength = hexStr.length; // Convert const /** @type {?} */ words = []; for (let /** @type {?} */ i = 0; i < hexStrLength; i += 2) { words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); } return new WordArray(words, hexStrLength / 2); } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class WordArray { /** * Creates a word array filled with random bytes. * * \@example * * let wordArray = WordArray.random(16); * @param {?} nBytes The number of random bytes to generate. * * @return {?} The random word array. * */ static random(nBytes) { const /** @type {?} */ words = []; const /** @type {?} */ r = (function (m_w) { let /** @type {?} */ m_z = 0x3ade68b1; const /** @type {?} */ mask = 0xffffffff; return function () { m_z = (0x9069 * (m_z & 0xFFFF) + (m_z >> 0x10)) & mask; m_w = (0x4650 * (m_w & 0xFFFF) + (m_w >> 0x10)) & mask; let /** @type {?} */ result = ((m_z << 0x10) + m_w) & mask; result /= 0x100000000; result += 0.5; return result * (Math.random() > .5 ? 1 : -1); }; }); for (let /** @type {?} */ i = 0, /** @type {?} */ rcache; i < nBytes; i += 4) { const /** @type {?} */ _r = r((rcache || Math.random()) * 0x100000000); rcache = _r() * 0x3ade67b7; words.push((_r() * 0x100000000) | 0); } return new WordArray(words, nBytes); } /** * Initializes a newly created word array. * * \@example * * let wordArray = new WordArray(); * let wordArray = new WordArray([0x00010203, 0x04050607]); * let wordArray = new WordArray([0x00010203, 0x04050607], 6); * @param {?=} words (Optional) An array of 32-bit words. * @param {?=} sigBytes (Optional) The number of significant bytes in the words. * */ constructor(words, sigBytes) { this.words = words || []; if (sigBytes !== undefined) { this.sigBytes = sigBytes; } else { this.sigBytes = this.words.length * 4; } } /** * Converts this word array to a string. * * \@example * * let string = wordArray + ''; * let string = wordArray.toString(); * let string = wordArray.toString(CryptoJS.enc.Utf8); * @param {?=} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex * * @return {?} The stringified word array. * */ toString(encoder) { return (encoder || Hex).stringify(this); } /** * Concatenates a word array to this word array. * * \@example * * wordArray1.concat(wordArray2); * @param {?} wordArray The word array to append. * * @return {?} This word array. * */ concat(wordArray) { // Clamp excess bits this.clamp(); // Concat if (this.sigBytes % 4) { // Copy one byte at a time for (let /** @type {?} */ i = 0; i < wordArray.sigBytes; i++) { const /** @type {?} */ thatByte = (wordArray.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; this.words[(this.sigBytes + i) >>> 2] |= thatByte << (24 - ((this.sigBytes + i) % 4) * 8); } } else { // Copy one word at a time for (let /** @type {?} */ i = 0; i < wordArray.sigBytes; i += 4) { this.words[(this.sigBytes + i) >>> 2] = wordArray.words[i >>> 2]; } } this.sigBytes += wordArray.sigBytes; // Chainable return this; } /** * Removes insignificant bits. * * \@example * * wordArray.clamp(); * @return {?} */ clamp() { // Clamp this.words[this.sigBytes >>> 2] &= 0xffffffff << (32 - (this.sigBytes % 4) * 8); this.words.length = Math.ceil(this.sigBytes / 4); } /** * Creates a copy of this word array. * * \@example * * let clone = wordArray.clone(); * @return {?} The clone. * */ clone() { return new WordArray(this.words.slice(0), this.sigBytes); } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class Latin1 { /** * Converts a word array to a Latin1 string. * * \@example * * let latin1String = Latin1.stringify(wordArray); * @param {?} wordArray The word array. * * @return {?} The Latin1 string. * */ static stringify(wordArray) { // Convert const /** @type {?} */ latin1Chars = []; for (let /** @type {?} */ i = 0; i < wordArray.sigBytes; i++) { const /** @type {?} */ bite = (wordArray.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; latin1Chars.push(String.fromCharCode(bite)); } return latin1Chars.join(''); } /** * Converts a Latin1 string to a word array. * * \@example * * let wordArray = Latin1.parse(latin1String); * @param {?} latin1Str The Latin1 string. * * @return {?} The word array. * */ static parse(latin1Str) { // Shortcut const /** @type {?} */ latin1StrLength = latin1Str.length; // Convert const /** @type {?} */ words = []; for (let /** @type {?} */ i = 0; i < latin1StrLength; i++) { words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); } return new WordArray(words, latin1StrLength); } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class Utf8 { /** * Converts a word array to a UTF-8 string. * * \@example * * let utf8String = Utf8.stringify(wordArray); * @param {?} wordArray The word array. * * @return {?} The UTF-8 string. * */ static stringify(wordArray) { try { return decodeURIComponent(escape(Latin1.stringify(wordArray))); } catch (/** @type {?} */ e) { throw new Error('Malformed UTF-8 data'); } } /** * Converts a UTF-8 string to a word array. * * \@example * * let wordArray = Utf8.parse(utf8String); * @param {?} utf8Str The UTF-8 string. * * @return {?} The word array. * */ static parse(utf8Str) { return Latin1.parse(unescape(encodeURIComponent(utf8Str))); } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @abstract */ class BufferedBlockAlgorithm { /** * @param {?=} cfg */ constructor(cfg) { this._minBufferSize = 0; this.cfg = Object.assign({ blockSize: 1 }, cfg); // Initial values this._data = new WordArray(); this._nDataBytes = 0; } /** * Resets this block algorithm's data buffer to its initial state. * * \@example * * bufferedBlockAlgorithm.reset(); * @return {?} */ reset() { // Initial values this._data = new WordArray(); this._nDataBytes = 0; } /** * Adds new data to this block algorithm's buffer. * * \@example * * bufferedBlockAlgorithm._append('data'); * bufferedBlockAlgorithm._append(wordArray); * @param {?} data The data to append. Strings are converted to a WordArray using UTF-8. * * @return {?} */ _append(data) { // Convert string to WordArray, else assume WordArray already if (typeof data === 'string') { data = Utf8.parse(data); } // Append this._data.concat(data); this._nDataBytes += data.sigBytes; } /** * Processes available data blocks. * * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. * * \@example * * let processedData = bufferedBlockAlgorithm._process(); * let processedData = bufferedBlockAlgorithm._process(!!'flush'); * @param {?=} doFlush Whether all blocks and partial blocks should be processed. * * @return {?} The processed data. * */ _process(doFlush) { if (!this.cfg.blockSize) { throw new Error('missing blockSize in config'); } // Shortcuts const /** @type {?} */ blockSizeBytes = this.cfg.blockSize * 4; // Count blocks ready let /** @type {?} */ nBlocksReady = this._data.sigBytes / blockSizeBytes; if (doFlush) { // Round up to include partial blocks nBlocksReady = Math.ceil(nBlocksReady); } else { // Round down to include only full blocks, // less the number of blocks that must remain in the buffer nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); } // Count words ready const /** @type {?} */ nWordsReady = nBlocksReady * this.cfg.blockSize; // Count bytes ready const /** @type {?} */ nBytesReady = Math.min(nWordsReady * 4, this._data.sigBytes); // Process blocks let /** @type {?} */ processedWords; if (nWordsReady) { for (let /** @type {?} */ offset = 0; offset < nWordsReady; offset += this.cfg.blockSize) { // Perform concrete-algorithm logic this._doProcessBlock(this._data.words, offset); } // Remove processed words processedWords = this._data.words.splice(0, nWordsReady); this._data.sigBytes -= nBytesReady; } // Return processed words return new WordArray(processedWords, nBytesReady); } /** * Creates a copy of this object. * * \@example * * let clone = bufferedBlockAlgorithm.clone(); * @return {?} The clone. * */ clone() { const /** @type {?} */ clone = this.constructor(); for (const /** @type {?} */ attr in this) { if (this.hasOwnProperty(attr)) { clone[attr] = this[attr]; } } clone._data = this._data.clone(); return clone; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class Base { } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class CipherParams extends Base { /** * Initializes a newly created cipher params object. * * \@example * * let cipherParams = CipherParams.create({ * ciphertext: ciphertextWordArray, * key: keyWordArray, * iv: ivWordArray, * salt: saltWordArray, * algorithm: AESAlgorithm, * mode: CBC, * padding: PKCS7, * blockSize: 4, * formatter: OpenSSLFormatter * }); * @param {?} cipherParams An object with any of the possible cipher parameters. * */ constructor(cipherParams) { super(); this.ciphertext = cipherParams.ciphertext; this.key = cipherParams.key; this.iv = cipherParams.iv; this.salt = cipherParams.salt; this.algorithm = cipherParams.algorithm; this.mode = cipherParams.mode; this.padding = cipherParams.padding; this.blockSize = cipherParams.blockSize; this.formatter = cipherParams.formatter; } /** * @param {?} additionalParams * @return {?} */ extend(additionalParams) { if (additionalParams.ciphertext !== undefined) { this.ciphertext = additionalParams.ciphertext; } if (additionalParams.key !== undefined) { this.key = additionalParams.key; } if (additionalParams.iv !== undefined) { this.iv = additionalParams.iv; } if (additionalParams.salt !== undefined) { this.salt = additionalParams.salt; } if (additionalParams.algorithm !== undefined) { this.algorithm = additionalParams.algorithm; } if (additionalParams.mode !== undefined) { this.mode = additionalParams.mode; } if (additionalParams.padding !== undefined) { this.padding = additionalParams.padding; } if (additionalParams.blockSize !== undefined) { this.blockSize = additionalParams.blockSize; } if (additionalParams.formatter !== undefined) { this.formatter = additionalParams.formatter; } return this; } /** * Converts this cipher params object to a string. * * @throws Error If neither the formatter nor the default formatter is set. * * \@example * * let string = cipherParams + ''; * let string = cipherParams.toString(); * let string = cipherParams.toString(CryptoJS.format.OpenSSL); * @param {?=} formatter (Optional) The formatting strategy to use. * * @return {?} The stringified cipher params. * */ toString(formatter) { if (formatter) { return formatter.stringify(this); } else if (this.formatter) { return this.formatter.stringify(this); } else { throw new Error('cipher needs a formatter to be able to convert the result into a string'); } } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class Base64 { /** * Converts a word array to a Base64 string. * * \@example * * let base64String = Base64.stringify(wordArray); * @param {?} wordArray The word array. * * @return {?} The Base64 string. * */ static stringify(wordArray) { // Clamp excess bits wordArray.clamp(); // Convert const /** @type {?} */ base64Chars = []; for (let /** @type {?} */ i = 0; i < wordArray.sigBytes; i += 3) { const /** @type {?} */ byte1 = (wordArray.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; const /** @type {?} */ byte2 = (wordArray.words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; const /** @type {?} */ byte3 = (wordArray.words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; const /** @type {?} */ triplet = (byte1 << 16) | (byte2 << 8) | byte3; for (let /** @type {?} */ j = 0; (j < 4) && (i + j * 0.75 < wordArray.sigBytes); j++) { base64Chars.push(this._map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); } } // Add padding const /** @type {?} */ paddingChar = this._map.charAt(64); if (paddingChar) { while (base64Chars.length % 4) { base64Chars.push(paddingChar); } } return base64Chars.join(''); } /** * Converts a Base64 string to a word array. * * \@example * * let wordArray = Base64.parse(base64String); * @param {?} base64Str The Base64 string. * * @return {?} The word array. * */ static parse(base64Str) { // Shortcuts let /** @type {?} */ base64StrLength = base64Str.length; if (this._reverseMap === undefined) { this._reverseMap = []; for (let /** @type {?} */ j = 0; j < this._map.length; j++) { this._reverseMap[this._map.charCodeAt(j)] = j; } } // Ignore padding const /** @type {?} */ paddingChar = this._map.charAt(64); if (paddingChar) { const /** @type {?} */ paddingIndex = base64Str.indexOf(paddingChar); if (paddingIndex !== -1) { base64StrLength = paddingIndex; } } // Convert return this.parseLoop(base64Str, base64StrLength, this._reverseMap); } /** * @param {?} base64Str * @param {?} base64StrLength * @param {?} reverseMap * @return {?} */ static parseLoop(base64Str, base64StrLength, reverseMap) { const /** @type {?} */ words = []; let /** @type {?} */ nBytes = 0; for (let /** @type {?} */ i = 0; i < base64StrLength; i++) { if (i % 4) { const /** @type {?} */ bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2); const /** @type {?} */ bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2); words[nBytes >>> 2] |= (bits1 | bits2) << (24 - (nBytes % 4) * 8); nBytes++; } } return new WordArray(words, nBytes); } } Base64._map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; Base64._reverseMap = undefined; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class OpenSSL { /** * Converts a cipher params object to an OpenSSL-compatible string. * * \@example * * let openSSLString = OpenSSLFormatter.stringify(cipherParams); * @param {?} cipherParams The cipher params object. * * @return {?} The OpenSSL-compatible string. * */ static stringify(cipherParams) { if (!cipherParams.ciphertext) { throw new Error('missing ciphertext in params'); } // Shortcuts const /** @type {?} */ ciphertext = cipherParams.ciphertext; const /** @type {?} */ salt = cipherParams.salt; // Format let /** @type {?} */ wordArray; if (salt) { if (typeof salt === 'string') { throw new Error('salt is expected to be a WordArray'); } wordArray = (new WordArray([0x53616c74, 0x65645f5f])).concat(salt).concat(ciphertext); } else { wordArray = ciphertext; } return wordArray.toString(Base64); } /** * Converts an OpenSSL-compatible string to a cipher params object. * * \@example * * let cipherParams = OpenSSLFormatter.parse(openSSLString); * @param {?} openSSLStr The OpenSSL-compatible string. * * @return {?} The cipher params object. * */ static parse(openSSLStr) { // Parse base64 const /** @type {?} */ ciphertext = Base64.parse(openSSLStr); // Test for salt let /** @type {?} */ salt; if (ciphertext.words[0] === 0x53616c74 && ciphertext.words[1] === 0x65645f5f) { // Extract salt salt = new WordArray(ciphertext.words.slice(2, 4)); // Remove salt from ciphertext ciphertext.words.splice(0, 4); ciphertext.sigBytes -= 16; } return new CipherParams({ ciphertext: ciphertext, salt: salt }); } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class SerializableCipher { /** * Encrypts a message. * * \@example * * let ciphertextParams = SerializableCipher.encrypt(CryptoJS.algo.AES, message, key); * let ciphertextParams = SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv }); * let ciphertextParams = SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { * iv: iv, * format: CryptoJS.format.OpenSSL * }); * @param {?} cipher The cipher algorithm to use. * @param {?} message The message to encrypt. * @param {?} key The key. * @param {?=} cfg (Optional) The configuration options to use for this operation. * * @return {?} A cipher params object. * */ static encrypt(cipher, message, key, cfg) { // Apply config defaults const /** @type {?} */ config = Object.assign({}, this.cfg, cfg); // Encrypt const /** @type {?} */ encryptor = cipher.createEncryptor(key, config); const /** @type {?} */ ciphertext = encryptor.finalize(message); // Create and return serializable cipher params return new CipherParams({ ciphertext: ciphertext, key: key, iv: encryptor.cfg.iv, algorithm: cipher, mode: (/** @type {?} */ (encryptor.cfg)).mode, padding: (/** @type {?} */ (encryptor.cfg)).padding, blockSize: encryptor.cfg.blockSize, formatter: config.format }); } /** * Decrypts serialized ciphertext. * * \@example * * let plaintext = SerializableCipher.decrypt( * AESAlgorithm, * formattedCiphertext, * key, { * iv: iv, * format: CryptoJS.format.OpenSSL * } * ); * * let plaintext = SerializableCipher.decrypt( * AESAlgorithm, * ciphertextParams, * key, { * iv: iv, * format: CryptoJS.format.OpenSSL * } * ); * @param {?} cipher The cipher algorithm to use. * @param {?} ciphertext The ciphertext to decrypt. * @param {?} key The key. * @param {?=} optionalCfg * @return {?} The plaintext. * */ static decrypt(cipher, ciphertext, key, optionalCfg) { // Apply config defaults const /** @type {?} */ cfg = Object.assign({}, this.cfg, optionalCfg); if (!cfg.format) { throw new Error('could not determine format'); } // Convert string to CipherParams ciphertext = this._parse(ciphertext, cfg.format); if (!ciphertext.ciphertext) { throw new Error('could not determine ciphertext'); } // Decrypt const /** @type {?} */ plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext); return plaintext; } /** * Converts serialized ciphertext to CipherParams, * else assumed CipherParams already and returns ciphertext unchanged. * * \@example * * var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format); * @param {?} ciphertext The ciphertext. * @param {?} format The formatting strategy to use to parse serialized ciphertext. * * @return {?} The unserialized ciphertext. * */ static _parse(ciphertext, format) { if (typeof ciphertext === 'string') { return format.parse(ciphertext); } else { return ciphertext; } } } SerializableCipher.cfg = { blockSize: 4, iv: new WordArray([]), format: OpenSSL }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @abstract */ class Hasher extends BufferedBlockAlgorithm { /** * Creates a shortcut function to a hasher's object interface. * * \@example * * let SHA256 = Hasher._createHelper(SHA256); * @param {?} hasher The hasher to create a helper for. * * @return {?} The shortcut function. * */ static _createHelper(hasher) { /** * @param {?} message * @param {?=} cfg * @return {?} */ function helper(message, cfg) { const /** @type {?} */ hasherClass = hasher; const /** @type {?} */ hasherInstance = new hasherClass(cfg); return hasherInstance.finalize(message); } return helper; } /** * Initializes a newly created hasher. * * \@example * * let hasher = CryptoJS.algo.SHA256.create(); * @param {?=} cfg (Optional) The configuration options to use for this hash computation. * */ constructor(cfg) { // Apply config defaults super(Object.assign({ blockSize: 512 / 32 }, cfg)); // Set initial values this.reset(); } /** * Updates this hasher with a message. * * \@example * * hasher.update('message'); * hasher.update(wordArray); * @param {?} messageUpdate The message to append. * * @return {?} This hasher. * */ update(messageUpdate) { // Append this._append(messageUpdate); // Update the hash this._process(); // Chainable return this; } /** * Finalizes the hash computation. * Note that the finalize operation is effectively a destructive, read-once operation. * * \@example * * let hash = hasher.finalize(); * let hash = hasher.finalize('message'); * let hash = hasher.finalize(wordArray); * @param {?} messageUpdate (Optional) A final message update. * * @return {?} The hash. * */ finalize(messageUpdate) { // Final message update if (messageUpdate) { this._append(messageUpdate); } // Perform concrete-hasher logic const /** @type {?} */ hash = this._doFinalize(); return hash; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ // Constants table const /** @type {?} */ T = []; // Compute constants for (let /** @type {?} */ i = 0; i < 64; i++) { T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0; } class MD5 extends Hasher { /** * @param {?} a * @param {?} b * @param {?} c * @param {?} d * @param {?} x * @param {?} s * @param {?} t * @return {?} */ static FF(a, b, c, d, x, s, t) { const /** @type {?} */ n = a + ((b & c) | (~b & d)) + x + t; return ((n << s) | (n >>> (32 - s))) + b; } /** * @param {?} a * @param {?} b * @param {?} c * @param {?} d * @param {?} x * @param {?} s * @param {?} t * @return {?} */ static GG(a, b, c, d, x, s, t) { const /** @type {?} */ n = a + ((b & d) | (c & ~d)) + x + t; return ((n << s) | (n >>> (32 - s))) + b; } /** * @param {?} a * @param {?} b * @param {?} c * @param {?} d * @param {?} x * @param {?} s * @param {?} t * @return {?} */ static HH(a, b, c, d, x, s, t) { const /** @type {?} */ n = a + (b ^ c ^ d) + x + t; return ((n << s) | (n >>> (32 - s))) + b; } /** * @param {?} a * @param {?} b * @param {?} c * @param {?} d * @param {?} x * @param {?} s * @param {?} t * @return {?} */ static II(a, b, c, d, x, s, t) { const /** @type {?} */ n = a + (c ^ (b | ~d)) + x + t; return ((n << s) | (n >>> (32 - s))) + b; } /** * @return {?} */ reset() { // reset core values super.reset(); this._hash = new WordArray([ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 ]); } /** * @param {?} M * @param {?} offset * @return {?} */ _doProcessBlock(M, offset) { // Swap endian for (let /** @type {?} */ i = 0; i < 16; i++) { // Shortcuts const /** @type {?} */ offset_i = offset + i; const /** @type {?} */ M_offset_i = M[offset_i]; M[offset_i] = ((((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00)); } // Shortcuts const /** @type {?} */ H = this._hash.words; const /** @type {?} */ M_offset_0 = M[offset + 0]; const /** @type {?} */ M_offset_1 = M[offset + 1]; const /** @type {?} */ M_offset_2 = M[offset + 2]; const /** @type {?} */ M_offset_3 = M[offset + 3]; const /** @type {?} */ M_offset_4 = M[offset + 4]; const /** @type {?} */ M_offset_5 = M[offset + 5]; const /** @type {?} */ M_offset_6 = M[offset + 6]; const /** @type {?} */ M_offset_7 = M[offset + 7]; const /** @type {?} */ M_offset_8 = M[offset + 8]; const /** @type {?} */ M_offset_9 = M[offset + 9]; const /** @type {?} */ M_offset_10 = M[offset + 10]; const /** @type {?} */ M_offset_11 = M[offset + 11]; const /** @type {?} */ M_offset_12 = M[offset + 12]; const /** @type {?} */ M_offset_13 = M[offset + 13]; const /** @type {?} */ M_offset_14 = M[offset + 14]; const /** @type {?} */ M_offset_15 = M[offset + 15]; // Working variables let /** @type {?} */ a = H[0]; let /** @type {?} */ b = H[1]; let /** @type {?} */ c = H[2]; let /** @type {?} */ d = H[3]; // Computation a = MD5.FF(a, b, c, d, M_offset_0, 7, T[0]); d = MD5.FF(d, a, b, c, M_offset_1, 12, T[1]); c = MD5.FF(c, d, a, b, M_offset_2, 17, T[2]); b = MD5.FF(b, c, d, a, M_offset_3, 22, T[3]); a = MD5.FF(a, b, c, d, M_offset_4, 7, T[4]); d = MD5.FF(d, a, b, c, M_offset_5, 12, T[5]); c = MD5.FF(c, d, a, b, M_offset_6, 17, T[6]); b = MD5.FF(b, c, d, a, M_offset_7, 22, T[7]); a = MD5.FF(a, b, c, d, M_offset_8, 7, T[8]); d = MD5.FF(d, a, b, c, M_offset_9, 12, T[9]); c = MD5.FF(c, d, a, b, M_offset_10, 17, T[10]); b = MD5.FF(b, c, d, a, M_offset_11, 22, T[11]); a = MD5.FF(a, b, c, d, M_offset_12, 7, T[12]); d = MD5.FF(d, a, b, c, M_offset_13, 12, T[13]); c = MD5.FF(c, d, a, b, M_offset_14, 17, T[14]); b = MD5.FF(b, c, d, a, M_offset_15, 22, T[15]); a = MD5.GG(a, b, c, d, M_offset_1, 5, T[16]); d = MD5.GG(d, a, b, c, M_offset_6, 9, T[17]); c = MD5.GG(c, d, a, b, M_offset_11, 14, T[18]); b = MD5.GG(b, c, d, a, M_offset_0, 20, T[19]); a = MD5.GG(a, b, c, d, M_offset_5, 5, T[20]); d = MD5.GG(d, a, b, c, M_offset_10, 9, T[21]); c = MD5.GG(c, d, a, b, M_offset_15, 14, T[22]); b = MD5.GG(b, c, d, a, M_offset_4, 20, T[23]); a = MD5.GG(a, b, c, d, M_offset_9, 5, T[24]); d = MD5.GG(d, a, b, c, M_offset_14, 9, T[25]); c = MD5.GG(c, d, a, b, M_offset_3, 14, T[26]); b = MD5.GG(b, c, d, a, M_offset_8, 20, T[27]); a = MD5.GG(a, b, c, d, M_offset_13, 5, T[28]); d = MD5.GG(d, a, b, c, M_offset_2, 9, T[29]); c = MD5.GG(c, d, a, b, M_offset_7, 14, T[30]); b = MD5.GG(b, c, d, a, M_offset_12, 20, T[31]); a = MD5.HH(a, b, c, d, M_offset_5, 4, T[32]); d = MD5.HH(d, a, b, c, M_offset_8, 11, T[33]); c = MD5.HH(c, d, a, b, M_offset_11, 16, T[34]); b = MD5.HH(b, c, d, a, M_offset_14, 23, T[35]); a = MD5.HH(a, b, c, d, M_offset_1, 4, T[36]); d = MD5.HH(d, a, b, c, M_offset_4, 11, T[37]); c = MD5.HH(c, d, a, b, M_offset_7, 16, T[38]); b = MD5.HH(b, c, d, a, M_offset_10, 23, T[39]); a = MD5.HH(a, b, c, d, M_offset_13, 4, T[40]); d = MD5.HH(d, a, b, c, M_offset_0, 11, T[41]); c = MD5.HH(c, d, a, b, M_offset_3, 16, T[42]); b = MD5.HH(b, c, d, a, M_offset_6, 23, T[43]); a = MD5.HH(a, b, c, d, M_offset_9, 4, T[44]); d = MD5.HH(d, a, b, c, M_offset_12, 11, T[45]); c = MD5.HH(c, d, a, b, M_offset_15, 16, T[46]); b = MD5.HH(b, c, d, a, M_offset_2, 23, T[47]); a = MD5.II(a, b, c, d, M_offset_0, 6, T[48]); d = MD5.II(d, a, b, c, M_offset_7, 10, T[49]); c = MD5.II(c, d, a, b, M_offset_14, 15, T[50]); b = MD5.II(b, c, d, a, M_offset_5, 21, T[51]); a = MD5.II(a, b, c, d, M_offset_12, 6, T[52]); d = MD5.II(d, a, b, c, M_offset_3, 10, T[53]); c = MD5.II(c, d, a, b, M_offset_10, 15, T[54]); b = MD5.II(b, c, d, a, M_offset_1, 21, T[55]); a = MD5.II(a, b, c, d, M_offset_8, 6, T[56]); d = MD5.II(d, a, b, c, M_offset_15, 10, T[57]); c = MD5.II(c, d, a, b, M_offset_6, 15, T[58]); b = MD5.II(b, c, d, a, M_offset_13, 21, T[59]); a = MD5.II(a, b, c, d, M_offset_4, 6, T[60]); d = MD5.II(d, a, b, c, M_offset_11, 10, T[61]); c = MD5.II(c, d, a, b, M_offset_2, 15, T[62]); b = MD5.II(b, c, d, a, M_offset_9, 21, T[63]); // Intermediate hash value H[0] = (H[0] + a) | 0; H[1] = (H[1] + b) | 0; H[2] = (H[2] + c) | 0; H[3] = (H[3] + d) | 0; } /** * @return {?} */ _doFinalize() { // Shortcuts const /** @type {?} */ data = this._data; const /** @type {?} */ dataWords = data.words; const /** @type {?} */ nBitsTotal = this._nDataBytes * 8; const /** @type {?} */ nBitsLeft = data.sigBytes * 8; // Add padding dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); const /** @type {?} */ nBitsTotalH = Math.floor(nBitsTotal / 0x100000000); const /** @type {?} */ nBitsTotalL = nBitsTotal; dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = ((((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) | (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00)); dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ((((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) | (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00)); data.sigBytes = (dataWords.length + 1) * 4; // Hash final blocks this._process(); // Shortcuts const /** @type {?} */ hash = this._hash; const /** @type {?} */ H = hash.words; // Swap endian for (let /** @type {?} */ i = 0; i < 4; i++) { // Shortcut const /** @type {?} */ H_i = H[i]; H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); } // Return final computed hash return hash; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class EvpKDF { /** * Initializes a newly created key derivation function. * * \@example * * let kdf = EvpKDF.create(); * let kdf = EvpKDF.create({ keySize: 8 }); * let kdf = EvpKDF.create({ keySize: 8, iterations: 1000 }); * @param {?=} cfg (Optional) The configuration options to use for the derivation. * */ constructor(cfg) { this.cfg = Object.assign({ keySize: 128 / 32, hasher: MD5, iterations: 1 }, cfg); } /** * Derives a key from a password. * * \@example * * let key = kdf.compute(password, salt); * @param {?} password The password. * @param {?} salt A salt. * * @return {?} The derived key. * */ compute(password, salt) { // Init hasher const /** @type {?} */ hasher = new (/** @type {?} */ (this.cfg.hasher))(); // Initial values const /** @type {?} */ derivedKey = new WordArray(); // Generate key let /** @type {?} */ block; while (derivedKey.words.length < this.cfg.keySize) { if (block) { hasher.update(block); } block = hasher.update(password).finalize(salt); hasher.reset(); // Iterations for (let /** @type {?} */ i = 1; i < this.cfg.iterations; i++) { block = hasher.finalize(block); hasher.reset(); } derivedKey.concat(block); } derivedKey.sigBytes = this.cfg.keySize * 4; return derivedKey; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class OpenSSLKdf { /** * Derives a key and IV from a password. * * \@example * * let derivedParams = OpenSSL.execute('Password', 256/32, 128/32); * let derivedParams = OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt'); * @param {?} password The password to derive from. * @param {?} keySize The size in words of the key to generate. * @param {?} ivSize The size in words of the IV to generate. * @param {?=} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly. * * @return {?} A cipher params object with the key, IV, and salt. * */ static execute(password, keySize, ivSize, salt) { // Generate random salt if (!salt) { salt = WordArray.random(64 / 8); } // Derive key and IV const /** @type {?} */ key = (new EvpKDF({ keySize: keySize + ivSize })).compute(password, salt); // Separate key and IV const /** @type {?} */ iv = new WordArray(key.words.slice(keySize), ivSize * 4); key.sigBytes = keySize * 4; // Return params return new CipherParams({ key: key, iv: iv, salt: salt }); } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class PasswordBasedCipher { /** * Encrypts a message using a password. * * \@example * * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(AES, message, 'password'); * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(AES, message, 'password', { format: OpenSSL }); * @param {?} cipher The cipher algorithm to use. * @param {?} message The message to encrypt. * @param {?} password The password. * @param {?=} cfg (Optional) The configuration options to use for this operation. * * @return {?} A cipher params object. * */ static encrypt(cipher, message, password, cfg) { // Apply config defaults const /** @type {?} */ config = Object.assign({}, this.cfg, cfg); // Check if we have a kdf if (config.kdf === undefined) { throw new Error('missing kdf in config'); } // Derive key and other params const /** @type {?} */ derivedParams = config.kdf.execute(password, cipher.keySize, cipher.ivSize); // Check if we have an IV if (derivedParams.iv !== undefined) { // Add IV to config config.iv = derivedParams.iv; } // Encrypt const /** @type {?} */ ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, config); // Mix in derived params return ciphertext.extend(derivedParams); } /** * Decrypts serialized ciphertext using a password. * * \@example * * var plaintext = PasswordBasedCipher.decrypt(AES, formattedCiphertext, 'password', { format: OpenSSL }); * var plaintext = PasswordBasedCipher.decrypt(AES, ciphertextParams, 'password', { format: OpenSSL }); * @param {?} cipher The cipher algorithm to use. * @param {?} ciphertext The ciphertext to decrypt. * @param {?} password The password. * @param {?=} cfg (Optional) The configuration options to use for this operation. * * @return {?} The plaintext. * */ static decrypt(cipher, ciphertext, password, cfg) { // Apply config defaults const /** @type {?} */ config = Object.assign({}, this.cfg, cfg); // Check if we have a kdf if (config.format === undefined) { throw new Error('missing format in config'); } // Convert string to CipherParams ciphertext = this._parse(ciphertext, config.format); // Check if we have a kdf if (config.kdf === undefined) { throw new Error('the key derivation function must be set'); } // Derive key and other params const /** @type {?} */ derivedParams = config.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt); // Check if we have an IV if (derivedParams.iv !== undefined) { // Add IV to config config.iv = derivedParams.iv; } // Decrypt const /** @type {?} */ plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, config); return plaintext; } /** * Converts serialized ciphertext to CipherParams, * else assumed CipherParams already and returns ciphertext unchanged. * * \@example * * var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format); * @param {?} ciphertext The ciphertext. * @param {?} format The formatting strategy to use to parse serialized ciphertext. * * @return {?} The unserialized ciphertext. * */ static _parse(ciphertext, format) { if (typeof ciphertext === 'string') { return format.parse(ciphertext); } else { return ciphertext; } } } PasswordBasedCipher.cfg = { blockSize: 4, iv: new WordArray([]), format: OpenSSL, kdf: OpenSSLKdf }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @abstract */ class Cipher extends BufferedBlockAlgorithm { /** * Initializes a newly created cipher. * * \@example * * let cipher = AES.create(AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray }); * @param {?} xformMode Either the encryption or decryption transormation mode constant. * @param {?} key The key. * @param {?=} cfg (Optional) The configuration options to use for this operation. * */ constructor(xformMode, key, cfg) { // Apply config defaults super(Object.assign({ blockSize: 1 }, cfg)); // Store transform mode and key this._xformMode = xformMode; this._key = key; // Set initial values this.reset(); } /** * Creates this cipher in encryption mode. * * \@example * * let cipher = AES.createEncryptor(keyWordArray, { iv: ivWordArray }); * @param {?} key The key. * @param {?=} cfg (Optional) The configuration options to use for this operation. * * @return {?} A cipher instance. * */ static createEncryptor(key, cfg) { // workaround for typescript not being able to create a abstract creator function directly const /** @type {?} */ thisClass = this; return new thisClass(this._ENC_XFORM_MODE, key, cfg); } /** * Creates this cipher in decryption mode. * * \@example * * let cipher = AES.createDecryptor(keyWordArray, { iv: ivWordArray }); * @param {?} key The key. * @param {?=} cfg (Optional) The configuration options to use for this operation. * * @return {?} A cipher instance. * */ static createDecryptor(key, cfg) { // workaround for typescript not being able to create a abstract creator function directly const /** @type {?} */ thisClass = this; return new thisClass(this._DEC_XFORM_MODE, key, cfg); } /** * Creates shortcut functions to a cipher's object interface. * * \@example * * let AES = Cipher._createHelper(AESAlgorithm); * @param {?} cipher The cipher to create a helper for. * * @return {?} An object with encrypt and decrypt shortcut functions. * */ static _createHelper(cipher) { /** * @param {?} message * @param {?} key * @param {?=} cfg * @return {?} */ function encrypt(message, key, cfg) { if (typeof key === 'string') { return PasswordBasedCipher.encrypt(cipher, message, key, cfg); } else { return SerializableCipher.encrypt(cipher, message, key, cfg); } } /** * @param {?} ciphertext * @param {?} key * @param {?=} cfg * @return {?} */ function decrypt(ciphertext, key, cfg) { if (typeof key === 'string') { return PasswordBasedCipher.decrypt(cipher, ciphertext, key, cfg); } else { return SerializableCipher.decrypt(cipher, ciphertext, key, cfg); } } return { encrypt: encrypt, decrypt: decrypt }; } /** * Adds data to be encrypted or decrypted. * * \@example * * let encrypted = cipher.process('data'); * let encrypted = cipher.process(wordArray); * @param {?} dataUpdate The data to encrypt or decrypt. * * @return {?} The data after processing. * */ process(dataUpdate) { // Append this._append(dataUpdate); // Process available blocks return this._process(); } /** * Finalizes the encryption or decryption process. * Note that the finalize operation is effectively a destructive, read-once operation. * * \@example * * var encrypted = cipher.finalize(); * var encrypted = cipher.finalize('data'); * var encrypted = cipher.finalize(wordArray); * @param {?=} dataUpdate The final data to encrypt or decrypt. * * @return {?} The data after final processing. * */ finalize(dataUpdate) { // Final data update if (dataUpdate) { this._append(dataUpdate); } // Perform concrete-cipher logic const /** @type {?} */ finalProcessedData = this._doFinalize(); return finalProcessedData; } } /** * A constant representing encryption mode. */ Cipher._ENC_XFORM_MODE = 1; /** * A constant representing decryption mode. */ Cipher._DEC_XFORM_MODE = 2; /** * This cipher's key size. Default: 4 (128 bits / 32 Bits) */ Cipher.keySize = 4; /** * This cipher's IV size. Default: 4 (128 bits / 32 Bits) */ Cipher.ivSize = 4; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @abstract */ class BlockCipherModeAlgorithm { /** * @param {?} cipher * @param {?} iv */ constructor(cipher, iv) { this.init(cipher, iv); } /** * Initializes a newly created mode. * * \@example * * var mode = CBC.Encryptor.create(cipher, iv.words); * @param {?} cipher A block cipher instance. * @param {?=} iv The IV words. * * @return {?} */ init(cipher, iv) { this._cipher = cipher; this._iv = iv; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @abstract */ class BlockCipherMode { /** * Creates this mode for encryption. * * \@example * * var mode = CBC.createEncryptor(cipher, iv.words); * @param {?} cipher A block cipher instance. * @param {?} iv The IV words. * * @return {?} */ static createEncryptor(cipher, iv) { // workaround for typescript not being able to create a abstract creator function directly const /** @type {?} */ encryptorClass = this.Encryptor; return new encryptorClass(cipher, iv); } /** * Creates this mode for decryption. * * \@example * * var mode = CBC.createDecryptor(cipher, iv.words); * @param {?} cipher A block cipher instance. * @param {?} iv The IV words. * * @return {?} */ static createDecryptor(cipher, iv) { // workaround for typescript not being able to create a abstract creator function directly const /** @type {?} */ decryptorClass = this.Decryptor; return new decryptorClass(cipher, iv); } } BlockCipherMode.Encryptor = BlockCipherModeAlgorithm; BlockCipherMode.Decryptor = BlockCipherModeAlgorithm; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class CBCEncryptor extends BlockCipherModeAlgorithm { /** * Processes the data block at offset. * * \@example * * mode.processBlock(data.words, offset); * @param {?} words The data words to operate on. * @param {?} offset The offset where the block starts. * * @return {?} */ processBlock(words, offset) { // Check if we have a blockSize if (this._cipher.cfg.blockSize === undefined) { throw new Error('missing blockSize in cipher config'); } // XOR and encrypt this.xorBlock(words, offset, this._cipher.cfg.blockSize); this._cipher.encryptBlock(words, offset);