Show More
Commit Description:
utf8mb4
Commit Description:
utf8mb4
References:
File last commit:
Show/Diff file:
Action:
node_modules/crypto-js/cipher-core.js
| 879 lines
| 28.8 KiB
| application/javascript
| JavascriptLexer
|
r789 | ;(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) { | |||
// 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; | |||
} | |||
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 () { | |||
// 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; | |||
} | |||
}); | |||
}()); | |||
})); |