cipher-core.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  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. // Shortcut
  318. var iv = this._iv;
  319. // Choose mixing block
  320. if (iv) {
  321. var block = iv;
  322. // Remove IV for subsequent blocks
  323. this._iv = undefined;
  324. } else {
  325. var block = this._prevBlock;
  326. }
  327. // XOR blocks
  328. for (var i = 0; i < blockSize; i++) {
  329. words[offset + i] ^= block[i];
  330. }
  331. }
  332. return CBC;
  333. }());
  334. /**
  335. * Padding namespace.
  336. */
  337. var C_pad = C.pad = {};
  338. /**
  339. * PKCS #5/7 padding strategy.
  340. */
  341. var Pkcs7 = C_pad.Pkcs7 = {
  342. /**
  343. * Pads data using the algorithm defined in PKCS #5/7.
  344. *
  345. * @param {WordArray} data The data to pad.
  346. * @param {number} blockSize The multiple that the data should be padded to.
  347. *
  348. * @static
  349. *
  350. * @example
  351. *
  352. * CryptoJS.pad.Pkcs7.pad(wordArray, 4);
  353. */
  354. pad: function (data, blockSize) {
  355. // Shortcut
  356. var blockSizeBytes = blockSize * 4;
  357. // Count padding bytes
  358. var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes;
  359. // Create padding word
  360. var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes;
  361. // Create padding
  362. var paddingWords = [];
  363. for (var i = 0; i < nPaddingBytes; i += 4) {
  364. paddingWords.push(paddingWord);
  365. }
  366. var padding = WordArray.create(paddingWords, nPaddingBytes);
  367. // Add padding
  368. data.concat(padding);
  369. },
  370. /**
  371. * Unpads data that had been padded using the algorithm defined in PKCS #5/7.
  372. *
  373. * @param {WordArray} data The data to unpad.
  374. *
  375. * @static
  376. *
  377. * @example
  378. *
  379. * CryptoJS.pad.Pkcs7.unpad(wordArray);
  380. */
  381. unpad: function (data) {
  382. // Get number of padding bytes from last byte
  383. var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;
  384. // Remove padding
  385. data.sigBytes -= nPaddingBytes;
  386. }
  387. };
  388. /**
  389. * Abstract base block cipher template.
  390. *
  391. * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits)
  392. */
  393. var BlockCipher = C_lib.BlockCipher = Cipher.extend({
  394. /**
  395. * Configuration options.
  396. *
  397. * @property {Mode} mode The block mode to use. Default: CBC
  398. * @property {Padding} padding The padding strategy to use. Default: Pkcs7
  399. */
  400. cfg: Cipher.cfg.extend({
  401. mode: CBC,
  402. padding: Pkcs7
  403. }),
  404. reset: function () {
  405. // Reset cipher
  406. Cipher.reset.call(this);
  407. // Shortcuts
  408. var cfg = this.cfg;
  409. var iv = cfg.iv;
  410. var mode = cfg.mode;
  411. // Reset block mode
  412. if (this._xformMode == this._ENC_XFORM_MODE) {
  413. var modeCreator = mode.createEncryptor;
  414. } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
  415. var modeCreator = mode.createDecryptor;
  416. // Keep at least one block in the buffer for unpadding
  417. this._minBufferSize = 1;
  418. }
  419. if (this._mode && this._mode.__creator == modeCreator) {
  420. this._mode.init(this, iv && iv.words);
  421. } else {
  422. this._mode = modeCreator.call(mode, this, iv && iv.words);
  423. this._mode.__creator = modeCreator;
  424. }
  425. },
  426. _doProcessBlock: function (words, offset) {
  427. this._mode.processBlock(words, offset);
  428. },
  429. _doFinalize: function () {
  430. // Shortcut
  431. var padding = this.cfg.padding;
  432. // Finalize
  433. if (this._xformMode == this._ENC_XFORM_MODE) {
  434. // Pad data
  435. padding.pad(this._data, this.blockSize);
  436. // Process final blocks
  437. var finalProcessedBlocks = this._process(!!'flush');
  438. } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
  439. // Process final blocks
  440. var finalProcessedBlocks = this._process(!!'flush');
  441. // Unpad data
  442. padding.unpad(finalProcessedBlocks);
  443. }
  444. return finalProcessedBlocks;
  445. },
  446. blockSize: 128/32
  447. });
  448. /**
  449. * A collection of cipher parameters.
  450. *
  451. * @property {WordArray} ciphertext The raw ciphertext.
  452. * @property {WordArray} key The key to this ciphertext.
  453. * @property {WordArray} iv The IV used in the ciphering operation.
  454. * @property {WordArray} salt The salt used with a key derivation function.
  455. * @property {Cipher} algorithm The cipher algorithm.
  456. * @property {Mode} mode The block mode used in the ciphering operation.
  457. * @property {Padding} padding The padding scheme used in the ciphering operation.
  458. * @property {number} blockSize The block size of the cipher.
  459. * @property {Format} formatter The default formatting strategy to convert this cipher params object to a string.
  460. */
  461. var CipherParams = C_lib.CipherParams = Base.extend({
  462. /**
  463. * Initializes a newly created cipher params object.
  464. *
  465. * @param {Object} cipherParams An object with any of the possible cipher parameters.
  466. *
  467. * @example
  468. *
  469. * var cipherParams = CryptoJS.lib.CipherParams.create({
  470. * ciphertext: ciphertextWordArray,
  471. * key: keyWordArray,
  472. * iv: ivWordArray,
  473. * salt: saltWordArray,
  474. * algorithm: CryptoJS.algo.AES,
  475. * mode: CryptoJS.mode.CBC,
  476. * padding: CryptoJS.pad.PKCS7,
  477. * blockSize: 4,
  478. * formatter: CryptoJS.format.OpenSSL
  479. * });
  480. */
  481. init: function (cipherParams) {
  482. this.mixIn(cipherParams);
  483. },
  484. /**
  485. * Converts this cipher params object to a string.
  486. *
  487. * @param {Format} formatter (Optional) The formatting strategy to use.
  488. *
  489. * @return {string} The stringified cipher params.
  490. *
  491. * @throws Error If neither the formatter nor the default formatter is set.
  492. *
  493. * @example
  494. *
  495. * var string = cipherParams + '';
  496. * var string = cipherParams.toString();
  497. * var string = cipherParams.toString(CryptoJS.format.OpenSSL);
  498. */
  499. toString: function (formatter) {
  500. return (formatter || this.formatter).stringify(this);
  501. }
  502. });
  503. /**
  504. * Format namespace.
  505. */
  506. var C_format = C.format = {};
  507. /**
  508. * OpenSSL formatting strategy.
  509. */
  510. var OpenSSLFormatter = C_format.OpenSSL = {
  511. /**
  512. * Converts a cipher params object to an OpenSSL-compatible string.
  513. *
  514. * @param {CipherParams} cipherParams The cipher params object.
  515. *
  516. * @return {string} The OpenSSL-compatible string.
  517. *
  518. * @static
  519. *
  520. * @example
  521. *
  522. * var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams);
  523. */
  524. stringify: function (cipherParams) {
  525. // Shortcuts
  526. var ciphertext = cipherParams.ciphertext;
  527. var salt = cipherParams.salt;
  528. // Format
  529. if (salt) {
  530. var wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext);
  531. } else {
  532. var wordArray = ciphertext;
  533. }
  534. return wordArray.toString(Base64);
  535. },
  536. /**
  537. * Converts an OpenSSL-compatible string to a cipher params object.
  538. *
  539. * @param {string} openSSLStr The OpenSSL-compatible string.
  540. *
  541. * @return {CipherParams} The cipher params object.
  542. *
  543. * @static
  544. *
  545. * @example
  546. *
  547. * var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString);
  548. */
  549. parse: function (openSSLStr) {
  550. // Parse base64
  551. var ciphertext = Base64.parse(openSSLStr);
  552. // Shortcut
  553. var ciphertextWords = ciphertext.words;
  554. // Test for salt
  555. if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) {
  556. // Extract salt
  557. var salt = WordArray.create(ciphertextWords.slice(2, 4));
  558. // Remove salt from ciphertext
  559. ciphertextWords.splice(0, 4);
  560. ciphertext.sigBytes -= 16;
  561. }
  562. return CipherParams.create({ ciphertext: ciphertext, salt: salt });
  563. }
  564. };
  565. /**
  566. * A cipher wrapper that returns ciphertext as a serializable cipher params object.
  567. */
  568. var SerializableCipher = C_lib.SerializableCipher = Base.extend({
  569. /**
  570. * Configuration options.
  571. *
  572. * @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL
  573. */
  574. cfg: Base.extend({
  575. format: OpenSSLFormatter
  576. }),
  577. /**
  578. * Encrypts a message.
  579. *
  580. * @param {Cipher} cipher The cipher algorithm to use.
  581. * @param {WordArray|string} message The message to encrypt.
  582. * @param {WordArray} key The key.
  583. * @param {Object} cfg (Optional) The configuration options to use for this operation.
  584. *
  585. * @return {CipherParams} A cipher params object.
  586. *
  587. * @static
  588. *
  589. * @example
  590. *
  591. * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key);
  592. * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv });
  593. * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL });
  594. */
  595. encrypt: function (cipher, message, key, cfg) {
  596. // Apply config defaults
  597. cfg = this.cfg.extend(cfg);
  598. // Encrypt
  599. var encryptor = cipher.createEncryptor(key, cfg);
  600. var ciphertext = encryptor.finalize(message);
  601. // Shortcut
  602. var cipherCfg = encryptor.cfg;
  603. // Create and return serializable cipher params
  604. return CipherParams.create({
  605. ciphertext: ciphertext,
  606. key: key,
  607. iv: cipherCfg.iv,
  608. algorithm: cipher,
  609. mode: cipherCfg.mode,
  610. padding: cipherCfg.padding,
  611. blockSize: cipher.blockSize,
  612. formatter: cfg.format
  613. });
  614. },
  615. /**
  616. * Decrypts serialized ciphertext.
  617. *
  618. * @param {Cipher} cipher The cipher algorithm to use.
  619. * @param {CipherParams|string} ciphertext The ciphertext to decrypt.
  620. * @param {WordArray} key The key.
  621. * @param {Object} cfg (Optional) The configuration options to use for this operation.
  622. *
  623. * @return {WordArray} The plaintext.
  624. *
  625. * @static
  626. *
  627. * @example
  628. *
  629. * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL });
  630. * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL });
  631. */
  632. decrypt: function (cipher, ciphertext, key, cfg) {
  633. // Apply config defaults
  634. cfg = this.cfg.extend(cfg);
  635. // Convert string to CipherParams
  636. ciphertext = this._parse(ciphertext, cfg.format);
  637. // Decrypt
  638. var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext);
  639. return plaintext;
  640. },
  641. /**
  642. * Converts serialized ciphertext to CipherParams,
  643. * else assumed CipherParams already and returns ciphertext unchanged.
  644. *
  645. * @param {CipherParams|string} ciphertext The ciphertext.
  646. * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext.
  647. *
  648. * @return {CipherParams} The unserialized ciphertext.
  649. *
  650. * @static
  651. *
  652. * @example
  653. *
  654. * var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format);
  655. */
  656. _parse: function (ciphertext, format) {
  657. if (typeof ciphertext == 'string') {
  658. return format.parse(ciphertext, this);
  659. } else {
  660. return ciphertext;
  661. }
  662. }
  663. });
  664. /**
  665. * Key derivation function namespace.
  666. */
  667. var C_kdf = C.kdf = {};
  668. /**
  669. * OpenSSL key derivation function.
  670. */
  671. var OpenSSLKdf = C_kdf.OpenSSL = {
  672. /**
  673. * Derives a key and IV from a password.
  674. *
  675. * @param {string} password The password to derive from.
  676. * @param {number} keySize The size in words of the key to generate.
  677. * @param {number} ivSize The size in words of the IV to generate.
  678. * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly.
  679. *
  680. * @return {CipherParams} A cipher params object with the key, IV, and salt.
  681. *
  682. * @static
  683. *
  684. * @example
  685. *
  686. * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32);
  687. * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
  688. */
  689. execute: function (password, keySize, ivSize, salt) {
  690. // Generate random salt
  691. if (!salt) {
  692. salt = WordArray.random(64/8);
  693. }
  694. // Derive key and IV
  695. var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
  696. // Separate key and IV
  697. var iv = WordArray.create(key.words.slice(keySize), ivSize * 4);
  698. key.sigBytes = keySize * 4;
  699. // Return params
  700. return CipherParams.create({ key: key, iv: iv, salt: salt });
  701. }
  702. };
  703. /**
  704. * A serializable cipher wrapper that derives the key from a password,
  705. * and returns ciphertext as a serializable cipher params object.
  706. */
  707. var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({
  708. /**
  709. * Configuration options.
  710. *
  711. * @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL
  712. */
  713. cfg: SerializableCipher.cfg.extend({
  714. kdf: OpenSSLKdf
  715. }),
  716. /**
  717. * Encrypts a message using a password.
  718. *
  719. * @param {Cipher} cipher The cipher algorithm to use.
  720. * @param {WordArray|string} message The message to encrypt.
  721. * @param {string} password The password.
  722. * @param {Object} cfg (Optional) The configuration options to use for this operation.
  723. *
  724. * @return {CipherParams} A cipher params object.
  725. *
  726. * @static
  727. *
  728. * @example
  729. *
  730. * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password');
  731. * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL });
  732. */
  733. encrypt: function (cipher, message, password, cfg) {
  734. // Apply config defaults
  735. cfg = this.cfg.extend(cfg);
  736. // Derive key and other params
  737. var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize);
  738. // Add IV to config
  739. cfg.iv = derivedParams.iv;
  740. // Encrypt
  741. var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg);
  742. // Mix in derived params
  743. ciphertext.mixIn(derivedParams);
  744. return ciphertext;
  745. },
  746. /**
  747. * Decrypts serialized ciphertext using a password.
  748. *
  749. * @param {Cipher} cipher The cipher algorithm to use.
  750. * @param {CipherParams|string} ciphertext The ciphertext to decrypt.
  751. * @param {string} password The password.
  752. * @param {Object} cfg (Optional) The configuration options to use for this operation.
  753. *
  754. * @return {WordArray} The plaintext.
  755. *
  756. * @static
  757. *
  758. * @example
  759. *
  760. * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL });
  761. * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL });
  762. */
  763. decrypt: function (cipher, ciphertext, password, cfg) {
  764. // Apply config defaults
  765. cfg = this.cfg.extend(cfg);
  766. // Convert string to CipherParams
  767. ciphertext = this._parse(ciphertext, cfg.format);
  768. // Derive key and other params
  769. var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt);
  770. // Add IV to config
  771. cfg.iv = derivedParams.iv;
  772. // Decrypt
  773. var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg);
  774. return plaintext;
  775. }
  776. });
  777. }());
  778. }));