cipher-core.js 31 KB

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