UNPKG

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