aboutsummaryrefslogtreecommitdiffstats
path: root/library/cryptojs/components/cipher-core.js
diff options
context:
space:
mode:
authorfriendica <info@friendica.com>2013-11-07 23:25:13 -0800
committerfriendica <info@friendica.com>2013-11-07 23:25:13 -0800
commit3a9cbcaf011f5c5d423e1cd99b43442669692129 (patch)
treed160f11dd97871d94ffe6e6d10ea48ce57eed357 /library/cryptojs/components/cipher-core.js
parent90ab0d963bf5074643c6f275dbb8595b6c51a03d (diff)
downloadvolse-hubzilla-3a9cbcaf011f5c5d423e1cd99b43442669692129.tar.gz
volse-hubzilla-3a9cbcaf011f5c5d423e1cd99b43442669692129.tar.bz2
volse-hubzilla-3a9cbcaf011f5c5d423e1cd99b43442669692129.zip
Wankers.
Diffstat (limited to 'library/cryptojs/components/cipher-core.js')
-rw-r--r--library/cryptojs/components/cipher-core.js863
1 files changed, 863 insertions, 0 deletions
diff --git a/library/cryptojs/components/cipher-core.js b/library/cryptojs/components/cipher-core.js
new file mode 100644
index 000000000..09862098f
--- /dev/null
+++ b/library/cryptojs/components/cipher-core.js
@@ -0,0 +1,863 @@
+/*
+CryptoJS v3.1.2
+code.google.com/p/crypto-js
+(c) 2009-2013 by Jeff Mott. All rights reserved.
+code.google.com/p/crypto-js/wiki/License
+*/
+/**
+ * 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) {
+ // Shortcut
+ var iv = this._iv;
+
+ // Choose mixing block
+ if (iv) {
+ var block = iv;
+
+ // Remove IV for subsequent blocks
+ this._iv = undefined;
+ } else {
+ var 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 () {
+ // 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) {
+ var modeCreator = mode.createEncryptor;
+ } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
+ var modeCreator = mode.createDecryptor;
+
+ // Keep at least one block in the buffer for unpadding
+ this._minBufferSize = 1;
+ }
+ this._mode = modeCreator.call(mode, this, iv && iv.words);
+ },
+
+ _doProcessBlock: function (words, offset) {
+ this._mode.processBlock(words, offset);
+ },
+
+ _doFinalize: function () {
+ // 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
+ var finalProcessedBlocks = this._process(!!'flush');
+ } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
+ // Process final blocks
+ var 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) {
+ // Shortcuts
+ var ciphertext = cipherParams.ciphertext;
+ var salt = cipherParams.salt;
+
+ // Format
+ if (salt) {
+ var wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext);
+ } else {
+ var 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) {
+ // Parse base64
+ var ciphertext = Base64.parse(openSSLStr);
+
+ // Shortcut
+ var ciphertextWords = ciphertext.words;
+
+ // Test for salt
+ if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) {
+ // Extract salt
+ var 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) {
+ // Generate random salt
+ if (!salt) {
+ salt = WordArray.random(64/8);
+ }
+
+ // Derive key and IV
+ var key = EvpKDF.create({ keySize: keySize + ivSize }).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);
+
+ // 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);
+
+ // Add IV to config
+ cfg.iv = derivedParams.iv;
+
+ // Decrypt
+ var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg);
+
+ return plaintext;
+ }
+ });
+}());