@brix-crypto/crypto-js 0.0.1-security → 4.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of @brix-crypto/crypto-js might be problematic. Click here for more details.

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