cipher-core.js 28 KB

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