;(function (root, factory, undef) { 
 | 
    if (typeof exports === "object") { 
 | 
        // CommonJS 
 | 
        module.exports = exports = factory(require("./core"), require("./evpkdf")); 
 | 
    } 
 | 
    else if (typeof define === "function" && define.amd) { 
 | 
        // AMD 
 | 
        define(["./core", "./evpkdf"], factory); 
 | 
    } 
 | 
    else { 
 | 
        // Global (browser) 
 | 
        factory(root.CryptoJS); 
 | 
    } 
 | 
}(this, function (CryptoJS) { 
 | 
  
 | 
    /** 
 | 
     * Cipher core components. 
 | 
     */ 
 | 
    CryptoJS.lib.Cipher || (function (undefined) { 
 | 
        // Shortcuts 
 | 
        var C = CryptoJS; 
 | 
        var C_lib = C.lib; 
 | 
        var Base = C_lib.Base; 
 | 
        var WordArray = C_lib.WordArray; 
 | 
        var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm; 
 | 
        var C_enc = C.enc; 
 | 
        var Utf8 = C_enc.Utf8; 
 | 
        var Base64 = C_enc.Base64; 
 | 
        var C_algo = C.algo; 
 | 
        var EvpKDF = C_algo.EvpKDF; 
 | 
  
 | 
        /** 
 | 
         * Abstract base cipher template. 
 | 
         * 
 | 
         * @property {number} keySize This cipher's key size. Default: 4 (128 bits) 
 | 
         * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits) 
 | 
         * @property {number} _ENC_XFORM_MODE A constant representing encryption mode. 
 | 
         * @property {number} _DEC_XFORM_MODE A constant representing decryption mode. 
 | 
         */ 
 | 
        var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({ 
 | 
            /** 
 | 
             * Configuration options. 
 | 
             * 
 | 
             * @property {WordArray} iv The IV to use for this operation. 
 | 
             */ 
 | 
            cfg: Base.extend(), 
 | 
  
 | 
            /** 
 | 
             * Creates this cipher in encryption mode. 
 | 
             * 
 | 
             * @param {WordArray} key The key. 
 | 
             * @param {Object} cfg (Optional) The configuration options to use for this operation. 
 | 
             * 
 | 
             * @return {Cipher} A cipher instance. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray }); 
 | 
             */ 
 | 
            createEncryptor: function (key, cfg) { 
 | 
                return this.create(this._ENC_XFORM_MODE, key, cfg); 
 | 
            }, 
 | 
  
 | 
            /** 
 | 
             * Creates this cipher in decryption mode. 
 | 
             * 
 | 
             * @param {WordArray} key The key. 
 | 
             * @param {Object} cfg (Optional) The configuration options to use for this operation. 
 | 
             * 
 | 
             * @return {Cipher} A cipher instance. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray }); 
 | 
             */ 
 | 
            createDecryptor: function (key, cfg) { 
 | 
                return this.create(this._DEC_XFORM_MODE, key, cfg); 
 | 
            }, 
 | 
  
 | 
            /** 
 | 
             * Initializes a newly created cipher. 
 | 
             * 
 | 
             * @param {number} xformMode Either the encryption or decryption transormation mode constant. 
 | 
             * @param {WordArray} key The key. 
 | 
             * @param {Object} cfg (Optional) The configuration options to use for this operation. 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray }); 
 | 
             */ 
 | 
            init: function (xformMode, key, cfg) { 
 | 
                // Apply config defaults 
 | 
                this.cfg = this.cfg.extend(cfg); 
 | 
  
 | 
                // Store transform mode and key 
 | 
                this._xformMode = xformMode; 
 | 
                this._key = key; 
 | 
  
 | 
                // Set initial values 
 | 
                this.reset(); 
 | 
            }, 
 | 
  
 | 
            /** 
 | 
             * Resets this cipher to its initial state. 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     cipher.reset(); 
 | 
             */ 
 | 
            reset: function () { 
 | 
                // Reset data buffer 
 | 
                BufferedBlockAlgorithm.reset.call(this); 
 | 
  
 | 
                // Perform concrete-cipher logic 
 | 
                this._doReset(); 
 | 
            }, 
 | 
  
 | 
            /** 
 | 
             * Adds data to be encrypted or decrypted. 
 | 
             * 
 | 
             * @param {WordArray|string} dataUpdate The data to encrypt or decrypt. 
 | 
             * 
 | 
             * @return {WordArray} The data after processing. 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var encrypted = cipher.process('data'); 
 | 
             *     var encrypted = cipher.process(wordArray); 
 | 
             */ 
 | 
            process: function (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. 
 | 
             * 
 | 
             * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt. 
 | 
             * 
 | 
             * @return {WordArray} The data after final processing. 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var encrypted = cipher.finalize(); 
 | 
             *     var encrypted = cipher.finalize('data'); 
 | 
             *     var encrypted = cipher.finalize(wordArray); 
 | 
             */ 
 | 
            finalize: function (dataUpdate) { 
 | 
                // Final data update 
 | 
                if (dataUpdate) { 
 | 
                    this._append(dataUpdate); 
 | 
                } 
 | 
  
 | 
                // Perform concrete-cipher logic 
 | 
                var finalProcessedData = this._doFinalize(); 
 | 
  
 | 
                return finalProcessedData; 
 | 
            }, 
 | 
  
 | 
            keySize: 128/32, 
 | 
  
 | 
            ivSize: 128/32, 
 | 
  
 | 
            _ENC_XFORM_MODE: 1, 
 | 
  
 | 
            _DEC_XFORM_MODE: 2, 
 | 
  
 | 
            /** 
 | 
             * Creates shortcut functions to a cipher's object interface. 
 | 
             * 
 | 
             * @param {Cipher} cipher The cipher to create a helper for. 
 | 
             * 
 | 
             * @return {Object} An object with encrypt and decrypt shortcut functions. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES); 
 | 
             */ 
 | 
            _createHelper: (function () { 
 | 
                function selectCipherStrategy(key) { 
 | 
                    if (typeof key == 'string') { 
 | 
                        return PasswordBasedCipher; 
 | 
                    } else { 
 | 
                        return SerializableCipher; 
 | 
                    } 
 | 
                } 
 | 
  
 | 
                return function (cipher) { 
 | 
                    return { 
 | 
                        encrypt: function (message, key, cfg) { 
 | 
                            return selectCipherStrategy(key).encrypt(cipher, message, key, cfg); 
 | 
                        }, 
 | 
  
 | 
                        decrypt: function (ciphertext, key, cfg) { 
 | 
                            return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg); 
 | 
                        } 
 | 
                    }; 
 | 
                }; 
 | 
            }()) 
 | 
        }); 
 | 
  
 | 
        /** 
 | 
         * Abstract base stream cipher template. 
 | 
         * 
 | 
         * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits) 
 | 
         */ 
 | 
        var StreamCipher = C_lib.StreamCipher = Cipher.extend({ 
 | 
            _doFinalize: function () { 
 | 
                // Process partial blocks 
 | 
                var finalProcessedBlocks = this._process(!!'flush'); 
 | 
  
 | 
                return finalProcessedBlocks; 
 | 
            }, 
 | 
  
 | 
            blockSize: 1 
 | 
        }); 
 | 
  
 | 
        /** 
 | 
         * Mode namespace. 
 | 
         */ 
 | 
        var C_mode = C.mode = {}; 
 | 
  
 | 
        /** 
 | 
         * Abstract base block cipher mode template. 
 | 
         */ 
 | 
        var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({ 
 | 
            /** 
 | 
             * Creates this mode for encryption. 
 | 
             * 
 | 
             * @param {Cipher} cipher A block cipher instance. 
 | 
             * @param {Array} iv The IV words. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words); 
 | 
             */ 
 | 
            createEncryptor: function (cipher, iv) { 
 | 
                return this.Encryptor.create(cipher, iv); 
 | 
            }, 
 | 
  
 | 
            /** 
 | 
             * Creates this mode for decryption. 
 | 
             * 
 | 
             * @param {Cipher} cipher A block cipher instance. 
 | 
             * @param {Array} iv The IV words. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words); 
 | 
             */ 
 | 
            createDecryptor: function (cipher, iv) { 
 | 
                return this.Decryptor.create(cipher, iv); 
 | 
            }, 
 | 
  
 | 
            /** 
 | 
             * Initializes a newly created mode. 
 | 
             * 
 | 
             * @param {Cipher} cipher A block cipher instance. 
 | 
             * @param {Array} iv The IV words. 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words); 
 | 
             */ 
 | 
            init: function (cipher, iv) { 
 | 
                this._cipher = cipher; 
 | 
                this._iv = iv; 
 | 
            } 
 | 
        }); 
 | 
  
 | 
        /** 
 | 
         * Cipher Block Chaining mode. 
 | 
         */ 
 | 
        var CBC = C_mode.CBC = (function () { 
 | 
            /** 
 | 
             * Abstract base CBC mode. 
 | 
             */ 
 | 
            var CBC = BlockCipherMode.extend(); 
 | 
  
 | 
            /** 
 | 
             * CBC encryptor. 
 | 
             */ 
 | 
            CBC.Encryptor = CBC.extend({ 
 | 
                /** 
 | 
                 * Processes the data block at offset. 
 | 
                 * 
 | 
                 * @param {Array} words The data words to operate on. 
 | 
                 * @param {number} offset The offset where the block starts. 
 | 
                 * 
 | 
                 * @example 
 | 
                 * 
 | 
                 *     mode.processBlock(data.words, offset); 
 | 
                 */ 
 | 
                processBlock: function (words, offset) { 
 | 
                    // Shortcuts 
 | 
                    var cipher = this._cipher; 
 | 
                    var blockSize = cipher.blockSize; 
 | 
  
 | 
                    // XOR and encrypt 
 | 
                    xorBlock.call(this, words, offset, blockSize); 
 | 
                    cipher.encryptBlock(words, offset); 
 | 
  
 | 
                    // Remember this block to use with next block 
 | 
                    this._prevBlock = words.slice(offset, offset + blockSize); 
 | 
                } 
 | 
            }); 
 | 
  
 | 
            /** 
 | 
             * CBC decryptor. 
 | 
             */ 
 | 
            CBC.Decryptor = CBC.extend({ 
 | 
                /** 
 | 
                 * Processes the data block at offset. 
 | 
                 * 
 | 
                 * @param {Array} words The data words to operate on. 
 | 
                 * @param {number} offset The offset where the block starts. 
 | 
                 * 
 | 
                 * @example 
 | 
                 * 
 | 
                 *     mode.processBlock(data.words, offset); 
 | 
                 */ 
 | 
                processBlock: function (words, offset) { 
 | 
                    // Shortcuts 
 | 
                    var cipher = this._cipher; 
 | 
                    var blockSize = cipher.blockSize; 
 | 
  
 | 
                    // Remember this block to use with next block 
 | 
                    var thisBlock = words.slice(offset, offset + blockSize); 
 | 
  
 | 
                    // Decrypt and XOR 
 | 
                    cipher.decryptBlock(words, offset); 
 | 
                    xorBlock.call(this, words, offset, blockSize); 
 | 
  
 | 
                    // This block becomes the previous block 
 | 
                    this._prevBlock = thisBlock; 
 | 
                } 
 | 
            }); 
 | 
  
 | 
            function xorBlock(words, offset, blockSize) { 
 | 
                var block; 
 | 
  
 | 
                // Shortcut 
 | 
                var iv = this._iv; 
 | 
  
 | 
                // Choose mixing block 
 | 
                if (iv) { 
 | 
                    block = iv; 
 | 
  
 | 
                    // Remove IV for subsequent blocks 
 | 
                    this._iv = undefined; 
 | 
                } else { 
 | 
                    block = this._prevBlock; 
 | 
                } 
 | 
  
 | 
                // XOR blocks 
 | 
                for (var i = 0; i < blockSize; i++) { 
 | 
                    words[offset + i] ^= block[i]; 
 | 
                } 
 | 
            } 
 | 
  
 | 
            return CBC; 
 | 
        }()); 
 | 
  
 | 
        /** 
 | 
         * Padding namespace. 
 | 
         */ 
 | 
        var C_pad = C.pad = {}; 
 | 
  
 | 
        /** 
 | 
         * PKCS #5/7 padding strategy. 
 | 
         */ 
 | 
        var Pkcs7 = C_pad.Pkcs7 = { 
 | 
            /** 
 | 
             * Pads data using the algorithm defined in PKCS #5/7. 
 | 
             * 
 | 
             * @param {WordArray} data The data to pad. 
 | 
             * @param {number} blockSize The multiple that the data should be padded to. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     CryptoJS.pad.Pkcs7.pad(wordArray, 4); 
 | 
             */ 
 | 
            pad: function (data, blockSize) { 
 | 
                // Shortcut 
 | 
                var blockSizeBytes = blockSize * 4; 
 | 
  
 | 
                // Count padding bytes 
 | 
                var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; 
 | 
  
 | 
                // Create padding word 
 | 
                var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes; 
 | 
  
 | 
                // Create padding 
 | 
                var paddingWords = []; 
 | 
                for (var i = 0; i < nPaddingBytes; i += 4) { 
 | 
                    paddingWords.push(paddingWord); 
 | 
                } 
 | 
                var padding = WordArray.create(paddingWords, nPaddingBytes); 
 | 
  
 | 
                // Add padding 
 | 
                data.concat(padding); 
 | 
            }, 
 | 
  
 | 
            /** 
 | 
             * Unpads data that had been padded using the algorithm defined in PKCS #5/7. 
 | 
             * 
 | 
             * @param {WordArray} data The data to unpad. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     CryptoJS.pad.Pkcs7.unpad(wordArray); 
 | 
             */ 
 | 
            unpad: function (data) { 
 | 
                // Get number of padding bytes from last byte 
 | 
                var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; 
 | 
  
 | 
                // Remove padding 
 | 
                data.sigBytes -= nPaddingBytes; 
 | 
            } 
 | 
        }; 
 | 
  
 | 
        /** 
 | 
         * Abstract base block cipher template. 
 | 
         * 
 | 
         * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits) 
 | 
         */ 
 | 
        var BlockCipher = C_lib.BlockCipher = Cipher.extend({ 
 | 
            /** 
 | 
             * Configuration options. 
 | 
             * 
 | 
             * @property {Mode} mode The block mode to use. Default: CBC 
 | 
             * @property {Padding} padding The padding strategy to use. Default: Pkcs7 
 | 
             */ 
 | 
            cfg: Cipher.cfg.extend({ 
 | 
                mode: CBC, 
 | 
                padding: Pkcs7 
 | 
            }), 
 | 
  
 | 
            reset: function () { 
 | 
                var modeCreator; 
 | 
  
 | 
                // Reset cipher 
 | 
                Cipher.reset.call(this); 
 | 
  
 | 
                // Shortcuts 
 | 
                var cfg = this.cfg; 
 | 
                var iv = cfg.iv; 
 | 
                var mode = cfg.mode; 
 | 
  
 | 
                // Reset block mode 
 | 
                if (this._xformMode == this._ENC_XFORM_MODE) { 
 | 
                    modeCreator = mode.createEncryptor; 
 | 
                } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { 
 | 
                    modeCreator = mode.createDecryptor; 
 | 
                    // Keep at least one block in the buffer for unpadding 
 | 
                    this._minBufferSize = 1; 
 | 
                } 
 | 
  
 | 
                if (this._mode && this._mode.__creator == modeCreator) { 
 | 
                    this._mode.init(this, iv && iv.words); 
 | 
                } else { 
 | 
                    this._mode = modeCreator.call(mode, this, iv && iv.words); 
 | 
                    this._mode.__creator = modeCreator; 
 | 
                } 
 | 
            }, 
 | 
  
 | 
            _doProcessBlock: function (words, offset) { 
 | 
                this._mode.processBlock(words, offset); 
 | 
            }, 
 | 
  
 | 
            _doFinalize: function () { 
 | 
                var finalProcessedBlocks; 
 | 
  
 | 
                // Shortcut 
 | 
                var padding = this.cfg.padding; 
 | 
  
 | 
                // Finalize 
 | 
                if (this._xformMode == this._ENC_XFORM_MODE) { 
 | 
                    // Pad data 
 | 
                    padding.pad(this._data, this.blockSize); 
 | 
  
 | 
                    // Process final blocks 
 | 
                    finalProcessedBlocks = this._process(!!'flush'); 
 | 
                } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { 
 | 
                    // Process final blocks 
 | 
                    finalProcessedBlocks = this._process(!!'flush'); 
 | 
  
 | 
                    // Unpad data 
 | 
                    padding.unpad(finalProcessedBlocks); 
 | 
                } 
 | 
  
 | 
                return finalProcessedBlocks; 
 | 
            }, 
 | 
  
 | 
            blockSize: 128/32 
 | 
        }); 
 | 
  
 | 
        /** 
 | 
         * A collection of cipher parameters. 
 | 
         * 
 | 
         * @property {WordArray} ciphertext The raw ciphertext. 
 | 
         * @property {WordArray} key The key to this ciphertext. 
 | 
         * @property {WordArray} iv The IV used in the ciphering operation. 
 | 
         * @property {WordArray} salt The salt used with a key derivation function. 
 | 
         * @property {Cipher} algorithm The cipher algorithm. 
 | 
         * @property {Mode} mode The block mode used in the ciphering operation. 
 | 
         * @property {Padding} padding The padding scheme used in the ciphering operation. 
 | 
         * @property {number} blockSize The block size of the cipher. 
 | 
         * @property {Format} formatter The default formatting strategy to convert this cipher params object to a string. 
 | 
         */ 
 | 
        var CipherParams = C_lib.CipherParams = Base.extend({ 
 | 
            /** 
 | 
             * Initializes a newly created cipher params object. 
 | 
             * 
 | 
             * @param {Object} cipherParams An object with any of the possible cipher parameters. 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var cipherParams = CryptoJS.lib.CipherParams.create({ 
 | 
             *         ciphertext: ciphertextWordArray, 
 | 
             *         key: keyWordArray, 
 | 
             *         iv: ivWordArray, 
 | 
             *         salt: saltWordArray, 
 | 
             *         algorithm: CryptoJS.algo.AES, 
 | 
             *         mode: CryptoJS.mode.CBC, 
 | 
             *         padding: CryptoJS.pad.PKCS7, 
 | 
             *         blockSize: 4, 
 | 
             *         formatter: CryptoJS.format.OpenSSL 
 | 
             *     }); 
 | 
             */ 
 | 
            init: function (cipherParams) { 
 | 
                this.mixIn(cipherParams); 
 | 
            }, 
 | 
  
 | 
            /** 
 | 
             * Converts this cipher params object to a string. 
 | 
             * 
 | 
             * @param {Format} formatter (Optional) The formatting strategy to use. 
 | 
             * 
 | 
             * @return {string} The stringified cipher params. 
 | 
             * 
 | 
             * @throws Error If neither the formatter nor the default formatter is set. 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var string = cipherParams + ''; 
 | 
             *     var string = cipherParams.toString(); 
 | 
             *     var string = cipherParams.toString(CryptoJS.format.OpenSSL); 
 | 
             */ 
 | 
            toString: function (formatter) { 
 | 
                return (formatter || this.formatter).stringify(this); 
 | 
            } 
 | 
        }); 
 | 
  
 | 
        /** 
 | 
         * Format namespace. 
 | 
         */ 
 | 
        var C_format = C.format = {}; 
 | 
  
 | 
        /** 
 | 
         * OpenSSL formatting strategy. 
 | 
         */ 
 | 
        var OpenSSLFormatter = C_format.OpenSSL = { 
 | 
            /** 
 | 
             * Converts a cipher params object to an OpenSSL-compatible string. 
 | 
             * 
 | 
             * @param {CipherParams} cipherParams The cipher params object. 
 | 
             * 
 | 
             * @return {string} The OpenSSL-compatible string. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams); 
 | 
             */ 
 | 
            stringify: function (cipherParams) { 
 | 
                var wordArray; 
 | 
  
 | 
                // Shortcuts 
 | 
                var ciphertext = cipherParams.ciphertext; 
 | 
                var salt = cipherParams.salt; 
 | 
  
 | 
                // Format 
 | 
                if (salt) { 
 | 
                    wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext); 
 | 
                } else { 
 | 
                    wordArray = ciphertext; 
 | 
                } 
 | 
  
 | 
                return wordArray.toString(Base64); 
 | 
            }, 
 | 
  
 | 
            /** 
 | 
             * Converts an OpenSSL-compatible string to a cipher params object. 
 | 
             * 
 | 
             * @param {string} openSSLStr The OpenSSL-compatible string. 
 | 
             * 
 | 
             * @return {CipherParams} The cipher params object. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString); 
 | 
             */ 
 | 
            parse: function (openSSLStr) { 
 | 
                var salt; 
 | 
  
 | 
                // Parse base64 
 | 
                var ciphertext = Base64.parse(openSSLStr); 
 | 
  
 | 
                // Shortcut 
 | 
                var ciphertextWords = ciphertext.words; 
 | 
  
 | 
                // Test for salt 
 | 
                if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) { 
 | 
                    // Extract salt 
 | 
                    salt = WordArray.create(ciphertextWords.slice(2, 4)); 
 | 
  
 | 
                    // Remove salt from ciphertext 
 | 
                    ciphertextWords.splice(0, 4); 
 | 
                    ciphertext.sigBytes -= 16; 
 | 
                } 
 | 
  
 | 
                return CipherParams.create({ ciphertext: ciphertext, salt: salt }); 
 | 
            } 
 | 
        }; 
 | 
  
 | 
        /** 
 | 
         * A cipher wrapper that returns ciphertext as a serializable cipher params object. 
 | 
         */ 
 | 
        var SerializableCipher = C_lib.SerializableCipher = Base.extend({ 
 | 
            /** 
 | 
             * Configuration options. 
 | 
             * 
 | 
             * @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL 
 | 
             */ 
 | 
            cfg: Base.extend({ 
 | 
                format: OpenSSLFormatter 
 | 
            }), 
 | 
  
 | 
            /** 
 | 
             * Encrypts a message. 
 | 
             * 
 | 
             * @param {Cipher} cipher The cipher algorithm to use. 
 | 
             * @param {WordArray|string} message The message to encrypt. 
 | 
             * @param {WordArray} key The key. 
 | 
             * @param {Object} cfg (Optional) The configuration options to use for this operation. 
 | 
             * 
 | 
             * @return {CipherParams} A cipher params object. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key); 
 | 
             *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv }); 
 | 
             *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL }); 
 | 
             */ 
 | 
            encrypt: function (cipher, message, key, cfg) { 
 | 
                // Apply config defaults 
 | 
                cfg = this.cfg.extend(cfg); 
 | 
  
 | 
                // Encrypt 
 | 
                var encryptor = cipher.createEncryptor(key, cfg); 
 | 
                var ciphertext = encryptor.finalize(message); 
 | 
  
 | 
                // Shortcut 
 | 
                var cipherCfg = encryptor.cfg; 
 | 
  
 | 
                // Create and return serializable cipher params 
 | 
                return CipherParams.create({ 
 | 
                    ciphertext: ciphertext, 
 | 
                    key: key, 
 | 
                    iv: cipherCfg.iv, 
 | 
                    algorithm: cipher, 
 | 
                    mode: cipherCfg.mode, 
 | 
                    padding: cipherCfg.padding, 
 | 
                    blockSize: cipher.blockSize, 
 | 
                    formatter: cfg.format 
 | 
                }); 
 | 
            }, 
 | 
  
 | 
            /** 
 | 
             * Decrypts serialized ciphertext. 
 | 
             * 
 | 
             * @param {Cipher} cipher The cipher algorithm to use. 
 | 
             * @param {CipherParams|string} ciphertext The ciphertext to decrypt. 
 | 
             * @param {WordArray} key The key. 
 | 
             * @param {Object} cfg (Optional) The configuration options to use for this operation. 
 | 
             * 
 | 
             * @return {WordArray} The plaintext. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL }); 
 | 
             *     var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL }); 
 | 
             */ 
 | 
            decrypt: function (cipher, ciphertext, key, cfg) { 
 | 
                // Apply config defaults 
 | 
                cfg = this.cfg.extend(cfg); 
 | 
  
 | 
                // Convert string to CipherParams 
 | 
                ciphertext = this._parse(ciphertext, cfg.format); 
 | 
  
 | 
                // Decrypt 
 | 
                var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext); 
 | 
  
 | 
                return plaintext; 
 | 
            }, 
 | 
  
 | 
            /** 
 | 
             * Converts serialized ciphertext to CipherParams, 
 | 
             * else assumed CipherParams already and returns ciphertext unchanged. 
 | 
             * 
 | 
             * @param {CipherParams|string} ciphertext The ciphertext. 
 | 
             * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext. 
 | 
             * 
 | 
             * @return {CipherParams} The unserialized ciphertext. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format); 
 | 
             */ 
 | 
            _parse: function (ciphertext, format) { 
 | 
                if (typeof ciphertext == 'string') { 
 | 
                    return format.parse(ciphertext, this); 
 | 
                } else { 
 | 
                    return ciphertext; 
 | 
                } 
 | 
            } 
 | 
        }); 
 | 
  
 | 
        /** 
 | 
         * Key derivation function namespace. 
 | 
         */ 
 | 
        var C_kdf = C.kdf = {}; 
 | 
  
 | 
        /** 
 | 
         * OpenSSL key derivation function. 
 | 
         */ 
 | 
        var OpenSSLKdf = C_kdf.OpenSSL = { 
 | 
            /** 
 | 
             * Derives a key and IV from a password. 
 | 
             * 
 | 
             * @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. 
 | 
             * 
 | 
             * @return {CipherParams} A cipher params object with the key, IV, and salt. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32); 
 | 
             *     var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt'); 
 | 
             */ 
 | 
            execute: function (password, keySize, ivSize, salt, hasher) { 
 | 
                // Generate random salt 
 | 
                if (!salt) { 
 | 
                    salt = WordArray.random(64/8); 
 | 
                } 
 | 
  
 | 
                // Derive key and IV 
 | 
                if (!hasher) { 
 | 
                    var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt); 
 | 
                } else { 
 | 
                    var key = EvpKDF.create({ keySize: keySize + ivSize, hasher: hasher }).compute(password, salt); 
 | 
                } 
 | 
  
 | 
  
 | 
                // Separate key and IV 
 | 
                var iv = WordArray.create(key.words.slice(keySize), ivSize * 4); 
 | 
                key.sigBytes = keySize * 4; 
 | 
  
 | 
                // Return params 
 | 
                return CipherParams.create({ key: key, iv: iv, salt: salt }); 
 | 
            } 
 | 
        }; 
 | 
  
 | 
        /** 
 | 
         * A serializable cipher wrapper that derives the key from a password, 
 | 
         * and returns ciphertext as a serializable cipher params object. 
 | 
         */ 
 | 
        var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({ 
 | 
            /** 
 | 
             * Configuration options. 
 | 
             * 
 | 
             * @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL 
 | 
             */ 
 | 
            cfg: SerializableCipher.cfg.extend({ 
 | 
                kdf: OpenSSLKdf 
 | 
            }), 
 | 
  
 | 
            /** 
 | 
             * Encrypts a message using a password. 
 | 
             * 
 | 
             * @param {Cipher} cipher The cipher algorithm to use. 
 | 
             * @param {WordArray|string} message The message to encrypt. 
 | 
             * @param {string} password The password. 
 | 
             * @param {Object} cfg (Optional) The configuration options to use for this operation. 
 | 
             * 
 | 
             * @return {CipherParams} A cipher params object. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password'); 
 | 
             *     var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL }); 
 | 
             */ 
 | 
            encrypt: function (cipher, message, password, cfg) { 
 | 
                // Apply config defaults 
 | 
                cfg = this.cfg.extend(cfg); 
 | 
  
 | 
                // Derive key and other params 
 | 
                var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, cfg.salt, cfg.hasher); 
 | 
  
 | 
                // Add IV to config 
 | 
                cfg.iv = derivedParams.iv; 
 | 
  
 | 
                // Encrypt 
 | 
                var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg); 
 | 
  
 | 
                // Mix in derived params 
 | 
                ciphertext.mixIn(derivedParams); 
 | 
  
 | 
                return ciphertext; 
 | 
            }, 
 | 
  
 | 
            /** 
 | 
             * Decrypts serialized ciphertext using a password. 
 | 
             * 
 | 
             * @param {Cipher} cipher The cipher algorithm to use. 
 | 
             * @param {CipherParams|string} ciphertext The ciphertext to decrypt. 
 | 
             * @param {string} password The password. 
 | 
             * @param {Object} cfg (Optional) The configuration options to use for this operation. 
 | 
             * 
 | 
             * @return {WordArray} The plaintext. 
 | 
             * 
 | 
             * @static 
 | 
             * 
 | 
             * @example 
 | 
             * 
 | 
             *     var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL }); 
 | 
             *     var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL }); 
 | 
             */ 
 | 
            decrypt: function (cipher, ciphertext, password, cfg) { 
 | 
                // Apply config defaults 
 | 
                cfg = this.cfg.extend(cfg); 
 | 
  
 | 
                // Convert string to CipherParams 
 | 
                ciphertext = this._parse(ciphertext, cfg.format); 
 | 
  
 | 
                // Derive key and other params 
 | 
                var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt, cfg.hasher); 
 | 
  
 | 
                // Add IV to config 
 | 
                cfg.iv = derivedParams.iv; 
 | 
  
 | 
                // Decrypt 
 | 
                var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg); 
 | 
  
 | 
                return plaintext; 
 | 
            } 
 | 
        }); 
 | 
    }()); 
 | 
  
 | 
  
 | 
})); 
 |