| ;(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; | 
|             } | 
|         }); | 
|     }()); | 
|   | 
|   | 
| })); |