UNPKG

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