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 |