Subversion Repositories cryptochat

Rev

View as "text/javascript" | Blame | Last modification | View Log | RSS feed

  1. /*
  2. CryptoJS v3.1.2
  3. code.google.com/p/crypto-js
  4. (c) 2009-2013 by Jeff Mott. All rights reserved.
  5. code.google.com/p/crypto-js/wiki/License
  6. */
  7. /**
  8.  * Cipher core components.
  9.  */
  10. CryptoJS.lib.Cipher || (function (undefined) {
  11.     // Shortcuts
  12.     var C = CryptoJS;
  13.     var C_lib = C.lib;
  14.     var Base = C_lib.Base;
  15.     var WordArray = C_lib.WordArray;
  16.     var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm;
  17.     var C_enc = C.enc;
  18.     var Utf8 = C_enc.Utf8;
  19.     var Base64 = C_enc.Base64;
  20.     var C_algo = C.algo;
  21.     var EvpKDF = C_algo.EvpKDF;
  22.  
  23.     /**
  24.      * Abstract base cipher template.
  25.      *
  26.      * @property {number} keySize This cipher's key size. Default: 4 (128 bits)
  27.      * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits)
  28.      * @property {number} _ENC_XFORM_MODE A constant representing encryption mode.
  29.      * @property {number} _DEC_XFORM_MODE A constant representing decryption mode.
  30.      */
  31.     var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({
  32.         /**
  33.          * Configuration options.
  34.          *
  35.          * @property {WordArray} iv The IV to use for this operation.
  36.          */
  37.         cfg: Base.extend(),
  38.  
  39.         /**
  40.          * Creates this cipher in encryption mode.
  41.          *
  42.          * @param {WordArray} key The key.
  43.          * @param {Object} cfg (Optional) The configuration options to use for this operation.
  44.          *
  45.          * @return {Cipher} A cipher instance.
  46.          *
  47.          * @static
  48.          *
  49.          * @example
  50.          *
  51.          *     var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray });
  52.          */
  53.         createEncryptor: function (key, cfg) {
  54.             return this.create(this._ENC_XFORM_MODE, key, cfg);
  55.         },
  56.  
  57.         /**
  58.          * Creates this cipher in decryption mode.
  59.          *
  60.          * @param {WordArray} key The key.
  61.          * @param {Object} cfg (Optional) The configuration options to use for this operation.
  62.          *
  63.          * @return {Cipher} A cipher instance.
  64.          *
  65.          * @static
  66.          *
  67.          * @example
  68.          *
  69.          *     var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray });
  70.          */
  71.         createDecryptor: function (key, cfg) {
  72.             return this.create(this._DEC_XFORM_MODE, key, cfg);
  73.         },
  74.  
  75.         /**
  76.          * Initializes a newly created cipher.
  77.          *
  78.          * @param {number} xformMode Either the encryption or decryption transormation mode constant.
  79.          * @param {WordArray} key The key.
  80.          * @param {Object} cfg (Optional) The configuration options to use for this operation.
  81.          *
  82.          * @example
  83.          *
  84.          *     var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray });
  85.          */
  86.         init: function (xformMode, key, cfg) {
  87.             // Apply config defaults
  88.             this.cfg = this.cfg.extend(cfg);
  89.  
  90.             // Store transform mode and key
  91.             this._xformMode = xformMode;
  92.             this._key = key;
  93.  
  94.             // Set initial values
  95.             this.reset();
  96.         },
  97.  
  98.         /**
  99.          * Resets this cipher to its initial state.
  100.          *
  101.          * @example
  102.          *
  103.          *     cipher.reset();
  104.          */
  105.         reset: function () {
  106.             // Reset data buffer
  107.             BufferedBlockAlgorithm.reset.call(this);
  108.  
  109.             // Perform concrete-cipher logic
  110.             this._doReset();
  111.         },
  112.  
  113.         /**
  114.          * Adds data to be encrypted or decrypted.
  115.          *
  116.          * @param {WordArray|string} dataUpdate The data to encrypt or decrypt.
  117.          *
  118.          * @return {WordArray} The data after processing.
  119.          *
  120.          * @example
  121.          *
  122.          *     var encrypted = cipher.process('data');
  123.          *     var encrypted = cipher.process(wordArray);
  124.          */
  125.         process: function (dataUpdate) {
  126.             // Append
  127.             this._append(dataUpdate);
  128.  
  129.             // Process available blocks
  130.             return this._process();
  131.         },
  132.  
  133.         /**
  134.          * Finalizes the encryption or decryption process.
  135.          * Note that the finalize operation is effectively a destructive, read-once operation.
  136.          *
  137.          * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt.
  138.          *
  139.          * @return {WordArray} The data after final processing.
  140.          *
  141.          * @example
  142.          *
  143.          *     var encrypted = cipher.finalize();
  144.          *     var encrypted = cipher.finalize('data');
  145.          *     var encrypted = cipher.finalize(wordArray);
  146.          */
  147.         finalize: function (dataUpdate) {
  148.             // Final data update
  149.             if (dataUpdate) {
  150.                 this._append(dataUpdate);
  151.             }
  152.  
  153.             // Perform concrete-cipher logic
  154.             var finalProcessedData = this._doFinalize();
  155.  
  156.             return finalProcessedData;
  157.         },
  158.  
  159.         keySize: 128/32,
  160.  
  161.         ivSize: 128/32,
  162.  
  163.         _ENC_XFORM_MODE: 1,
  164.  
  165.         _DEC_XFORM_MODE: 2,
  166.  
  167.         /**
  168.          * Creates shortcut functions to a cipher's object interface.
  169.          *
  170.          * @param {Cipher} cipher The cipher to create a helper for.
  171.          *
  172.          * @return {Object} An object with encrypt and decrypt shortcut functions.
  173.          *
  174.          * @static
  175.          *
  176.          * @example
  177.          *
  178.          *     var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES);
  179.          */
  180.         _createHelper: (function () {
  181.             function selectCipherStrategy(key) {
  182.                 if (typeof key == 'string') {
  183.                     return PasswordBasedCipher;
  184.                 } else {
  185.                     return SerializableCipher;
  186.                 }
  187.             }
  188.  
  189.             return function (cipher) {
  190.                 return {
  191.                     encrypt: function (message, key, cfg) {
  192.                         return selectCipherStrategy(key).encrypt(cipher, message, key, cfg);
  193.                     },
  194.  
  195.                     decrypt: function (ciphertext, key, cfg) {
  196.                         return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg);
  197.                     }
  198.                 };
  199.             };
  200.         }())
  201.     });
  202.  
  203.     /**
  204.      * Abstract base stream cipher template.
  205.      *
  206.      * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits)
  207.      */
  208.     var StreamCipher = C_lib.StreamCipher = Cipher.extend({
  209.         _doFinalize: function () {
  210.             // Process partial blocks
  211.             var finalProcessedBlocks = this._process(!!'flush');
  212.  
  213.             return finalProcessedBlocks;
  214.         },
  215.  
  216.         blockSize: 1
  217.     });
  218.  
  219.     /**
  220.      * Mode namespace.
  221.      */
  222.     var C_mode = C.mode = {};
  223.  
  224.     /**
  225.      * Abstract base block cipher mode template.
  226.      */
  227.     var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({
  228.         /**
  229.          * Creates this mode for encryption.
  230.          *
  231.          * @param {Cipher} cipher A block cipher instance.
  232.          * @param {Array} iv The IV words.
  233.          *
  234.          * @static
  235.          *
  236.          * @example
  237.          *
  238.          *     var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words);
  239.          */
  240.         createEncryptor: function (cipher, iv) {
  241.             return this.Encryptor.create(cipher, iv);
  242.         },
  243.  
  244.         /**
  245.          * Creates this mode for decryption.
  246.          *
  247.          * @param {Cipher} cipher A block cipher instance.
  248.          * @param {Array} iv The IV words.
  249.          *
  250.          * @static
  251.          *
  252.          * @example
  253.          *
  254.          *     var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words);
  255.          */
  256.         createDecryptor: function (cipher, iv) {
  257.             return this.Decryptor.create(cipher, iv);
  258.         },
  259.  
  260.         /**
  261.          * Initializes a newly created mode.
  262.          *
  263.          * @param {Cipher} cipher A block cipher instance.
  264.          * @param {Array} iv The IV words.
  265.          *
  266.          * @example
  267.          *
  268.          *     var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words);
  269.          */
  270.         init: function (cipher, iv) {
  271.             this._cipher = cipher;
  272.             this._iv = iv;
  273.         }
  274.     });
  275.  
  276.     /**
  277.      * Cipher Block Chaining mode.
  278.      */
  279.     var CBC = C_mode.CBC = (function () {
  280.         /**
  281.          * Abstract base CBC mode.
  282.          */
  283.         var CBC = BlockCipherMode.extend();
  284.  
  285.         /**
  286.          * CBC encryptor.
  287.          */
  288.         CBC.Encryptor = CBC.extend({
  289.             /**
  290.              * Processes the data block at offset.
  291.              *
  292.              * @param {Array} words The data words to operate on.
  293.              * @param {number} offset The offset where the block starts.
  294.              *
  295.              * @example
  296.              *
  297.              *     mode.processBlock(data.words, offset);
  298.              */
  299.             processBlock: function (words, offset) {
  300.                 // Shortcuts
  301.                 var cipher = this._cipher;
  302.                 var blockSize = cipher.blockSize;
  303.  
  304.                 // XOR and encrypt
  305.                 xorBlock.call(this, words, offset, blockSize);
  306.                 cipher.encryptBlock(words, offset);
  307.  
  308.                 // Remember this block to use with next block
  309.                 this._prevBlock = words.slice(offset, offset + blockSize);
  310.             }
  311.         });
  312.  
  313.         /**
  314.          * CBC decryptor.
  315.          */
  316.         CBC.Decryptor = CBC.extend({
  317.             /**
  318.              * Processes the data block at offset.
  319.              *
  320.              * @param {Array} words The data words to operate on.
  321.              * @param {number} offset The offset where the block starts.
  322.              *
  323.              * @example
  324.              *
  325.              *     mode.processBlock(data.words, offset);
  326.              */
  327.             processBlock: function (words, offset) {
  328.                 // Shortcuts
  329.                 var cipher = this._cipher;
  330.                 var blockSize = cipher.blockSize;
  331.  
  332.                 // Remember this block to use with next block
  333.                 var thisBlock = words.slice(offset, offset + blockSize);
  334.  
  335.                 // Decrypt and XOR
  336.                 cipher.decryptBlock(words, offset);
  337.                 xorBlock.call(this, words, offset, blockSize);
  338.  
  339.                 // This block becomes the previous block
  340.                 this._prevBlock = thisBlock;
  341.             }
  342.         });
  343.  
  344.         function xorBlock(words, offset, blockSize) {
  345.             // Shortcut
  346.             var iv = this._iv;
  347.  
  348.             // Choose mixing block
  349.             if (iv) {
  350.                 var block = iv;
  351.  
  352.                 // Remove IV for subsequent blocks
  353.                 this._iv = undefined;
  354.             } else {
  355.                 var block = this._prevBlock;
  356.             }
  357.  
  358.             // XOR blocks
  359.             for (var i = 0; i < blockSize; i++) {
  360.                 words[offset + i] ^= block[i];
  361.             }
  362.         }
  363.  
  364.         return CBC;
  365.     }());
  366.  
  367.     /**
  368.      * Padding namespace.
  369.      */
  370.     var C_pad = C.pad = {};
  371.  
  372.     /**
  373.      * PKCS #5/7 padding strategy.
  374.      */
  375.     var Pkcs7 = C_pad.Pkcs7 = {
  376.         /**
  377.          * Pads data using the algorithm defined in PKCS #5/7.
  378.          *
  379.          * @param {WordArray} data The data to pad.
  380.          * @param {number} blockSize The multiple that the data should be padded to.
  381.          *
  382.          * @static
  383.          *
  384.          * @example
  385.          *
  386.          *     CryptoJS.pad.Pkcs7.pad(wordArray, 4);
  387.          */
  388.         pad: function (data, blockSize) {
  389.             // Shortcut
  390.             var blockSizeBytes = blockSize * 4;
  391.  
  392.             // Count padding bytes
  393.             var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes;
  394.  
  395.             // Create padding word
  396.             var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes;
  397.  
  398.             // Create padding
  399.             var paddingWords = [];
  400.             for (var i = 0; i < nPaddingBytes; i += 4) {
  401.                 paddingWords.push(paddingWord);
  402.             }
  403.             var padding = WordArray.create(paddingWords, nPaddingBytes);
  404.  
  405.             // Add padding
  406.             data.concat(padding);
  407.         },
  408.  
  409.         /**
  410.          * Unpads data that had been padded using the algorithm defined in PKCS #5/7.
  411.          *
  412.          * @param {WordArray} data The data to unpad.
  413.          *
  414.          * @static
  415.          *
  416.          * @example
  417.          *
  418.          *     CryptoJS.pad.Pkcs7.unpad(wordArray);
  419.          */
  420.         unpad: function (data) {
  421.             // Get number of padding bytes from last byte
  422.             var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;
  423.  
  424.             // Remove padding
  425.             data.sigBytes -= nPaddingBytes;
  426.         }
  427.     };
  428.  
  429.     /**
  430.      * Abstract base block cipher template.
  431.      *
  432.      * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits)
  433.      */
  434.     var BlockCipher = C_lib.BlockCipher = Cipher.extend({
  435.         /**
  436.          * Configuration options.
  437.          *
  438.          * @property {Mode} mode The block mode to use. Default: CBC
  439.          * @property {Padding} padding The padding strategy to use. Default: Pkcs7
  440.          */
  441.         cfg: Cipher.cfg.extend({
  442.             mode: CBC,
  443.             padding: Pkcs7
  444.         }),
  445.  
  446.         reset: function () {
  447.             // Reset cipher
  448.             Cipher.reset.call(this);
  449.  
  450.             // Shortcuts
  451.             var cfg = this.cfg;
  452.             var iv = cfg.iv;
  453.             var mode = cfg.mode;
  454.  
  455.             // Reset block mode
  456.             if (this._xformMode == this._ENC_XFORM_MODE) {
  457.                 var modeCreator = mode.createEncryptor;
  458.             } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
  459.                 var modeCreator = mode.createDecryptor;
  460.  
  461.                 // Keep at least one block in the buffer for unpadding
  462.                 this._minBufferSize = 1;
  463.             }
  464.             this._mode = modeCreator.call(mode, this, iv && iv.words);
  465.         },
  466.  
  467.         _doProcessBlock: function (words, offset) {
  468.             this._mode.processBlock(words, offset);
  469.         },
  470.  
  471.         _doFinalize: function () {
  472.             // Shortcut
  473.             var padding = this.cfg.padding;
  474.  
  475.             // Finalize
  476.             if (this._xformMode == this._ENC_XFORM_MODE) {
  477.                 // Pad data
  478.                 padding.pad(this._data, this.blockSize);
  479.  
  480.                 // Process final blocks
  481.                 var finalProcessedBlocks = this._process(!!'flush');
  482.             } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
  483.                 // Process final blocks
  484.                 var finalProcessedBlocks = this._process(!!'flush');
  485.  
  486.                 // Unpad data
  487.                 padding.unpad(finalProcessedBlocks);
  488.             }
  489.  
  490.             return finalProcessedBlocks;
  491.         },
  492.  
  493.         blockSize: 128/32
  494.     });
  495.  
  496.     /**
  497.      * A collection of cipher parameters.
  498.      *
  499.      * @property {WordArray} ciphertext The raw ciphertext.
  500.      * @property {WordArray} key The key to this ciphertext.
  501.      * @property {WordArray} iv The IV used in the ciphering operation.
  502.      * @property {WordArray} salt The salt used with a key derivation function.
  503.      * @property {Cipher} algorithm The cipher algorithm.
  504.      * @property {Mode} mode The block mode used in the ciphering operation.
  505.      * @property {Padding} padding The padding scheme used in the ciphering operation.
  506.      * @property {number} blockSize The block size of the cipher.
  507.      * @property {Format} formatter The default formatting strategy to convert this cipher params object to a string.
  508.      */
  509.     var CipherParams = C_lib.CipherParams = Base.extend({
  510.         /**
  511.          * Initializes a newly created cipher params object.
  512.          *
  513.          * @param {Object} cipherParams An object with any of the possible cipher parameters.
  514.          *
  515.          * @example
  516.          *
  517.          *     var cipherParams = CryptoJS.lib.CipherParams.create({
  518.          *         ciphertext: ciphertextWordArray,
  519.          *         key: keyWordArray,
  520.          *         iv: ivWordArray,
  521.          *         salt: saltWordArray,
  522.          *         algorithm: CryptoJS.algo.AES,
  523.          *         mode: CryptoJS.mode.CBC,
  524.          *         padding: CryptoJS.pad.PKCS7,
  525.          *         blockSize: 4,
  526.          *         formatter: CryptoJS.format.OpenSSL
  527.          *     });
  528.          */
  529.         init: function (cipherParams) {
  530.             this.mixIn(cipherParams);
  531.         },
  532.  
  533.         /**
  534.          * Converts this cipher params object to a string.
  535.          *
  536.          * @param {Format} formatter (Optional) The formatting strategy to use.
  537.          *
  538.          * @return {string} The stringified cipher params.
  539.          *
  540.          * @throws Error If neither the formatter nor the default formatter is set.
  541.          *
  542.          * @example
  543.          *
  544.          *     var string = cipherParams + '';
  545.          *     var string = cipherParams.toString();
  546.          *     var string = cipherParams.toString(CryptoJS.format.OpenSSL);
  547.          */
  548.         toString: function (formatter) {
  549.             return (formatter || this.formatter).stringify(this);
  550.         }
  551.     });
  552.  
  553.     /**
  554.      * Format namespace.
  555.      */
  556.     var C_format = C.format = {};
  557.  
  558.     /**
  559.      * OpenSSL formatting strategy.
  560.      */
  561.     var OpenSSLFormatter = C_format.OpenSSL = {
  562.         /**
  563.          * Converts a cipher params object to an OpenSSL-compatible string.
  564.          *
  565.          * @param {CipherParams} cipherParams The cipher params object.
  566.          *
  567.          * @return {string} The OpenSSL-compatible string.
  568.          *
  569.          * @static
  570.          *
  571.          * @example
  572.          *
  573.          *     var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams);
  574.          */
  575.         stringify: function (cipherParams) {
  576.             // Shortcuts
  577.             var ciphertext = cipherParams.ciphertext;
  578.             var salt = cipherParams.salt;
  579.  
  580.             // Format
  581.             if (salt) {
  582.                 var wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext);
  583.             } else {
  584.                 var wordArray = ciphertext;
  585.             }
  586.  
  587.             return wordArray.toString(Base64);
  588.         },
  589.  
  590.         /**
  591.          * Converts an OpenSSL-compatible string to a cipher params object.
  592.          *
  593.          * @param {string} openSSLStr The OpenSSL-compatible string.
  594.          *
  595.          * @return {CipherParams} The cipher params object.
  596.          *
  597.          * @static
  598.          *
  599.          * @example
  600.          *
  601.          *     var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString);
  602.          */
  603.         parse: function (openSSLStr) {
  604.             // Parse base64
  605.             var ciphertext = Base64.parse(openSSLStr);
  606.  
  607.             // Shortcut
  608.             var ciphertextWords = ciphertext.words;
  609.  
  610.             // Test for salt
  611.             if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) {
  612.                 // Extract salt
  613.                 var salt = WordArray.create(ciphertextWords.slice(2, 4));
  614.  
  615.                 // Remove salt from ciphertext
  616.                 ciphertextWords.splice(0, 4);
  617.                 ciphertext.sigBytes -= 16;
  618.             }
  619.  
  620.             return CipherParams.create({ ciphertext: ciphertext, salt: salt });
  621.         }
  622.     };
  623.  
  624.     /**
  625.      * A cipher wrapper that returns ciphertext as a serializable cipher params object.
  626.      */
  627.     var SerializableCipher = C_lib.SerializableCipher = Base.extend({
  628.         /**
  629.          * Configuration options.
  630.          *
  631.          * @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL
  632.          */
  633.         cfg: Base.extend({
  634.             format: OpenSSLFormatter
  635.         }),
  636.  
  637.         /**
  638.          * Encrypts a message.
  639.          *
  640.          * @param {Cipher} cipher The cipher algorithm to use.
  641.          * @param {WordArray|string} message The message to encrypt.
  642.          * @param {WordArray} key The key.
  643.          * @param {Object} cfg (Optional) The configuration options to use for this operation.
  644.          *
  645.          * @return {CipherParams} A cipher params object.
  646.          *
  647.          * @static
  648.          *
  649.          * @example
  650.          *
  651.          *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key);
  652.          *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv });
  653.          *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL });
  654.          */
  655.         encrypt: function (cipher, message, key, cfg) {
  656.             // Apply config defaults
  657.             cfg = this.cfg.extend(cfg);
  658.  
  659.             // Encrypt
  660.             var encryptor = cipher.createEncryptor(key, cfg);
  661.             var ciphertext = encryptor.finalize(message);
  662.  
  663.             // Shortcut
  664.             var cipherCfg = encryptor.cfg;
  665.  
  666.             // Create and return serializable cipher params
  667.             return CipherParams.create({
  668.                 ciphertext: ciphertext,
  669.                 key: key,
  670.                 iv: cipherCfg.iv,
  671.                 algorithm: cipher,
  672.                 mode: cipherCfg.mode,
  673.                 padding: cipherCfg.padding,
  674.                 blockSize: cipher.blockSize,
  675.                 formatter: cfg.format
  676.             });
  677.         },
  678.  
  679.         /**
  680.          * Decrypts serialized ciphertext.
  681.          *
  682.          * @param {Cipher} cipher The cipher algorithm to use.
  683.          * @param {CipherParams|string} ciphertext The ciphertext to decrypt.
  684.          * @param {WordArray} key The key.
  685.          * @param {Object} cfg (Optional) The configuration options to use for this operation.
  686.          *
  687.          * @return {WordArray} The plaintext.
  688.          *
  689.          * @static
  690.          *
  691.          * @example
  692.          *
  693.          *     var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL });
  694.          *     var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL });
  695.          */
  696.         decrypt: function (cipher, ciphertext, key, cfg) {
  697.             // Apply config defaults
  698.             cfg = this.cfg.extend(cfg);
  699.  
  700.             // Convert string to CipherParams
  701.             ciphertext = this._parse(ciphertext, cfg.format);
  702.  
  703.             // Decrypt
  704.             var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext);
  705.  
  706.             return plaintext;
  707.         },
  708.  
  709.         /**
  710.          * Converts serialized ciphertext to CipherParams,
  711.          * else assumed CipherParams already and returns ciphertext unchanged.
  712.          *
  713.          * @param {CipherParams|string} ciphertext The ciphertext.
  714.          * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext.
  715.          *
  716.          * @return {CipherParams} The unserialized ciphertext.
  717.          *
  718.          * @static
  719.          *
  720.          * @example
  721.          *
  722.          *     var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format);
  723.          */
  724.         _parse: function (ciphertext, format) {
  725.             if (typeof ciphertext == 'string') {
  726.                 return format.parse(ciphertext, this);
  727.             } else {
  728.                 return ciphertext;
  729.             }
  730.         }
  731.     });
  732.  
  733.     /**
  734.      * Key derivation function namespace.
  735.      */
  736.     var C_kdf = C.kdf = {};
  737.  
  738.     /**
  739.      * OpenSSL key derivation function.
  740.      */
  741.     var OpenSSLKdf = C_kdf.OpenSSL = {
  742.         /**
  743.          * Derives a key and IV from a password.
  744.          *
  745.          * @param {string} password The password to derive from.
  746.          * @param {number} keySize The size in words of the key to generate.
  747.          * @param {number} ivSize The size in words of the IV to generate.
  748.          * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly.
  749.          *
  750.          * @return {CipherParams} A cipher params object with the key, IV, and salt.
  751.          *
  752.          * @static
  753.          *
  754.          * @example
  755.          *
  756.          *     var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32);
  757.          *     var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
  758.          */
  759.         execute: function (password, keySize, ivSize, salt) {
  760.             // Generate random salt
  761.             if (!salt) {
  762.                 salt = WordArray.random(64/8);
  763.             }
  764.  
  765.             // Derive key and IV
  766.             var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
  767.  
  768.             // Separate key and IV
  769.             var iv = WordArray.create(key.words.slice(keySize), ivSize * 4);
  770.             key.sigBytes = keySize * 4;
  771.  
  772.             // Return params
  773.             return CipherParams.create({ key: key, iv: iv, salt: salt });
  774.         }
  775.     };
  776.  
  777.     /**
  778.      * A serializable cipher wrapper that derives the key from a password,
  779.      * and returns ciphertext as a serializable cipher params object.
  780.      */
  781.     var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({
  782.         /**
  783.          * Configuration options.
  784.          *
  785.          * @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL
  786.          */
  787.         cfg: SerializableCipher.cfg.extend({
  788.             kdf: OpenSSLKdf
  789.         }),
  790.  
  791.         /**
  792.          * Encrypts a message using a password.
  793.          *
  794.          * @param {Cipher} cipher The cipher algorithm to use.
  795.          * @param {WordArray|string} message The message to encrypt.
  796.          * @param {string} password The password.
  797.          * @param {Object} cfg (Optional) The configuration options to use for this operation.
  798.          *
  799.          * @return {CipherParams} A cipher params object.
  800.          *
  801.          * @static
  802.          *
  803.          * @example
  804.          *
  805.          *     var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password');
  806.          *     var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL });
  807.          */
  808.         encrypt: function (cipher, message, password, cfg) {
  809.             // Apply config defaults
  810.             cfg = this.cfg.extend(cfg);
  811.  
  812.             // Derive key and other params
  813.             var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize);
  814.  
  815.             // Add IV to config
  816.             cfg.iv = derivedParams.iv;
  817.  
  818.             // Encrypt
  819.             var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg);
  820.  
  821.             // Mix in derived params
  822.             ciphertext.mixIn(derivedParams);
  823.  
  824.             return ciphertext;
  825.         },
  826.  
  827.         /**
  828.          * Decrypts serialized ciphertext using a password.
  829.          *
  830.          * @param {Cipher} cipher The cipher algorithm to use.
  831.          * @param {CipherParams|string} ciphertext The ciphertext to decrypt.
  832.          * @param {string} password The password.
  833.          * @param {Object} cfg (Optional) The configuration options to use for this operation.
  834.          *
  835.          * @return {WordArray} The plaintext.
  836.          *
  837.          * @static
  838.          *
  839.          * @example
  840.          *
  841.          *     var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL });
  842.          *     var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL });
  843.          */
  844.         decrypt: function (cipher, ciphertext, password, cfg) {
  845.             // Apply config defaults
  846.             cfg = this.cfg.extend(cfg);
  847.  
  848.             // Convert string to CipherParams
  849.             ciphertext = this._parse(ciphertext, cfg.format);
  850.  
  851.             // Derive key and other params
  852.             var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt);
  853.  
  854.             // Add IV to config
  855.             cfg.iv = derivedParams.iv;
  856.  
  857.             // Decrypt
  858.             var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg);
  859.  
  860.             return plaintext;
  861.         }
  862.     });
  863. }());
  864.