AI销管
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

890 lignes
29 KiB

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