core.js (20621B)
1 /** 2 * CryptoJS core components. 3 */ 4 var CryptoJS = CryptoJS || (function (Math, undefined) { 5 /** 6 * CryptoJS namespace. 7 */ 8 var C = {}; 9 10 /** 11 * Library namespace. 12 */ 13 var C_lib = C.lib = {}; 14 15 /** 16 * Base object for prototypal inheritance. 17 */ 18 var Base = C_lib.Base = (function () { 19 function F() {} 20 21 return { 22 /** 23 * Creates a new object that inherits from this object. 24 * 25 * @param {Object} overrides Properties to copy into the new object. 26 * 27 * @return {Object} The new object. 28 * 29 * @static 30 * 31 * @example 32 * 33 * var MyType = CryptoJS.lib.Base.extend({ 34 * field: 'value', 35 * 36 * method: function () { 37 * } 38 * }); 39 */ 40 extend: function (overrides) { 41 // Spawn 42 F.prototype = this; 43 var subtype = new F(); 44 45 // Augment 46 if (overrides) { 47 subtype.mixIn(overrides); 48 } 49 50 // Create default initializer 51 if (!subtype.hasOwnProperty('init')) { 52 subtype.init = function () { 53 subtype.$super.init.apply(this, arguments); 54 }; 55 } 56 57 // Initializer's prototype is the subtype object 58 subtype.init.prototype = subtype; 59 60 // Reference supertype 61 subtype.$super = this; 62 63 return subtype; 64 }, 65 66 /** 67 * Extends this object and runs the init method. 68 * Arguments to create() will be passed to init(). 69 * 70 * @return {Object} The new object. 71 * 72 * @static 73 * 74 * @example 75 * 76 * var instance = MyType.create(); 77 */ 78 create: function () { 79 var instance = this.extend(); 80 instance.init.apply(instance, arguments); 81 82 return instance; 83 }, 84 85 /** 86 * Initializes a newly created object. 87 * Override this method to add some logic when your objects are created. 88 * 89 * @example 90 * 91 * var MyType = CryptoJS.lib.Base.extend({ 92 * init: function () { 93 * // ... 94 * } 95 * }); 96 */ 97 init: function () { 98 }, 99 100 /** 101 * Copies properties into this object. 102 * 103 * @param {Object} properties The properties to mix in. 104 * 105 * @example 106 * 107 * MyType.mixIn({ 108 * field: 'value' 109 * }); 110 */ 111 mixIn: function (properties) { 112 for (var propertyName in properties) { 113 if (properties.hasOwnProperty(propertyName)) { 114 this[propertyName] = properties[propertyName]; 115 } 116 } 117 118 // IE won't copy toString using the loop above 119 if (properties.hasOwnProperty('toString')) { 120 this.toString = properties.toString; 121 } 122 }, 123 124 /** 125 * Creates a copy of this object. 126 * 127 * @return {Object} The clone. 128 * 129 * @example 130 * 131 * var clone = instance.clone(); 132 */ 133 clone: function () { 134 return this.init.prototype.extend(this); 135 } 136 }; 137 }()); 138 139 /** 140 * An array of 32-bit words. 141 * 142 * @property {Array} words The array of 32-bit words. 143 * @property {number} sigBytes The number of significant bytes in this word array. 144 */ 145 var WordArray = C_lib.WordArray = Base.extend({ 146 /** 147 * Initializes a newly created word array. 148 * 149 * @param {Array} words (Optional) An array of 32-bit words. 150 * @param {number} sigBytes (Optional) The number of significant bytes in the words. 151 * 152 * @example 153 * 154 * var wordArray = CryptoJS.lib.WordArray.create(); 155 * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); 156 * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); 157 */ 158 init: function (words, sigBytes) { 159 words = this.words = words || []; 160 161 if (sigBytes != undefined) { 162 this.sigBytes = sigBytes; 163 } else { 164 this.sigBytes = words.length * 4; 165 } 166 }, 167 168 /** 169 * Converts this word array to a string. 170 * 171 * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex 172 * 173 * @return {string} The stringified word array. 174 * 175 * @example 176 * 177 * var string = wordArray + ''; 178 * var string = wordArray.toString(); 179 * var string = wordArray.toString(CryptoJS.enc.Utf8); 180 */ 181 toString: function (encoder) { 182 return (encoder || Hex).stringify(this); 183 }, 184 185 /** 186 * Concatenates a word array to this word array. 187 * 188 * @param {WordArray} wordArray The word array to append. 189 * 190 * @return {WordArray} This word array. 191 * 192 * @example 193 * 194 * wordArray1.concat(wordArray2); 195 */ 196 concat: function (wordArray) { 197 // Shortcuts 198 var thisWords = this.words; 199 var thatWords = wordArray.words; 200 var thisSigBytes = this.sigBytes; 201 var thatSigBytes = wordArray.sigBytes; 202 203 // Clamp excess bits 204 this.clamp(); 205 206 // Concat 207 if (thisSigBytes % 4) { 208 // Copy one byte at a time 209 for (var i = 0; i < thatSigBytes; i++) { 210 var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; 211 thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8); 212 } 213 } else if (thatWords.length > 0xffff) { 214 // Copy one word at a time 215 for (var i = 0; i < thatSigBytes; i += 4) { 216 thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2]; 217 } 218 } else { 219 // Copy all words at once 220 thisWords.push.apply(thisWords, thatWords); 221 } 222 this.sigBytes += thatSigBytes; 223 224 // Chainable 225 return this; 226 }, 227 228 /** 229 * Removes insignificant bits. 230 * 231 * @example 232 * 233 * wordArray.clamp(); 234 */ 235 clamp: function () { 236 // Shortcuts 237 var words = this.words; 238 var sigBytes = this.sigBytes; 239 240 // Clamp 241 words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8); 242 words.length = Math.ceil(sigBytes / 4); 243 }, 244 245 /** 246 * Creates a copy of this word array. 247 * 248 * @return {WordArray} The clone. 249 * 250 * @example 251 * 252 * var clone = wordArray.clone(); 253 */ 254 clone: function () { 255 var clone = Base.clone.call(this); 256 clone.words = this.words.slice(0); 257 258 return clone; 259 }, 260 261 /** 262 * Creates a word array filled with random bytes. 263 * 264 * @param {number} nBytes The number of random bytes to generate. 265 * 266 * @return {WordArray} The random word array. 267 * 268 * @static 269 * 270 * @example 271 * 272 * var wordArray = CryptoJS.lib.WordArray.random(16); 273 */ 274 random: function (nBytes) { 275 var words = []; 276 for (var i = 0; i < nBytes; i += 4) { 277 words.push((Math.random() * 0x100000000) | 0); 278 } 279 280 return new WordArray.init(words, nBytes); 281 } 282 }); 283 284 /** 285 * Encoder namespace. 286 */ 287 var C_enc = C.enc = {}; 288 289 /** 290 * Hex encoding strategy. 291 */ 292 var Hex = C_enc.Hex = { 293 /** 294 * Converts a word array to a hex string. 295 * 296 * @param {WordArray} wordArray The word array. 297 * 298 * @return {string} The hex string. 299 * 300 * @static 301 * 302 * @example 303 * 304 * var hexString = CryptoJS.enc.Hex.stringify(wordArray); 305 */ 306 stringify: function (wordArray) { 307 // Shortcuts 308 var words = wordArray.words; 309 var sigBytes = wordArray.sigBytes; 310 311 // Convert 312 var hexChars = []; 313 for (var i = 0; i < sigBytes; i++) { 314 var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; 315 hexChars.push((bite >>> 4).toString(16)); 316 hexChars.push((bite & 0x0f).toString(16)); 317 } 318 319 return hexChars.join(''); 320 }, 321 322 /** 323 * Converts a hex string to a word array. 324 * 325 * @param {string} hexStr The hex string. 326 * 327 * @return {WordArray} The word array. 328 * 329 * @static 330 * 331 * @example 332 * 333 * var wordArray = CryptoJS.enc.Hex.parse(hexString); 334 */ 335 parse: function (hexStr) { 336 // Shortcut 337 var hexStrLength = hexStr.length; 338 339 // Convert 340 var words = []; 341 for (var i = 0; i < hexStrLength; i += 2) { 342 words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); 343 } 344 345 return new WordArray.init(words, hexStrLength / 2); 346 } 347 }; 348 349 /** 350 * Latin1 encoding strategy. 351 */ 352 var Latin1 = C_enc.Latin1 = { 353 /** 354 * Converts a word array to a Latin1 string. 355 * 356 * @param {WordArray} wordArray The word array. 357 * 358 * @return {string} The Latin1 string. 359 * 360 * @static 361 * 362 * @example 363 * 364 * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); 365 */ 366 stringify: function (wordArray) { 367 // Shortcuts 368 var words = wordArray.words; 369 var sigBytes = wordArray.sigBytes; 370 371 // Convert 372 var latin1Chars = []; 373 for (var i = 0; i < sigBytes; i++) { 374 var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; 375 latin1Chars.push(String.fromCharCode(bite)); 376 } 377 378 return latin1Chars.join(''); 379 }, 380 381 /** 382 * Converts a Latin1 string to a word array. 383 * 384 * @param {string} latin1Str The Latin1 string. 385 * 386 * @return {WordArray} The word array. 387 * 388 * @static 389 * 390 * @example 391 * 392 * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); 393 */ 394 parse: function (latin1Str) { 395 // Shortcut 396 var latin1StrLength = latin1Str.length; 397 398 // Convert 399 var words = []; 400 for (var i = 0; i < latin1StrLength; i++) { 401 words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); 402 } 403 404 return new WordArray.init(words, latin1StrLength); 405 } 406 }; 407 408 /** 409 * UTF-8 encoding strategy. 410 */ 411 var Utf8 = C_enc.Utf8 = { 412 /** 413 * Converts a word array to a UTF-8 string. 414 * 415 * @param {WordArray} wordArray The word array. 416 * 417 * @return {string} The UTF-8 string. 418 * 419 * @static 420 * 421 * @example 422 * 423 * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); 424 */ 425 stringify: function (wordArray) { 426 try { 427 return decodeURIComponent(escape(Latin1.stringify(wordArray))); 428 } catch (e) { 429 throw new Error('Malformed UTF-8 data'); 430 } 431 }, 432 433 /** 434 * Converts a UTF-8 string to a word array. 435 * 436 * @param {string} utf8Str The UTF-8 string. 437 * 438 * @return {WordArray} The word array. 439 * 440 * @static 441 * 442 * @example 443 * 444 * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); 445 */ 446 parse: function (utf8Str) { 447 return Latin1.parse(unescape(encodeURIComponent(utf8Str))); 448 } 449 }; 450 451 /** 452 * Abstract buffered block algorithm template. 453 * 454 * The property blockSize must be implemented in a concrete subtype. 455 * 456 * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0 457 */ 458 var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({ 459 /** 460 * Resets this block algorithm's data buffer to its initial state. 461 * 462 * @example 463 * 464 * bufferedBlockAlgorithm.reset(); 465 */ 466 reset: function () { 467 // Initial values 468 this._data = new WordArray.init(); 469 this._nDataBytes = 0; 470 }, 471 472 /** 473 * Adds new data to this block algorithm's buffer. 474 * 475 * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8. 476 * 477 * @example 478 * 479 * bufferedBlockAlgorithm._append('data'); 480 * bufferedBlockAlgorithm._append(wordArray); 481 */ 482 _append: function (data) { 483 // Convert string to WordArray, else assume WordArray already 484 if (typeof data == 'string') { 485 data = Utf8.parse(data); 486 } 487 488 // Append 489 this._data.concat(data); 490 this._nDataBytes += data.sigBytes; 491 }, 492 493 /** 494 * Processes available data blocks. 495 * 496 * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. 497 * 498 * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. 499 * 500 * @return {WordArray} The processed data. 501 * 502 * @example 503 * 504 * var processedData = bufferedBlockAlgorithm._process(); 505 * var processedData = bufferedBlockAlgorithm._process(!!'flush'); 506 */ 507 _process: function (doFlush) { 508 // Shortcuts 509 var data = this._data; 510 var dataWords = data.words; 511 var dataSigBytes = data.sigBytes; 512 var blockSize = this.blockSize; 513 var blockSizeBytes = blockSize * 4; 514 515 // Count blocks ready 516 var nBlocksReady = dataSigBytes / blockSizeBytes; 517 if (doFlush) { 518 // Round up to include partial blocks 519 nBlocksReady = Math.ceil(nBlocksReady); 520 } else { 521 // Round down to include only full blocks, 522 // less the number of blocks that must remain in the buffer 523 nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); 524 } 525 526 // Count words ready 527 var nWordsReady = nBlocksReady * blockSize; 528 529 // Count bytes ready 530 var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); 531 532 // Process blocks 533 if (nWordsReady) { 534 for (var offset = 0; offset < nWordsReady; offset += blockSize) { 535 // Perform concrete-algorithm logic 536 this._doProcessBlock(dataWords, offset); 537 } 538 539 // Remove processed words 540 var processedWords = dataWords.splice(0, nWordsReady); 541 data.sigBytes -= nBytesReady; 542 } 543 544 // Return processed words 545 return new WordArray.init(processedWords, nBytesReady); 546 }, 547 548 /** 549 * Creates a copy of this object. 550 * 551 * @return {Object} The clone. 552 * 553 * @example 554 * 555 * var clone = bufferedBlockAlgorithm.clone(); 556 */ 557 clone: function () { 558 var clone = Base.clone.call(this); 559 clone._data = this._data.clone(); 560 561 return clone; 562 }, 563 564 _minBufferSize: 0 565 }); 566 567 /** 568 * Abstract hasher template. 569 * 570 * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits) 571 */ 572 var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({ 573 /** 574 * Configuration options. 575 */ 576 cfg: Base.extend(), 577 578 /** 579 * Initializes a newly created hasher. 580 * 581 * @param {Object} cfg (Optional) The configuration options to use for this hash computation. 582 * 583 * @example 584 * 585 * var hasher = CryptoJS.algo.SHA256.create(); 586 */ 587 init: function (cfg) { 588 // Apply config defaults 589 this.cfg = this.cfg.extend(cfg); 590 591 // Set initial values 592 this.reset(); 593 }, 594 595 /** 596 * Resets this hasher to its initial state. 597 * 598 * @example 599 * 600 * hasher.reset(); 601 */ 602 reset: function () { 603 // Reset data buffer 604 BufferedBlockAlgorithm.reset.call(this); 605 606 // Perform concrete-hasher logic 607 this._doReset(); 608 }, 609 610 /** 611 * Updates this hasher with a message. 612 * 613 * @param {WordArray|string} messageUpdate The message to append. 614 * 615 * @return {Hasher} This hasher. 616 * 617 * @example 618 * 619 * hasher.update('message'); 620 * hasher.update(wordArray); 621 */ 622 update: function (messageUpdate) { 623 // Append 624 this._append(messageUpdate); 625 626 // Update the hash 627 this._process(); 628 629 // Chainable 630 return this; 631 }, 632 633 /** 634 * Finalizes the hash computation. 635 * Note that the finalize operation is effectively a destructive, read-once operation. 636 * 637 * @param {WordArray|string} messageUpdate (Optional) A final message update. 638 * 639 * @return {WordArray} The hash. 640 * 641 * @example 642 * 643 * var hash = hasher.finalize(); 644 * var hash = hasher.finalize('message'); 645 * var hash = hasher.finalize(wordArray); 646 */ 647 finalize: function (messageUpdate) { 648 // Final message update 649 if (messageUpdate) { 650 this._append(messageUpdate); 651 } 652 653 // Perform concrete-hasher logic 654 var hash = this._doFinalize(); 655 656 return hash; 657 }, 658 659 blockSize: 512/32, 660 661 /** 662 * Creates a shortcut function to a hasher's object interface. 663 * 664 * @param {Hasher} hasher The hasher to create a helper for. 665 * 666 * @return {Function} The shortcut function. 667 * 668 * @static 669 * 670 * @example 671 * 672 * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); 673 */ 674 _createHelper: function (hasher) { 675 return function (message, cfg) { 676 return new hasher.init(cfg).finalize(message); 677 }; 678 }, 679 680 /** 681 * Creates a shortcut function to the HMAC's object interface. 682 * 683 * @param {Hasher} hasher The hasher to use in this HMAC helper. 684 * 685 * @return {Function} The shortcut function. 686 * 687 * @static 688 * 689 * @example 690 * 691 * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); 692 */ 693 _createHmacHelper: function (hasher) { 694 return function (message, key) { 695 return new C_algo.HMAC.init(hasher, key).finalize(message); 696 }; 697 } 698 }); 699 700 /** 701 * Algorithm namespace. 702 */ 703 var C_algo = C.algo = {}; 704 705 return C; 706 }(Math));