1/* 2 * jCryption JavaScript data encryption v1.2 3 * http://www.jcryption.org/ 4 * 5 * Copyright (c) 2010 Daniel Griesser 6 * Dual licensed under the MIT and GPL licenses. 7 * http://www.opensource.org/licenses/mit-license.php 8 * http://www.opensource.org/licenses/gpl-2.0.php 9 * 10 * If you need any further information about this plugin please 11 * visit my homepage or contact me under [email protected] 12 */ 13 14(function($) { 15 $.jCryption = function(el, options) { 16 var base = this; 17 18 base.$el = $(el); 19 base.el = el; 20 21 base.$el.data("jCryption", base); 22 base.$el.data("salt", null); 23 base.$el.data("key", null); 24 25 base.init = function() { 26 base.options = $.extend({}, $.jCryption.defaultOptions, options); 27 28 // Making a good random salt 29 base.$el.bind('mousemove', function(e) { 30 if (base.$el.data("salt") === null) { 31 base.$el.data("salt", (e.pageX + e.pageY) * Math.random()); 32 } else { 33 base.$el.unbind('mousemove'); 34 } 35 }); 36 37 $encryptedElement = $("<input />",{ 38 type:'hidden', 39 name:base.options.postVariable 40 }); 41 42 if (base.options.submitElement !== false) { 43 var $submitElement = base.options.submitElement; 44 } else { 45 var $submitElement = base.$el.find(":input:submit"); 46 } 47 48 $submitElement.bind(base.options.submitEvent, function() { 49 $(this).attr("disabled", true); 50 if (base.options.beforeEncryption()) { 51 base.authenticate( 52 function(AESEncryptionKey) { 53 var toEncrypt = base.$el.serialize(); 54 if ($submitElement.is(":submit")) { 55 toEncrypt = toEncrypt + "&" + $submitElement.attr("name") + "=" + $submitElement.val(); 56 } 57 $encryptedElement.val($.jCryption.encrypt(toEncrypt, AESEncryptionKey)); 58 $(base.$el).find(base.options.formFieldSelector) 59 .attr("disabled", true).end() 60 .append($encryptedElement).submit(); 61 }, 62 function() { 63 // Authentication with AES Failed ... sending form without protection 64 $(base.$el).submit(); 65 } 66 ); 67 } 68 return false; 69 }); 70 }; 71 72 base.init(); 73 74 /** 75 * Creates a random string(key) for use in the AES algorithm 76 */ 77 base.getKey = function() { 78 if (base.$el.data("key") !== null) { 79 return base.$el.data("key"); 80 } 81 // no good salt available 82 var seed = base.$el.data("salt"); 83 if (seed === null) { 84 // generating weak seed 85 seed = Math.floor(Math.random() * Math.random()); 86 } 87 var hashObj = new jsSHA(seed.toString(), "ASCII"); 88 base.$el.data("key", hashObj.getHash("SHA-512", "HEX")); 89 return base.getKey(); 90 }; 91 92 /** 93 * Authenticate with the server (One way) 94 * @param {function} success The function to call if the operation was successfull 95 * @param {function} failure The function to call if an error has occurred 96 */ 97 base.authenticate = function(token,success, failure) { 98 var key = base.getKey(); 99 $.jCryption.authenticate(key, base.options.getKeysURL, base.options.handshakeURL,token, success, failure); 100 }; 101 }; 102 103 /** 104 * Authenticates with the server 105 * @param {string} AESEncryptionKey The AES key 106 * @param {string} publicKeyURL The public key URL 107 * @param {string} handshakeURL The handshake URL 108 * @param {function} success The function to call if the operation was successfull 109 * @param {function} failure The function to call if an error has occurred 110 */ 111 $.jCryption.authenticate = function(AESEncryptionKey, publicKeyURL, handshakeURL,token, success, failure) { 112 $.jCryption.getKeys(publicKeyURL, function(keys) {
113 $.jCryption.encryptKey(AESEncryptionKey, keys, function(encryptedKey) { 114 $.jCryption.handshake(handshakeURL, encryptedKey,token, function(response) { 115 if ($.jCryption.challenge(response.challenge, AESEncryptionKey)) { 116 success.call(this, AESEncryptionKey); 117 } else { 118 failure.call(this); 119 } 120 }); 121 }); 122 }); 123 }; 124 125 /** 126 * Gets the RSA keys from the specified url, and saves it into a RSA keypair 127 * @param {string} url The url to contact 128 * @param {function} callback The function to call when the operation has finshed 129 */ 130 $.jCryption.getKeys = function(url, callback) { 131 var jCryptionKeyPair = function(encryptionExponent, modulus, maxdigits) { 132 setMaxDigits(parseInt(maxdigits,10)); 133 this.e = biFromHex(encryptionExponent); 134 this.m = biFromHex(modulus); 135 this.chunkSize = 2 * biHighIndex(this.m); 136 this.radix = 16; 137 this.barrett = new BarrettMu(this.m); 138 }; 139 140 /** 141 * Gets the data from the specified url, and converts it into a RSA keypair 142 * @param {string} url The URL to contact 143 * @param {string} data The JSON data 144 */ 145 $.getJSON(url, function(data) { 146 var keys = new jCryptionKeyPair(data.e, data.n, data.maxdigits); 147 if($.isFunction(callback)) { 148 callback.call(this, keys); 149 } 150 }); 151 }; 152 153 /** 154 * Decrypts data using AES 256 155 * @param {string} data The data to decrypt(Ciphertext) 156 * @param {string} key The AES key 157 * @returns {string} The result of the decryption(Plaintext) 158 */ 159 $.jCryption.decrypt = function(data, key) { 160 return Aes.Ctr.decrypt(data, key , 256); 161 }; 162 163 /** 164 * Encrypts data using AES 256 165 * @param {string} data The data to encrypt(Plaintext) 166 * @param {string} key The AES key 167 * @returns {string} The result of the encryption(Ciphertext) 168 */ 169 $.jCryption.encrypt = function(data, key) { 170 return Aes.Ctr.encrypt(data, key , 256); 171 }; 172 173 /** 174 * Makes sure that the challenge the client sent, is correct 175 * @param {string} challenge The challenge string 176 * @param {string} key The AES key 177 */ 178 $.jCryption.challenge = function(challenge, key) { 179 if ($.jCryption.decrypt(challenge, key) == key) { 180 return true; 181 } 182 return false; 183 }; 184 185 /** 186 * Executes a handshake with the server 187 * @param {string} url The url to connect to 188 * @param {string} key The encrypted AES key 189 * @param {function} callback The function to call when the handshaking has finished 190 */ 191 $.jCryption.handshake = function(url, key,token, callback) { 192 $.ajax({ 193 url: url, 194 dataType: "json", 195 type: "POST", 196 data: { 197 key: key,csrf_jencrypt_name:token 198 }, 199 success: function(response) { 200 callback.call(this, response); 201 } 202 }); 203 }; 204 205 /** 206 * Encrypts the AES key using RSA 207 * @param {string} string The AES key 208 * @param {keypair} keyPair The RSA keypair to use 209 * @param {function} callback The function to call when the encryption has finished 210 */ 211 $.jCryption.encryptKey = function(string, keyPair, callback) { 212 var charSum = 0; 213 for(var i = 0; i < string.length; i++){ 214 charSum += string.charCodeAt(i); 215 } 216 var tag = '0123456789abcdef'; 217 var hex = ''; 218 hex += tag.charAt((charSum & 0xF0) >> 4) + tag.charAt(charSum & 0x0F); 219 220 var taggedString = hex + string; 221 222 var encrypt = []; 223 var j = 0; 224 225 while (j < taggedString.length) { 226 encrypt[j] = taggedString.charCodeAt(j); 227 j++; 228 } 229 230 while (encrypt.length % keyPair.chunkSize !== 0) { 231 encrypt[j++] = 0; 232 } 233 234 function encryption(encryptObject) { 235 var charCounter = 0; 236 var j, block; 237 var encrypted = ""; 238 function encryptChar() { 239 block = new BigInt(); 240 j = 0; 241 for (var k = charCounter; k < charCounter+keyPair.chunkSize;
241 ++j) { 242 block.digits[j] = encryptObject[k++]; 243 block.digits[j] += encryptObject[k++] << 8; 244 } 245 var crypt = keyPair.barrett.powMod(block, keyPair.e); 246 var text = keyPair.radix == 16 ? biToHex(crypt) : biToString(crypt, keyPair.radix); 247 encrypted += text + " "; 248 charCounter += keyPair.chunkSize; 249 if (charCounter < encryptObject.length) { 250 setTimeout(encryptChar, 1) 251 } else { 252 var encryptedString = encrypted.substring(0, encrypted.length - 1); 253 if($.isFunction(callback)) { 254 callback(encryptedString); 255 } else { 256 return encryptedString; 257 } 258 259 } 260 } 261 setTimeout(encryptChar, 1); 262 } 263 264 encryption(encrypt); 265 }; 266 267 $.jCryption.defaultOptions = { 268 submitElement: false, 269 submitEvent: "click", 270 getKeysURL: "main.php?generateKeypair=true", 271 handshakeURL: "main.php?handshake=true", 272 beforeEncryption: function() { return true }, 273 postVariable: "jCryption", 274 formFieldSelector: ":input" 275 }; 276 277 $.fn.jCryption = function(options) { 278 return this.each(function(){ 279 (new $.jCryption(this, options)); 280 }); 281 }; 282 283})(jQuery); 284 285 286/* 287 * BigInt, a suite of routines for performing multiple-precision arithmetic in 288 * JavaScript. 289 * BarrettMu, a class for performing Barrett modular reduction computations in 290 * JavaScript. 291 * 292 * 293 * Copyright 1998-2005 David Shapiro. 294 * [email protected] 295 * 296 * changed and improved by Daniel Griesser 297 * http://www.jcryption.org/ 298 * Daniel Griesser <[email protected]> 299 */ 300var biRadixBase = 2; 301var biRadixBits = 16; 302var bitsPerDigit = biRadixBits; 303var biRadix = 1 << 16; 304var biHalfRadix = biRadix >>> 1; 305var biRadixSquared = biRadix * biRadix; 306var maxDigitVal = biRadix - 1; 307var maxInteger = 9999999999999998; 308var maxDigits; 309var ZERO_ARRAY; 310var bigZero, bigOne; 311var dpl10 = 15; 312var highBitMasks = new Array(0x0000, 0x8000, 0xC000, 0xE000, 0xF000, 0xF800, 313 0xFC00, 0xFE00, 0xFF00, 0xFF80, 0xFFC0, 0xFFE0, 314 0xFFF0, 0xFFF8, 0xFFFC, 0xFFFE, 0xFFFF); 315 316var hexatrigesimalToChar = new Array( 317 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 318 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 319 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 320 'u', 'v', 'w', 'x', 'y', 'z' 321); 322 323var hexToChar = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 324 'a', 'b', 'c', 'd', 'e', 'f'); 325 326var lowBitMasks = new Array(0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 327 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 328 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF); 329 330function setMaxDigits(value) { 331 maxDigits = value; 332 ZERO_ARRAY = new Array(maxDigits); 333 for (var iza = 0; iza < ZERO_ARRAY.length; iza++) ZERO_ARRAY[iza] = 0; 334 bigZero = new BigInt(); 335 bigOne = new BigInt(); 336 bigOne.digits[0] = 1; 337} 338 339function BigInt(flag) { 340 if (typeof flag == "boolean" && flag == true) { 341 this.digits = null; 342 } 343 else { 344 this.digits = ZERO_ARRAY.slice(0); 345 } 346 this.isNeg = false; 347} 348 349function biFromDecimal(s) { 350 var isNeg = s.charAt(0) == '-'; 351 var i = isNeg ? 1 : 0; 352 var result; 353 while (i < s.length && s.charAt(i) == '0') ++i; 354 if (i == s.length) { 355 result = new BigInt(); 356 } 357 else { 358 var digitCount = s.length - i; 359 var fgl = digitCount % dpl10; 360 if (fgl == 0) fgl = dpl10; 361 result = biFromNumber(Number(s.substr(i, fgl))); 362 i += fgl; 363 while (i < s.length) { 364 result = biAdd(biMultiply(result, biFromNumber(1000000000000000)), 365 biFromNumber(Number(s.substr(i, dpl10)))); 366 i += dpl10; 367 } 368 result.isNeg = isNeg; 369 } 370 return result; 371} 372 373function biCopy(bi) { 374 var result = new BigInt(true); 375 result.digits = bi.digits.slice(0); 376 result.isNeg = bi.isNeg; 377 return result; 378} 379 380function biFromNumber(i) { 381 var result = new BigInt(); 382 result.isNeg = i < 0; 383 i = Math.abs(i); 384 var j = 0; 385 while (i > 0) { 386 result.digits[j++] = i & maxDigitVal;
387 i >>= biRadixBits; 388 } 389 return result; 390} 391 392function reverseStr(s) { 393 var result = ""; 394 for (var i = s.length - 1; i > -1; --i) { 395 result += s.charAt(i); 396 } 397 return result; 398} 399 400function biToString(x, radix) { 401 var b = new BigInt(); 402 b.digits[0] = radix; 403 var qr = biDivideModulo(x, b); 404 var result = hexatrigesimalToChar[qr[1].digits[0]]; 405 while (biCompare(qr[0], bigZero) == 1) { 406 qr = biDivideModulo(qr[0], b); 407 digit = qr[1].digits[0]; 408 result += hexatrigesimalToChar[qr[1].digits[0]]; 409 } 410 return (x.isNeg ? "-" : "") + reverseStr(result); 411} 412 413function biToDecimal(x) { 414 var b = new BigInt(); 415 b.digits[0] = 10; 416 var qr = biDivideModulo(x, b); 417 var result = String(qr[1].digits[0]); 418 while (biCompare(qr[0], bigZero) == 1) { 419 qr = biDivideModulo(qr[0], b); 420 result += String(qr[1].digits[0]); 421 } 422 return (x.isNeg ? "-" : "") + reverseStr(result); 423} 424 425function digitToHex(n) { 426 var mask = 0xf; 427 var result = ""; 428 for (i = 0; i < 4; ++i) { 429 result += hexToChar[n & mask]; 430 n >>>= 4; 431 } 432 return reverseStr(result); 433} 434 435function biToHex(x) { 436 var result = ""; 437 var n = biHighIndex(x); 438 for (var i = biHighIndex(x); i > -1; --i) { 439 result += digitToHex(x.digits[i]); 440 } 441 return result; 442} 443 444function charToHex(c) { 445 var ZERO = 48; 446 var NINE = ZERO + 9; 447 var littleA = 97; 448 var littleZ = littleA + 25; 449 var bigA = 65; 450 var bigZ = 65 + 25; 451 var result; 452 453 if (c >= ZERO && c <= NINE) { 454 result = c - ZERO; 455 } else if (c >= bigA && c <= bigZ) { 456 result = 10 + c - bigA; 457 } else if (c >= littleA && c <= littleZ) { 458 result = 10 + c - littleA; 459 } else { 460 result = 0; 461 } 462 return result; 463} 464 465function hexToDigit(s) { 466 var result = 0; 467 var sl = Math.min(s.length, 4); 468 for (var i = 0; i < sl; ++i) { 469 result <<= 4; 470 result |= charToHex(s.charCodeAt(i)) 471 } 472 return result; 473} 474 475function biFromHex(s) { 476 var result = new BigInt(); 477 var sl = s.length; 478 for (var i = sl, j = 0; i > 0; i -= 4, ++j) { 479 result.digits[j] = hexToDigit(s.substr(Math.max(i - 4, 0), Math.min(i, 4))); 480 } 481 return result; 482} 483 484function biFromString(s, radix) { 485 var isNeg = s.charAt(0) == '-'; 486 var istop = isNeg ? 1 : 0; 487 var result = new BigInt(); 488 var place = new BigInt(); 489 place.digits[0] = 1; // radix^0 490 for (var i = s.length - 1; i >= istop; i--) { 491 var c = s.charCodeAt(i); 492 var digit = charToHex(c); 493 var biDigit = biMultiplyDigit(place, digit); 494 result = biAdd(result, biDigit); 495 place = biMultiplyDigit(place, radix); 496 } 497 result.isNeg = isNeg; 498 return result; 499} 500 501function biDump(b) { 502 return (b.isNeg ? "-" : "") + b.digits.join(" "); 503} 504 505function biAdd(x, y) { 506 var result; 507 508 if (x.isNeg != y.isNeg) { 509 y.isNeg = !y.isNeg; 510 result = biSubtract(x, y); 511 y.isNeg = !y.isNeg; 512 } 513 else { 514 result = new BigInt(); 515 var c = 0; 516 var n; 517 for (var i = 0; i < x.digits.length; ++i) { 518 n = x.digits[i] + y.digits[i] + c; 519 result.digits[i] = n & 0xffff; 520 c = Number(n >= biRadix); 521 } 522 result.isNeg = x.isNeg; 523 } 524 return result; 525} 526 527function biSubtract(x, y) { 528 var result; 529 if (x.isNeg != y.isNeg) { 530 y.isNeg = !y.isNeg; 531 result = biAdd(x, y); 532 y.isNeg = !y.isNeg; 533 } else { 534 result = new BigInt(); 535 var n, c; 536 c = 0; 537 for (var i = 0; i < x.digits.length; ++i) { 538 n = x.digits[i] - y.digits[i] + c; 539 result.digits[i] = n & 0xffff; 540 if (result.digits[i] < 0) result.digits[i] += biRadix; 541 c = 0 - Number(n < 0); 542 } 543 if (c == -1) { 544 c = 0; 545 for (var i = 0; i < x.digits.length; ++i) { 546 n = 0 - result.digits[i] + c; 547 result.digits[i] = n & 0xffff; 548 if (result.digits[i] < 0) result.digits[i] += biRadix; 549 c = 0 - Number(n < 0); 550 } 551 result.isNeg = !x.isNeg; 552 } else { 553 result.isNeg = x.isNeg; 554 } 555 } 556 return result; 557} 558 559function biHighIndex(x) { 560 var result = x.digits.length - 1; 561 while (result > 0 && x.digits[result] == 0) --result; 562 return result; 563} 564 565function biNumBits(x) { 566 var n = biHighIndex(x); 567 var d = x.digits[n]; 568 var m = (n + 1) * bitsPerDigit; 569 var result; 570 for (result = m; result > m - bitsPerDigit; --result) { 571 if ((d & 0x8000) != 0) break; 572 d <<= 1; 573 } 574 return result; 575} 576 577function biMultiply(x, y) { 578 var result = new BigInt(); 579 var c; 580 var n = biHighIndex(x);
581 var t = biHighIndex(y); 582 var u, uv, k; 583 584 for (var i = 0; i <= t; ++i) { 585 c = 0; 586 k = i; 587 for (j = 0; j <= n; ++j, ++k) { 588 uv = result.digits[k] + x.digits[j] * y.digits[i] + c; 589 result.digits[k] = uv & maxDigitVal; 590 c = uv >>> biRadixBits; 591 } 592 result.digits[i + n + 1] = c; 593 } 594 result.isNeg = x.isNeg != y.isNeg; 595 return result; 596} 597 598function biMultiplyDigit(x, y) { 599 var n, c, uv; 600 var result = new BigInt(); 601 n = biHighIndex(x); 602 c = 0; 603 for (var j = 0; j <= n; ++j) { 604 uv = result.digits[j] + x.digits[j] * y + c; 605 result.digits[j] = uv & maxDigitVal; 606 c = uv >>> biRadixBits; 607 } 608 result.digits[1 + n] = c; 609 return result; 610} 611 612function arrayCopy(src, srcStart, dest, destStart, n) { 613 var m = Math.min(srcStart + n, src.length); 614 for (var i = srcStart, j = destStart; i < m; ++i, ++j) { 615 dest[j] = src[i]; 616 } 617} 618 619 620 621function biShiftLeft(x, n) { 622 var digitCount = Math.floor(n / bitsPerDigit); 623 var result = new BigInt(); 624 arrayCopy(x.digits, 0, result.digits, digitCount,result.digits.length - digitCount); 625 var bits = n % bitsPerDigit; 626 var rightBits = bitsPerDigit - bits; 627 for (var i = result.digits.length - 1, i1 = i - 1; i > 0; --i, --i1) { 628 result.digits[i] = ((result.digits[i] << bits) & maxDigitVal) | 629 ((result.digits[i1] & highBitMasks[bits]) >>> 630 (rightBits)); 631 } 632 result.digits[0] = ((result.digits[i] << bits) & maxDigitVal); 633 result.isNeg = x.isNeg; 634 return result; 635} 636 637function biShiftRight(x, n) { 638 var digitCount = Math.floor(n / bitsPerDigit); 639 var result = new BigInt(); 640 arrayCopy(x.digits, digitCount, result.digits, 0,x.digits.length - digitCount); 641 var bits = n % bitsPerDigit; 642 var leftBits = bitsPerDigit - bits; 643 for (var i = 0, i1 = i + 1; i < result.digits.length - 1; ++i, ++i1) { 644 result.digits[i] = (result.digits[i] >>> bits) | 645 ((result.digits[i1] & lowBitMasks[bits]) << leftBits); 646 } 647 result.digits[result.digits.length - 1] >>>= bits; 648 result.isNeg = x.isNeg; 649 return result; 650} 651 652function biMultiplyByRadixPower(x, n) { 653 var result = new BigInt(); 654 arrayCopy(x.digits, 0, result.digits, n, result.digits.length - n); 655 return result; 656} 657 658function biDivideByRadixPower(x, n) 659{ 660 var result = new BigInt(); 661 arrayCopy(x.digits, n, result.digits, 0, result.digits.length - n); 662 return result; 663} 664 665function biModuloByRadixPower(x, n) 666{ 667 var result = new BigInt(); 668 arrayCopy(x.digits, 0, result.digits, 0, n); 669 return result; 670} 671 672function biCompare(x, y) { 673 if (x.isNeg != y.isNeg) { 674 return 1 - 2 * Number(x.isNeg); 675 } 676 for (var i = x.digits.length - 1; i >= 0; --i) { 677 if (x.digits[i] != y.digits[i]) { 678 if (x.isNeg) { 679 return 1 - 2 * Number(x.digits[i] > y.digits[i]); 680 } else { 681 return 1 - 2 * Number(x.digits[i] < y.digits[i]); 682 } 683 } 684 } 685 return 0; 686} 687 688function biDivideModulo(x, y) { 689 var nb = biNumBits(x); 690 var tb = biNumBits(y); 691 var origYIsNeg = y.isNeg; 692 var q, r; 693 if (nb < tb) { 694 if (x.isNeg) { 695 q = biCopy(bigOne); 696 q.isNeg = !y.isNeg; 697 x.isNeg = false; 698 y.isNeg = false; 699 r = biSubtract(y, x); 700 x.isNeg = true; 701 y.isNeg = origYIsNeg; 702 } else { 703 q = new BigInt(); 704 r = biCopy(x); 705 } 706 return new Array(q, r); 707 } 708 709 q = new BigInt(); 710 r = x; 711 712 var t = Math.ceil(tb / bitsPerDigit) - 1; 713 var lambda = 0; 714 while (y.digits[t] < biHalfRadix) { 715 y = biShiftLeft(y, 1); 716 ++lambda; 717 ++tb; 718 t = Math.ceil(tb / bitsPerDigit) - 1; 719 } 720 721 r = biShiftLeft(r, lambda); 722 nb += lambda; 723 var n = Math.ceil(nb / bitsPerDigit) - 1; 724 725 var b = biMultiplyByRadixPower(y, n - t); 726 while (biCompare(r, b) != -1) { 727 ++q.digits[n - t]; 728 r = biSubtract(r, b); 729 } 730 for (var i = n; i > t; --i) { 731 var ri = (i >= r.digits.length) ? 0 : r.digits[i]; 732 var ri1 = (i - 1 >= r.digits.length) ? 0 : r.digits[i - 1]; 733 var ri2 = (i - 2 >= r.digits.length) ? 0 : r.digits[i - 2]; 734 var yt = (t >= y.digits.length) ? 0 : y.digits[t]; 735 var yt1 = (t - 1 >= y.digits.length) ? 0 : y.digits[t - 1]; 736 if (ri == yt) { 737 q.digits[i - t - 1] = maxDigitVal;
738 } else { 739 q.digits[i - t - 1] = Math.floor((ri * biRadix + ri1) / yt); 740 } 741 742 var c1 = q.digits[i - t - 1] * ((yt * biRadix) + yt1); 743 var c2 = (ri * biRadixSquared) + ((ri1 * biRadix) + ri2); 744 while (c1 > c2) { 745 --q.digits[i - t - 1]; 746 c1 = q.digits[i - t - 1] * ((yt * biRadix) | yt1); 747 c2 = (ri * biRadix * biRadix) + ((ri1 * biRadix) + ri2); 748 } 749 750 b = biMultiplyByRadixPower(y, i - t - 1); 751 r = biSubtract(r, biMultiplyDigit(b, q.digits[i - t - 1])); 752 if (r.isNeg) { 753 r = biAdd(r, b); 754 --q.digits[i - t - 1]; 755 } 756 } 757 r = biShiftRight(r, lambda); 758 759 q.isNeg = x.isNeg != origYIsNeg; 760 if (x.isNeg) { 761 if (origYIsNeg) { 762 q = biAdd(q, bigOne); 763 } else { 764 q = biSubtract(q, bigOne); 765 } 766 y = biShiftRight(y, lambda); 767 r = biSubtract(y, r); 768 } 769 770 if (r.digits[0] == 0 && biHighIndex(r) == 0) r.isNeg = false; 771 772 return new Array(q, r); 773} 774 775function biDivide(x, y) { 776 return biDivideModulo(x, y)[0]; 777} 778 779function biModulo(x, y) { 780 return biDivideModulo(x, y)[1]; 781} 782 783function biMultiplyMod(x, y, m) { 784 return biModulo(biMultiply(x, y), m); 785} 786 787function biPow(x, y) { 788 var result = bigOne; 789 var a = x; 790 while (true) { 791 if ((y & 1) != 0) result = biMultiply(result, a); 792 y >>= 1; 793 if (y == 0) break; 794 a = biMultiply(a, a); 795 } 796 return result; 797} 798 799function biPowMod(x, y, m) { 800 var result = bigOne; 801 var a = x; 802 var k = y; 803 while (true) { 804 if ((k.digits[0] & 1) != 0) result = biMultiplyMod(result, a, m); 805 k = biShiftRight(k, 1); 806 if (k.digits[0] == 0 && biHighIndex(k) == 0) break; 807 a = biMultiplyMod(a, a, m); 808 } 809 return result; 810} 811 812function BarrettMu(m) { 813 this.modulus = biCopy(m); 814 this.k = biHighIndex(this.modulus) + 1; 815 var b2k = new BigInt(); 816 b2k.digits[2 * this.k] = 1; 817 this.mu = biDivide(b2k, this.modulus); 818 this.bkplus1 = new BigInt(); 819 this.bkplus1.digits[this.k + 1] = 1; 820 this.modulo = BarrettMu_modulo; 821 this.multiplyMod = BarrettMu_multiplyMod; 822 this.powMod = BarrettMu_powMod; 823} 824 825function BarrettMu_modulo(x) { 826 var q1 = biDivideByRadixPower(x, this.k - 1); 827 var q2 = biMultiply(q1, this.mu); 828 var q3 = biDivideByRadixPower(q2, this.k + 1); 829 var r1 = biModuloByRadixPower(x, this.k + 1); 830 var r2term = biMultiply(q3, this.modulus); 831 var r2 = biModuloByRadixPower(r2term, this.k + 1); 832 var r = biSubtract(r1, r2); 833 if (r.isNeg) { 834 r = biAdd(r, this.bkplus1); 835 } 836 var rgtem = biCompare(r, this.modulus) >= 0; 837 while (rgtem) { 838 r = biSubtract(r, this.modulus); 839 rgtem = biCompare(r, this.modulus) >= 0; 840 } 841 return r; 842} 843 844function BarrettMu_multiplyMod(x, y) { 845 var xy = biMultiply(x, y); 846 return this.modulo(xy); 847} 848 849function BarrettMu_powMod(x, y) { 850 var result = new BigInt(); 851 result.digits[0] = 1; 852 while (true) { 853 if ((y.digits[0] & 1) != 0) result = this.multiplyMod(result, x); 854 y = biShiftRight(y, 1); 855 if (y.digits[0] == 0 && biHighIndex(y) == 0) break; 856 x = this.multiplyMod(x, x); 857 } 858 return result; 859} 860 861 862/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 863/* AES implementation in JavaScript (c) Chris Veness 2005-2011 */ 864/* - see http://csrc.nist.gov/publications/PubsFIPS.html#197 */ 865/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 866 867var Aes = {}; // Aes namespace 868 869/** 870 * AES Cipher function: encrypt 'input' state with Rijndael algorithm 871 * applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage 872 * 873 * @param {Number[]} input 16-byte (128-bit) input state array 874 * @param {Number[][]} w Key schedule as 2D byte-array (Nr+1 x Nb bytes) 875 * @returns {Number[]} Encrypted output state array 876 */ 877Aes.cipher = function(input, w) { // main Cipher function [§5.1] 878 var Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES) 879 var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys 880 881 var state = [[],[],[],[]]; // initialise 4xNb byte-array 'state' with input [§3.4] 882 for (var i=0; i<4*Nb;
882 i++) state[i%4][Math.floor(i/4)] = input[i]; 883 884 state = Aes.addRoundKey(state, w, 0, Nb); 885 886 for (var round=1; round<Nr; round++) { 887 state = Aes.subBytes(state, Nb); 888 state = Aes.shiftRows(state, Nb); 889 state = Aes.mixColumns(state, Nb); 890 state = Aes.addRoundKey(state, w, round, Nb); 891 } 892 893 state = Aes.subBytes(state, Nb); 894 state = Aes.shiftRows(state, Nb); 895 state = Aes.addRoundKey(state, w, Nr, Nb); 896 897 var output = new Array(4*Nb); // convert state to 1-d array before returning [§3.4] 898 for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)]; 899 return output; 900} 901 902/** 903 * Perform Key Expansion to generate a Key Schedule 904 * 905 * @param {Number[]} key Key as 16/24/32-byte array 906 * @returns {Number[][]} Expanded key schedule as 2D byte-array (Nr+1 x Nb bytes) 907 */ 908Aes.keyExpansion = function(key) { // generate Key Schedule (byte-array Nr+1 x Nb) from Key [§5.2] 909 var Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES) 910 var Nk = key.length/4 // key length (in words): 4/6/8 for 128/192/256-bit keys 911 var Nr = Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys 912 913 var w = new Array(Nb*(Nr+1)); 914 var temp = new Array(4); 915 916 for (var i=0; i<Nk; i++) { 917 var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]]; 918 w[i] = r; 919 } 920 921 for (var i=Nk; i<(Nb*(Nr+1)); i++) { 922 w[i] = new Array(4); 923 for (var t=0; t<4; t++) temp[t] = w[i-1][t]; 924 if (i % Nk == 0) { 925 temp = Aes.subWord(Aes.rotWord(temp)); 926 for (var t=0; t<4; t++) temp[t] ^= Aes.rCon[i/Nk][t]; 927 } else if (Nk > 6 && i%Nk == 4) { 928 temp = Aes.subWord(temp); 929 } 930 for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t]; 931 } 932 933 return w; 934} 935 936/* 937 * ---- remaining routines are private, not called externally ---- 938 */ 939 940Aes.subBytes = function(s, Nb) { // apply SBox to state S [§5.1.1] 941 for (var r=0; r<4; r++) { 942 for (var c=0; c<Nb; c++) s[r][c] = Aes.sBox[s[r][c]]; 943 } 944 return s; 945} 946 947Aes.shiftRows = function(s, Nb) { // shift row r of state S left by r bytes [§5.1.2] 948 var t = new Array(4); 949 for (var r=1; r<4; r++) { 950 for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb]; // shift into temp copy 951 for (var c=0; c<4; c++) s[r][c] = t[c]; // and copy back 952 } // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES): 953 return s; // see asmaes.sourceforge.net/rijndael/rijndaelImplementation.pdf 954} 955 956Aes.mixColumns = function(s, Nb) { // combine bytes of each col of state S [§5.1.3] 957 for (var c=0; c<4; c++) { 958 var a = new Array(4); // 'a' is a copy of the current column from 's' 959 var b = new Array(4); // 'b' is a•{02} in GF(2^8) 960 for (var i=0; i<4; i++) { 961 a[i] = s[i][c]; 962 b[i] = s[i][c]&0x80 ? s[i][c]<<1 ^ 0x011b : s[i][c]<<1; 963 964 } 965 // a[n] ^ b[n] is a•{03} in GF(2^8) 966 s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; // 2*a0 + 3*a1 + a2 + a3 967 s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; // a0 * 2*a1 + 3*a2 + a3 968 s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; // a0 + a1 + 2*a2 + 3*a3 969 s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; // 3*a0 + a1 + a2 + 2*a3 970 } 971 return s; 972} 973 974Aes.addRoundKey = function(state, w, rnd, Nb) { // xor Round Key into state S [§5.1.4] 975 for (var r=0; r<4; r++) { 976 for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r]; 977 } 978 return state; 979} 980 981Aes.subWord = function(w) { // apply SBox to 4-byte word w 982 for (var i=0; i<4; i++) w[i] = Aes.sBox[w[i]]; 983 return w; 984} 985 986Aes.rotWord = function(w) { // rotate 4-byte word w left by one byte 987 var tmp = w[0]; 988 for (var i=0; i<3; i++) w[i] = w[i+1]; 989 w[3] = tmp; 990 return w; 991} 992 993// sBox is pre-computed multiplicative inverse in GF(2^8) used in subBytes and keyExpansion [§5.1.1] 994Aes.sBox = [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, 995 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, 996 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, 997 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, 998 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, 999 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, 1000 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, 1001 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, 1002 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
1003 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, 1004 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, 1005 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, 1006 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, 1007 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, 1008 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, 1009 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16]; 1010 1011// rCon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2] 1012Aes.rCon = [ [0x00, 0x00, 0x00, 0x00], 1013 [0x01, 0x00, 0x00, 0x00], 1014 [0x02, 0x00, 0x00, 0x00], 1015 [0x04, 0x00, 0x00, 0x00], 1016 [0x08, 0x00, 0x00, 0x00], 1017 [0x10, 0x00, 0x00, 0x00], 1018 [0x20, 0x00, 0x00, 0x00], 1019 [0x40, 0x00, 0x00, 0x00], 1020 [0x80, 0x00, 0x00, 0x00], 1021 [0x1b, 0x00, 0x00, 0x00], 1022 [0x36, 0x00, 0x00, 0x00] ]; 1023 1024 1025/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1026/* AES Counter-mode implementation in JavaScript (c) Chris Veness 2005-2011 */ 1027/* - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */ 1028/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1029 1030Aes.Ctr = {}; // Aes.Ctr namespace: a subclass or extension of Aes 1031 1032/** 1033 * Encrypt a text using AES encryption in Counter mode of operation 1034 * 1035 * Unicode multi-byte character safe 1036 * 1037 * @param {String} plaintext Source text to be encrypted 1038 * @param {String} password The password to use to generate a key 1039 * @param {Number} nBits Number of bits to be used in the key (128, 192, or 256) 1040 * @returns {string} Encrypted text 1041 */ 1042Aes.Ctr.encrypt = function(plaintext, password, nBits) { 1043 var blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES 1044 if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys 1045 plaintext = Utf8.encode(plaintext); 1046 password = Utf8.encode(password); 1047 //var t = new Date(); // timer 1048 1049 // use AES itself to encrypt password to get cipher key (using plain password as source for key 1050 // expansion) - gives us well encrypted key (though hashed key might be preferred for prod'n use) 1051 var nBytes = nBits/8; // no bytes in key (16/24/32) 1052 var pwBytes = new Array(nBytes); 1053 for (var i=0; i<nBytes; i++) { // use 1st 16/24/32 chars of password for key 1054 pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i); 1055 } 1056 var key = Aes.cipher(pwBytes, Aes.keyExpansion(pwBytes)); // gives us 16-byte key 1057 key = key.concat(key.slice(0, nBytes-16)); // expand key to 16/24/32 bytes long 1058 1059 // initialise 1st 8 bytes of counter block with nonce (NIST SP800-38A §B.2): [0-1] = millisec, 1060 // [2-3] = random, [4-7] = seconds, together giving full sub-millisec uniqueness up to Feb 2106 1061 var counterBlock = new Array(blockSize); 1062 1063 var nonce = (new Date()).getTime(); // timestamp: milliseconds since 1-Jan-1970 1064 var nonceMs = nonce%1000; 1065 var nonceSec = Math.floor(nonce/1000); 1066 var nonceRnd = Math.floor(Math.random()*0xffff); 1067 1068 for (var i=0; i<2; i++) counterBlock[i] = (nonceMs >>> i*8) & 0xff; 1069 for (var i=0; i<2; i++) counterBlock[i+2] = (nonceRnd >>> i*8) & 0xff; 1070 for (var i=0; i<4; i++) counterBlock[i+4] = (nonceSec >>> i*8) & 0xff; 1071 1072 // and convert it to a string to go on the front of the ciphertext 1073 var ctrTxt = ''; 1074 for (var i=0; i<8; i++) ctrTxt += String.fromCharCode(counterBlock[i]); 1075 1076 // generate key schedule - an expansion of the key into distinct Key Rounds for each round 1077 var keySchedule = Aes.keyExpansion(key); 1078 1079 var blockCount = Math.ceil(plaintext.length/blockSize); 1080 var ciphertxt = new Array(blockCount); // ciphertext as array of strings 1081 1082 for (var b=0; b<blockCount; b++) { 1083 // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes) 1084 // done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB) 1085 for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff;
1086 for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8) 1087 1088 var cipherCntr = Aes.cipher(counterBlock, keySchedule); // -- encrypt counter block -- 1089 1090 // block size is reduced on final block 1091 var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1; 1092 var cipherChar = new Array(blockLength); 1093 1094 for (var i=0; i<blockLength; i++) { // -- xor plaintext with ciphered counter char-by-char -- 1095 cipherChar[i] = cipherCntr[i] ^ plaintext.charCodeAt(b*blockSize+i); 1096 cipherChar[i] = String.fromCharCode(cipherChar[i]); 1097 } 1098 ciphertxt[b] = cipherChar.join(''); 1099 } 1100 1101 // Array.join is more efficient than repeated string concatenation in IE 1102 var ciphertext = ctrTxt + ciphertxt.join(''); 1103 ciphertext = Base64.encode(ciphertext); // encode in base64 1104 1105 //alert((new Date()) - t); 1106 return ciphertext; 1107} 1108 1109/** 1110 * Decrypt a text encrypted by AES in counter mode of operation 1111 * 1112 * @param {String} ciphertext Source text to be encrypted 1113 * @param {String} password The password to use to generate a key 1114 * @param {Number} nBits Number of bits to be used in the key (128, 192, or 256) 1115 * @returns {String} Decrypted text 1116 */ 1117Aes.Ctr.decrypt = function(ciphertext, password, nBits) { 1118 var blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES 1119 if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys 1120 ciphertext = Base64.decode(ciphertext); 1121 password = Utf8.encode(password); 1122 //var t = new Date(); // timer 1123 1124 // use AES to encrypt password (mirroring encrypt routine) 1125 var nBytes = nBits/8; // no bytes in key 1126 var pwBytes = new Array(nBytes); 1127 for (var i=0; i<nBytes; i++) { 1128 pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i); 1129 } 1130 var key = Aes.cipher(pwBytes, Aes.keyExpansion(pwBytes)); 1131 key = key.concat(key.slice(0, nBytes-16)); // expand key to 16/24/32 bytes long 1132 1133 // recover nonce from 1st 8 bytes of ciphertext 1134 var counterBlock = new Array(8); 1135 ctrTxt = ciphertext.slice(0, 8); 1136 for (var i=0; i<8; i++) counterBlock[i] = ctrTxt.charCodeAt(i); 1137 1138 // generate key schedule 1139 var keySchedule = Aes.keyExpansion(key); 1140 1141 // separate ciphertext into blocks (skipping past initial 8 bytes) 1142 var nBlocks = Math.ceil((ciphertext.length-8) / blockSize); 1143 var ct = new Array(nBlocks); 1144 for (var b=0; b<nBlocks; b++) ct[b] = ciphertext.slice(8+b*blockSize, 8+b*blockSize+blockSize); 1145 ciphertext = ct; // ciphertext is now array of block-length strings 1146 1147 // plaintext will get generated block-by-block into array of block-length strings 1148 var plaintxt = new Array(ciphertext.length); 1149 1150 for (var b=0; b<nBlocks; b++) { 1151 // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes) 1152 for (var c=0; c<4; c++) counterBlock[15-c] = ((b) >>> c*8) & 0xff; 1153 for (var c=0; c<4; c++) counterBlock[15-c-4] = (((b+1)/0x100000000-1) >>> c*8) & 0xff; 1154 1155 var cipherCntr = Aes.cipher(counterBlock, keySchedule); // encrypt counter block 1156 1157 var plaintxtByte = new Array(ciphertext[b].length); 1158 for (var i=0; i<ciphertext[b].length; i++) { 1159 // -- xor plaintxt with ciphered counter byte-by-byte -- 1160 plaintxtByte[i] = cipherCntr[i] ^ ciphertext[b].charCodeAt(i); 1161 plaintxtByte[i] = String.fromCharCode(plaintxtByte[i]); 1162 } 1163 plaintxt[b] = plaintxtByte.join(''); 1164 } 1165 1166 // join array of blocks into single plaintext string 1167 var plaintext = plaintxt.join(''); 1168 plaintext = Utf8.decode(plaintext); // decode from UTF8 back to Unicode multi-byte chars 1169 1170 //alert((new Date()) - t); 1171 return plaintext; 1172} 1173 1174 1175/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1176/* Base64 class: Base 64 encoding / decoding (c) Chris Veness 2002-2011 */ 1177/* note: depends on Utf8 class */ 1178/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1179 1180var Base64 = {}; // Base64 namespace 1181 1182Base64.code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
1182+/="; 1183 1184/** 1185 * Encode string into Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648] 1186 * (instance method extending String object). As per RFC 4648, no newlines are added. 1187 * 1188 * @param {String} str The string to be encoded as base-64 1189 * @param {Boolean} [utf8encode=false] Flag to indicate whether str is Unicode string to be encoded 1190 * to UTF8 before conversion to base64; otherwise string is assumed to be 8-bit characters 1191 * @returns {String} Base64-encoded string 1192 */ 1193Base64.encode = function(str, utf8encode) { // http://tools.ietf.org/html/rfc4648 1194 utf8encode = (typeof utf8encode == 'undefined') ? false : utf8encode; 1195 var o1, o2, o3, bits, h1, h2, h3, h4, e=[], pad = '', c, plain, coded; 1196 var b64 = Base64.code; 1197 1198 plain = utf8encode ? str.encodeUTF8() : str; 1199 1200 c = plain.length % 3; // pad string to length of multiple of 3 1201 if (c > 0) { while (c++ < 3) { pad += '='; plain += '\0'; } } 1202 // note: doing padding here saves us doing special-case packing for trailing 1 or 2 chars 1203 1204 for (c=0; c<plain.length; c+=3) { // pack three octets into four hexets 1205 o1 = plain.charCodeAt(c); 1206 o2 = plain.charCodeAt(c+1); 1207 o3 = plain.charCodeAt(c+2); 1208 1209 bits = o1<<16 | o2<<8 | o3; 1210 1211 h1 = bits>>18 & 0x3f; 1212 h2 = bits>>12 & 0x3f; 1213 h3 = bits>>6 & 0x3f; 1214 h4 = bits & 0x3f; 1215 1216 // use hextets to index into code string 1217 e[c/3] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); 1218 } 1219 coded = e.join(''); // join() is far faster than repeated string concatenation in IE 1220 1221 // replace 'A's from padded nulls with '='s 1222 coded = coded.slice(0, coded.length-pad.length) + pad; 1223 1224 return coded; 1225} 1226 1227/** 1228 * Decode string from Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648] 1229 * (instance method extending String object). As per RFC 4648, newlines are not catered for. 1230 * 1231 * @param {String} str The string to be decoded from base-64 1232 * @param {Boolean} [utf8decode=false] Flag to indicate whether str is Unicode string to be decoded 1233 * from UTF8 after conversion from base64 1234 * @returns {String} decoded string 1235 */ 1236Base64.decode = function(str, utf8decode) { 1237 utf8decode = (typeof utf8decode == 'undefined') ? false : utf8decode; 1238 var o1, o2, o3, h1, h2, h3, h4, bits, d=[], plain, coded; 1239 var b64 = Base64.code; 1240 1241 coded = utf8decode ? str.decodeUTF8() : str; 1242 1243 1244 for (var c=0; c<coded.length; c+=4) { // unpack four hexets into three octets 1245 h1 = b64.indexOf(coded.charAt(c)); 1246 h2 = b64.indexOf(coded.charAt(c+1)); 1247 h3 = b64.indexOf(coded.charAt(c+2)); 1248 h4 = b64.indexOf(coded.charAt(c+3)); 1249 1250 bits = h1<<18 | h2<<12 | h3<<6 | h4; 1251 1252 o1 = bits>>>16 & 0xff; 1253 o2 = bits>>>8 & 0xff; 1254 o3 = bits & 0xff; 1255 1256 d[c/4] = String.fromCharCode(o1, o2, o3); 1257 // check for padding 1258 if (h4 == 0x40) d[c/4] = String.fromCharCode(o1, o2); 1259 if (h3 == 0x40) d[c/4] = String.fromCharCode(o1); 1260 } 1261 plain = d.join(''); // join() is far faster than repeated string concatenation in IE 1262 1263 return utf8decode ? plain.decodeUTF8() : plain; 1264} 1265 1266 1267/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1268/* Utf8 class: encode / decode between multi-byte Unicode characters and UTF-8 multiple */ 1269/* single-byte character encoding (c) Chris Veness 2002-2011 */ 1270/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1271 1272var Utf8 = {}; // Utf8 namespace 1273 1274/** 1275 * Encode multi-byte Unicode string into utf-8 multiple single-byte characters 1276 * (BMP / basic multilingual plane only) 1277 * 1278 * Chars in range U+0080 - U+07FF are encoded in 2 chars, U+0800 - U+FFFF in 3 chars 1279 * 1280 * @param {String} strUni Unicode string to be encoded as UTF-8 1281 * @returns {String} encoded string 1282 */ 1283Utf8.encode = function(strUni) { 1284 // use regular expressions & String.replace callback function for better efficiency 1285 // than procedural approaches 1286 var strUtf = strUni.replace( 1287 /[\u0080-\u07ff]/g, // U+0080 - U+07FF => 2 bytes 110yyyyy, 10zzzzzz 1288 function(c) {
1289 var cc = c.charCodeAt(0); 1290 return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); } 1291 ); 1292 strUtf = strUtf.replace( 1293 /[\u0800-\uffff]/g, // U+0800 - U+FFFF => 3 bytes 1110xxxx, 10yyyyyy, 10zzzzzz 1294 function(c) { 1295 var cc = c.charCodeAt(0); 1296 return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); } 1297 ); 1298 return strUtf; 1299} 1300 1301/** 1302 * Decode utf-8 encoded string back into multi-byte Unicode characters 1303 * 1304 * @param {String} strUtf UTF-8 string to be decoded back to Unicode 1305 * @returns {String} decoded string 1306 */ 1307Utf8.decode = function(strUtf) { 1308 // note: decode 3-byte chars first as decoded 2-byte strings could appear to be 3-byte char! 1309 var strUni = strUtf.replace( 1310 /[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars 1311 function(c) { // (note parentheses for precence) 1312 var cc = ((c.charCodeAt(0)&0x0f)<<12) | ((c.charCodeAt(1)&0x3f)<<6) | ( c.charCodeAt(2)&0x3f); 1313 return String.fromCharCode(cc); } 1314 ); 1315 strUni = strUni.replace( 1316 /[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars 1317 function(c) { // (note parentheses for precence) 1318 var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f; 1319 return String.fromCharCode(cc); } 1320 ); 1321 return strUni; 1322} 1323 1324 1325/* A JavaScript implementation of the SHA family of hashes, as defined in FIPS 1326 * PUB 180-2 as well as the corresponding HMAC implementation as defined in 1327 * FIPS PUB 198a 1328 * 1329 * Version 1.3 Copyright Brian Turek 2008-2010 1330 * Distributed under the BSD License 1331 * See http://jssha.sourceforge.net/ for more information 1332 * 1333 * Several functions taken from Paul Johnson 1334 */ 1335 1336/* 1337 * Configurable variables. Defaults typically work 1338 */ 1339/* Number of Bits Per character (8 for ASCII, 16 for Unicode) */ 1340var charSize = 8, 1341/* base-64 pad character. "=" for strict RFC compliance */ 1342 b64pad = "", 1343/* hex output format. 0 - lowercase; 1 - uppercase */ 1344 hexCase = 0, 1345 1346/* 1347 * Int_64 is a object for 2 32-bit numbers emulating a 64-bit number 1348 * 1349 * @constructor 1350 * @param {Number} msint_32 The most significant 32-bits of a 64-bit number 1351 * @param {Number} lsint_32 The least significant 32-bits of a 64-bit number 1352 */ 1353 Int_64 = function (msint_32, lsint_32) 1354 { 1355 this.highOrder = msint_32; 1356 this.lowOrder = lsint_32; 1357 }, 1358 1359/* 1360 * Convert a string to an array of big-endian words 1361 * If charSize is ASCII, characters >255 have their hi-byte silently 1362 * ignored. 1363 * 1364 * @param {String} str String to be converted to binary representation 1365 * @return Integer array representation of the parameter 1366 */ 1367 str2binb = function (str) 1368 { 1369 var bin = [], mask = (1 << charSize) - 1, 1370 length = str.length * charSize, i; 1371 1372 for (i = 0; i < length; i += charSize) 1373 { 1374 bin[i >> 5] |= (str.charCodeAt(i / charSize) & mask) << 1375 (32 - charSize - (i % 32)); 1376 } 1377 1378 return bin; 1379 }, 1380 1381/* 1382 * Convert a hex string to an array of big-endian words 1383 * 1384 * @param {String} str String to be converted to binary representation 1385 * @return Integer array representation of the parameter 1386 */ 1387 hex2binb = function (str) 1388 { 1389 var bin = [], length = str.length, i, num; 1390 1391 for (i = 0; i < length; i += 2) 1392 { 1393 num = parseInt(str.substr(i, 2), 16); 1394 if (!isNaN(num)) 1395 { 1396 bin[i >> 3] |= num << (24 - (4 * (i % 8))); 1397 } 1398 else 1399 { 1400 return "INVALID HEX STRING"; 1401 } 1402 } 1403 1404 return bin; 1405 }, 1406 1407/* 1408 * Convert an array of big-endian words to a hex string. 1409 * 1410 * @private 1411 * @param {Array} binarray Array of integers to be converted to hexidecimal 1412 * representation 1413 * @return Hexidecimal representation of the parameter in String form 1414 */ 1415 binb2hex = function (binarray) 1416 { 1417 var hex_tab = (hexCase) ? "0123456789ABCDEF" : "0123456789abcdef", 1418 str = "", length = binarray.length * 4, i, srcByte; 1419 1420 for (i = 0; i < length; i += 1) 1421 { 1422 srcByte = binarray[i >> 2] >> ((3 - (i % 4)) * 8); 1423 str += hex_tab.charAt((srcByte >> 4) & 0xF) + 1424 hex_tab.charAt(srcByte & 0xF); 1425 } 1426 1427 return str; 1428 }, 1429 1430/* 1431 * Convert an array of big-endian words to a base-64 string 1432 * 1433 * @private 1434 * @param {Array} binarray Array of integers to be converted to base-64 1435 * representation 1436 * @return Base-64 encoded representation of the parameter in String form 1437 */ 1438 binb2b64 = function (binarray) 1439 { 1440 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +
1441 "0123456789+/", str = "", length = binarray.length * 4, i, j, 1442 triplet; 1443 1444 for (i = 0; i < length; i += 3) 1445 { 1446 triplet = (((binarray[i >> 2] >> 8 * (3 - i % 4)) & 0xFF) << 16) | 1447 (((binarray[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4)) & 0xFF) << 8) | 1448 ((binarray[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4)) & 0xFF); 1449 for (j = 0; j < 4; j += 1) 1450 { 1451 if (i * 8 + j * 6 <= binarray.length * 32) 1452 { 1453 str += tab.charAt((triplet >> 6 * (3 - j)) & 0x3F); 1454 } 1455 else 1456 { 1457 str += b64pad; 1458 } 1459 } 1460 } 1461 return str; 1462 }, 1463 1464/* 1465 * The 32-bit implementation of circular rotate left 1466 * 1467 * @private 1468 * @param {Number} x The 32-bit integer argument 1469 * @param {Number} n The number of bits to shift 1470 * @return The x shifted circularly by n bits 1471 */ 1472 rotl_32 = function (x, n) 1473 { 1474 return (x << n) | (x >>> (32 - n)); 1475 }, 1476 1477/* 1478 * The 32-bit implementation of circular rotate right 1479 * 1480 * @private 1481 * @param {Number} x The 32-bit integer argument 1482 * @param {Number} n The number of bits to shift 1483 * @return The x shifted circularly by n bits 1484 */ 1485 rotr_32 = function (x, n) 1486 { 1487 return (x >>> n) | (x << (32 - n)); 1488 }, 1489 1490/* 1491 * The 64-bit implementation of circular rotate right 1492 * 1493 * @private 1494 * @param {Int_64} x The 64-bit integer argument 1495 * @param {Number} n The number of bits to shift 1496 * @return The x shifted circularly by n bits 1497 */ 1498 rotr_64 = function (x, n) 1499 { 1500 if (n <= 32) 1501 { 1502 return new Int_64( 1503 (x.highOrder >>> n) | (x.lowOrder << (32 - n)), 1504 (x.lowOrder >>> n) | (x.highOrder << (32 - n)) 1505 ); 1506 } 1507 else 1508 { 1509 return new Int_64( 1510 (x.lowOrder >>> n) | (x.highOrder << (32 - n)), 1511 (x.highOrder >>> n) | (x.lowOrder << (32 - n)) 1512 ); 1513 } 1514 }, 1515 1516/* 1517 * The 32-bit implementation of shift right 1518 * 1519 * @private 1520 * @param {Number} x The 32-bit integer argument 1521 * @param {Number} n The number of bits to shift 1522 * @return The x shifted by n bits 1523 */ 1524 shr_32 = function (x, n) 1525 { 1526 return x >>> n; 1527 }, 1528 1529/* 1530 * The 64-bit implementation of shift right 1531 * 1532 * @private 1533 * @param {Int_64} x The 64-bit integer argument 1534 * @param {Number} n The number of bits to shift 1535 * @return The x shifted by n bits 1536 */ 1537 shr_64 = function (x, n) 1538 { 1539 if (n <= 32) 1540 { 1541 return new Int_64( 1542 x.highOrder >>> n, 1543 x.lowOrder >>> n | (x.highOrder << (32 - n)) 1544 ); 1545 } 1546 else 1547 { 1548 return new Int_64( 1549 0, 1550 x.highOrder << (32 - n) 1551 ); 1552 } 1553 }, 1554 1555/* 1556 * The 32-bit implementation of the NIST specified Parity function 1557 * 1558 * @private 1559 * @param {Number} x The first 32-bit integer argument 1560 * @param {Number} y The second 32-bit integer argument 1561 * @param {Number} z The third 32-bit integer argument 1562 * @return The NIST specified output of the function 1563 */ 1564 parity_32 = function (x, y, z) 1565 { 1566 return x ^ y ^ z; 1567 }, 1568 1569/* 1570 * The 32-bit implementation of the NIST specified Ch function 1571 * 1572 * @private 1573 * @param {Number} x The first 32-bit integer argument 1574 * @param {Number} y The second 32-bit integer argument 1575 * @param {Number} z The third 32-bit integer argument 1576 * @return The NIST specified output of the function 1577 */ 1578 ch_32 = function (x, y, z) 1579 { 1580 return (x & y) ^ (~x & z); 1581 }, 1582 1583/* 1584 * The 64-bit implementation of the NIST specified Ch function 1585 * 1586 * @private 1587 * @param {Int_64} x The first 64-bit integer argument 1588 * @param {Int_64} y The second 64-bit integer argument 1589 * @param {Int_64} z The third 64-bit integer argument 1590 * @return The NIST specified output of the function 1591 */ 1592 ch_64 = function (x, y, z) 1593 { 1594 return new Int_64( 1595 (x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder), 1596 (x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder) 1597 ); 1598 }, 1599 1600/* 1601 * The 32-bit implementation of the NIST specified Maj function 1602 * 1603 * @private 1604 * @param {Number} x The first 32-bit integer argument 1605 * @param {Number} y The second 32-bit integer argument 1606 * @param {Number} z The third 32-bit integer argument 1607 * @return The NIST specified output of the function 1608 */ 1609 maj_32 = function (x, y, z) 1610 { 1611 return (x & y) ^ (x & z) ^ (y & z); 1612 }, 1613 1614/* 1615 * The 64-bit implementation of the NIST specified Maj function 1616 * 1617 * @private 1618 * @param {Int_64} x The first 64-bit integer argument 1619 * @param {Int_64} y The second 64-bit integer argument 1620 * @param {Int_64} z The third 64-bit integer argument 1621 * @return The NIST specified output of the function 1622 */ 1623 maj_64 = function (x, y, z) 1624 { 1625 return new Int_64( 1626 (x.highOrder & y.highOrder) ^ 1627 (x.highOrder & z.highOrder) ^ 1628 (y.highOrder & z.highOrder), 1629 (x.lowOrder & y.lowOrder) ^ 1630 (x.lowOrder & z.lowOrder) ^ 1631 (y.lowOrder & z.lowOrder) 1632 ); 1633 }, 1634 1635/* 1636 * The 32-bit implementation of the NIST specified Sigma0 function 1637 * 1638 * @private 1639 * @param {Number} x The 32-bit integer argument 1640 * @return The NIST specified output of the function 1641 */ 1642 sigma0_32 = function (x) 1643 { 1644 return rotr_32(x, 2) ^ rotr_32(x, 13) ^ rotr_32(x, 22); 1645 }, 1646 1647/* 1648 * The 64-bit implementation of the NIST specified Sigma0 function 1649 * 1650 * @private 1651 * @param {Int_64} x The 64-bit integer argument 1652 * @return The NIST specified output of the function 1653 */ 1654 sigma0_64 = function (x) 1655 { 1656 var rotr28 = rotr_64(x, 28), rotr34 = rotr_64(x, 34), 1657 rotr39 = rotr_64(x, 39); 1658 1659 return new Int_64( 1660 rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder, 1661 rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder); 1662 }, 1663 1664/* 1665 * The 32-bit implementation of the NIST specified Sigma1 function 1666 * 1667 * @private 1668 * @param {Number} x The 32-bit integer argument 1669 * @return The NIST specified output of the function 1670 */ 1671 sigma1_32 = function (x) 1672 { 1673 return rotr_32(x, 6) ^ rotr_32(x, 11) ^ rotr_32(x, 25); 1674 }, 1675 1676/* 1677 * The 64-bit implementation of the NIST specified Sigma1 function 1678 * 1679 * @private 1680 * @param {Int_64} x The 64-bit integer argument 1681 * @return The NIST specified output of the function 1682 */ 1683 sigma1_64 = function (x) 1684 { 1685 var rotr14 = rotr_64(x, 14), rotr18 = rotr_64(x, 18), 1686 rotr41 = rotr_64(x, 41); 1687 1688 return new Int_64( 1689 rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder, 1690 rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder); 1691 }, 1692 1693/* 1694 * The 32-bit implementation of the NIST specified Gamma0 function 1695 * 1696 * @private 1697 * @param {Number} x The 32-bit integer argument 1698 * @return The NIST specified output of the function 1699 */ 1700 gamma0_32 = function (x) 1701 { 1702 return rotr_32(x, 7) ^ rotr_32(x, 18) ^ shr_32(x, 3); 1703 }, 1704 1705/* 1706 * The 64-bit implementation of the NIST specified Gamma0 function 1707 * 1708 * @private 1709 * @param {Int_64} x The 64-bit integer argument 1710 * @return The NIST specified output of the function 1711 */ 1712 gamma0_64 = function (x) 1713 { 1714 var rotr1 = rotr_64(x, 1), rotr8 = rotr_64(x, 8), shr7 = shr_64(x, 7); 1715 1716 return new Int_64( 1717 rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder, 1718 rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder 1719 ); 1720 }, 1721 1722/* 1723 * The 32-bit implementation of the NIST specified Gamma1 function 1724 * 1725 * @private 1726 * @param {Number} x The 32-bit integer argument 1727 * @return The NIST specified output of the function 1728 */ 1729 gamma1_32 = function (x) 1730 { 1731 return rotr_32(x, 17) ^ rotr_32(x, 19) ^ shr_32(x, 10); 1732 }, 1733 1734/* 1735 * The 64-bit implementation of the NIST specified Gamma1 function 1736 * 1737 * @private 1738 * @param {Int_64} x The 64-bit integer argument 1739 * @return The NIST specified output of the function 1740 */ 1741 gamma1_64 = function (x) 1742 { 1743 var rotr19 = rotr_64(x, 19), rotr61 = rotr_64(x, 61), 1744 shr6 = shr_64(x, 6); 1745 1746 return new Int_64( 1747 rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder, 1748 rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder 1749 ); 1750 }, 1751 1752/* 1753 * Add two 32-bit integers, wrapping at 2^32. This uses 16-bit operations 1754 * internally to work around bugs in some JS interpreters. 1755 * 1756 * @private 1757 * @param {Number} x The first 32-bit integer argument to be added 1758 * @param {Number} y The second 32-bit integer argument to be added 1759 * @return The sum of x + y 1760 */ 1761 safeAdd_32_2 = function (x, y) 1762 { 1763 var lsw = (x & 0xFFFF) + (y & 0xFFFF), 1764 msw = (x >>> 16) + (y >>> 16) + (lsw >>> 16); 1765 1766 return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 1767 }, 1768 1769/* 1770 * Add four 32-bit integers, wrapping at 2^32. This uses 16-bit operations 1771 * internally to work around bugs in some JS interpreters. 1772 * 1773 * @private 1774 * @param {Number} a The first 32-bit integer argument to be added 1775 * @param {Number} b The second 32-bit integer argument to be added 1776 * @param {Number} c The third 32-bit integer argument to be added 1777 * @param {Number} d The fourth 32-bit integer argument to be added 1778 * @return The sum of a + b + c + d 1779 */ 1780 safeAdd_32_4 = function (a, b, c, d) 1781 { 1782 var lsw = (a & 0xFFFF) + (b & 0xFFFF) + (c & 0xFFFF) + (d & 0xFFFF), 1783 msw = (a >>> 16) + (b >>> 16) + (c >>> 16) + (d >>> 16) + 1784 (lsw >>> 16); 1785 1786 return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 1787 }, 1788 1789/* 1790 * Add five 32-bit integers, wrapping at 2^32. This uses 16-bit operations 1791 * internally to work around bugs in some JS interpreters. 1792 * 1793 * @private 1794 * @param {Number} a The first 32-bit integer argument to be added 1795 * @param {Number} b The second 32-bit integer argument to be added 1796 * @param {Number} c The third 32-bit integer argument to be added 1797 * @param {Number} d The fourth 32-bit integer argument to be added 1798 * @param {Number} e The fifth 32-bit integer argument to be added 1799 * @return The sum of a + b + c + d + e 1800 */ 1801 safeAdd_32_5 = function (a, b, c, d, e) 1802 { 1803 var lsw = (a & 0xFFFF) + (b & 0xFFFF) + (c & 0xFFFF) + (d & 0xFFFF) + 1804 (e & 0xFFFF), 1805 msw = (a >>> 16) + (b >>> 16) + (c >>> 16) + (d >>> 16) + 1806 (e >>> 16) + (lsw >>> 16); 1807 1808 return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 1809 }, 1810 1811/* 1812 * Add two 64-bit integers, wrapping at 2^64. This uses 16-bit operations 1813 * internally to work around bugs in some JS interpreters. 1814 * 1815 * @private 1816 * @param {Int_64} x The first 64-bit integer argument to be added 1817 * @param {Int_64} y The second 64-bit integer argument to be added 1818 * @return The sum of x + y 1819 */ 1820 safeAdd_64_2 = function (x, y) 1821 { 1822 var lsw, msw, lowOrder, highOrder; 1823 1824 lsw = (x.lowOrder & 0xFFFF) + (y.lowOrder & 0xFFFF); 1825 msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16); 1826 lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 1827 1828 lsw = (x.highOrder & 0xFFFF) + (y.highOrder & 0xFFFF) + (msw >>> 16); 1829 msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16); 1830 highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 1831 1832 return new Int_64(highOrder, lowOrder); 1833 }, 1834 1835/* 1836 * Add four 64-bit integers, wrapping at 2^64. This uses 16-bit operations 1837 * internally to work around bugs in some JS interpreters. 1838 * 1839 * @private 1840 * @param {Int_64} a The first 64-bit integer argument to be added 1841 * @param {Int_64} b The second 64-bit integer argument to be added 1842 * @param {Int_64} c The third 64-bit integer argument to be added 1843 * @param {Int_64} d The fouth 64-bit integer argument to be added 1844 * @return The sum of a + b + c + d 1845 */ 1846 safeAdd_64_4 = function (a, b, c, d) 1847 { 1848 var lsw, msw, lowOrder, highOrder; 1849 1850 lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + 1851 (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF); 1852 msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + 1853 (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16); 1854 lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 1855 1856 lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + 1857 (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (msw >>> 16); 1858 msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + 1859 (c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16); 1860 highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 1861 1862 return new Int_64(highOrder, lowOrder); 1863 }, 1864 1865/* 1866 * Add five 64-bit integers, wrapping at 2^64. This uses 16-bit operations 1867 * internally to work around bugs in some JS interpreters. 1868 * 1869 * @private 1870 * @param {Int_64} a The first 64-bit integer argument to be added 1871 * @param {Int_64} b The second 64-bit integer argument to be added 1872 * @param {Int_64} c The third 64-bit integer argument to be added 1873 * @param {Int_64} d The fouth 64-bit integer argument to be added 1874 * @param {Int_64} e The fouth 64-bit integer argument to be added 1875 * @return The sum of a + b + c + d + e 1876 */ 1877 safeAdd_64_5 = function (a, b, c, d, e) 1878 { 1879 var lsw, msw, lowOrder, highOrder; 1880 1881 lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + 1882 (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF) + 1883 (e.lowOrder & 0xFFFF); 1884 msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + 1885 (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (e.lowOrder >>> 16) + 1886 (lsw >>> 16); 1887 lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 1888 1889 lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + 1890 (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + 1891 (e.highOrder & 0xFFFF) + (msw >>> 16); 1892 msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + 1893 (c.highOrder >>> 16) + (d.highOrder >>> 16) + 1894 (e.highOrder >>> 16) + (lsw >>> 16); 1895 highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); 1896 1897 return new Int_64(highOrder, lowOrder); 1898 }, 1899 1900/* 1901 * Calculates the SHA-1 hash of the string set at instantiation 1902 * 1903 * @private 1904 * @param {Array} message The binary array representation of the string to 1905 * hash 1906 * @param {Number} messageLen The number of bits in the message 1907 * @return The array of integers representing the SHA-1 hash of message 1908 */ 1909 coreSHA1 = function (message, messageLen) 1910 { 1911 var W = [], a, b, c, d, e, T, ch = ch_32, parity = parity_32, 1912 maj = maj_32, rotl = rotl_32, safeAdd_2 = safeAdd_32_2, i, t, 1913 safeAdd_5 = safeAdd_32_5, appendedMessageLength, 1914 H = [ 1915 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 1916 ], 1917 K = [ 1918 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999, 1919 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999, 1920 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999, 1921 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999, 1922 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999, 1923 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 1924 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 1925 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 1926 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 1927 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 1928 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 1929 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 1930 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 1931 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 1932 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 1933 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 1934 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 1935 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 1936 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 1937 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6 1938 ]; 1939 1940 /* Append '1' at the end of the binary string */ 1941 message[messageLen >> 5] |= 0x80 << (24 - (messageLen % 32)); 1942 /* Append length of binary string in the position such that the new 1943 length is a multiple of 512. Logic does not work for even multiples 1944 of 512 bu
1944t there can never be even multiples of 512 */ 1945 message[(((messageLen + 65) >> 9) << 4) + 15] = messageLen; 1946 1947 appendedMessageLength = message.length; 1948 1949 for (i = 0; i < appendedMessageLength; i += 16) 1950 { 1951 a = H[0]; 1952 b = H[1]; 1953 c = H[2]; 1954 d = H[3]; 1955 e = H[4]; 1956 1957 for (t = 0; t < 80; t += 1) 1958 { 1959 if (t < 16) 1960 { 1961 W[t] = message[t + i]; 1962 } 1963 else 1964 { 1965 W[t] = rotl(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1); 1966 } 1967 1968 if (t < 20) 1969 { 1970 T = safeAdd_5(rotl(a, 5), ch(b, c, d), e, K[t], W[t]); 1971 } 1972 else if (t < 40) 1973 { 1974 T = safeAdd_5(rotl(a, 5), parity(b, c, d), e, K[t], W[t]); 1975 } 1976 else if (t < 60) 1977 { 1978 T = safeAdd_5(rotl(a, 5), maj(b, c, d), e, K[t], W[t]); 1979 } else { 1980 T = safeAdd_5(rotl(a, 5), parity(b, c, d), e, K[t], W[t]); 1981 } 1982 1983 e = d; 1984 d = c; 1985 c = rotl(b, 30); 1986 b = a; 1987 a = T; 1988 } 1989 1990 H[0] = safeAdd_2(a, H[0]); 1991 H[1] = safeAdd_2(b, H[1]); 1992 H[2] = safeAdd_2(c, H[2]); 1993 H[3] = safeAdd_2(d, H[3]); 1994 H[4] = safeAdd_2(e, H[4]); 1995 } 1996 1997 return H; 1998 }, 1999 2000/* 2001 * Calculates the desired SHA-2 hash of the string set at instantiation 2002 * 2003 * @private 2004 * @param {Array} The binary array representation of the string to hash 2005 * @param {Number} The number of bits in message 2006 * @param {String} variant The desired SHA-2 variant 2007 * @return The array of integers representing the SHA-2 hash of message 2008 */ 2009 coreSHA2 = function (message, messageLen, variant) 2010 { 2011 var a, b, c, d, e, f, g, h, T1, T2, H, numRounds, lengthPosition, i, t, 2012 binaryStringInc, binaryStringMult, safeAdd_2, safeAdd_4, safeAdd_5, 2013 gamma0, gamma1, sigma0, sigma1, ch, maj, Int, K, W = [], 2014 appendedMessageLength; 2015 2016 /* Set up the various function handles and variable for the specific 2017 * variant */ 2018 if (variant === "SHA-224" || variant === "SHA-256") 2019 { 2020 /* 32-bit variant */ 2021 numRounds = 64; 2022 lengthPosition = (((messageLen + 65) >> 9) << 4) + 15; 2023 binaryStringInc = 16; 2024 binaryStringMult = 1; 2025 Int = Number; 2026 safeAdd_2 = safeAdd_32_2; 2027 safeAdd_4 = safeAdd_32_4; 2028 safeAdd_5 = safeAdd_32_5; 2029 gamma0 = gamma0_32; 2030 gamma1 = gamma1_32; 2031 sigma0 = sigma0_32; 2032 sigma1 = sigma1_32; 2033 maj = maj_32; 2034 ch = ch_32; 2035 K = [ 2036 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 2037 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 2038 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 2039 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 2040 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 2041 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 2042 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 2043 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, 2044 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 2045 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 2046 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 2047 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 2048 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 2049 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 2050 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 2051 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 2052 ]; 2053 2054 if (variant === "SHA-224") 2055 { 2056 H = [ 2057 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 2058 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 2059 ]; 2060 } 2061 else 2062 { 2063 H = [ 2064 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 2065 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 2066 ]; 2067 } 2068 } 2069 else if (variant === "SHA-384" || variant === "SHA-512") 2070 { 2071 /* 64-bit variant */ 2072 numRounds = 80; 2073 lengthPosition = (((messageLen + 128) >> 10) << 5) + 31; 2074 binaryStringInc = 32; 2075 binaryStringMult = 2; 2076 Int = Int_64; 2077 safeAdd_2 = safeAdd_64_2; 2078 safeAdd_4 = safeAdd_64_4; 2079 safeAdd_5 = safeAdd_64_5; 2080 gamma0 = gamma0_64; 2081 gamma1 = gamma1_64; 2082 sigma0 = sigma0_64; 2083 sigma1 = sigma1_64; 2084 maj = maj_64; 2085 ch = ch_64; 2086 2087 K = [ 2088 new Int(0x428a2f98, 0xd728ae22), new Int(0x71374491, 0x23ef65cd), 2089 new Int(0xb5c0fbcf, 0xec4d3b2f), new Int(0xe9b5dba5, 0x8189dbbc), 2090 new Int(0x3956c25b, 0xf348b538), new Int(0x59f111f1, 0xb
2090605d019), 2091 new Int(0x923f82a4, 0xaf194f9b), new Int(0xab1c5ed5, 0xda6d8118), 2092 new Int(0xd807aa98, 0xa3030242), new Int(0x12835b01, 0x45706fbe), 2093 new Int(0x243185be, 0x4ee4b28c), new Int(0x550c7dc3, 0xd5ffb4e2), 2094 new Int(0x72be5d74, 0xf27b896f), new Int(0x80deb1fe, 0x3b1696b1), 2095 new Int(0x9bdc06a7, 0x25c71235), new Int(0xc19bf174, 0xcf692694), 2096 new Int(0xe49b69c1, 0x9ef14ad2), new Int(0xefbe4786, 0x384f25e3), 2097 new Int(0x0fc19dc6, 0x8b8cd5b5), new Int(0x240ca1cc, 0x77ac9c65), 2098 new Int(0x2de92c6f, 0x592b0275), new Int(0x4a7484aa, 0x6ea6e483), 2099 new Int(0x5cb0a9dc, 0xbd41fbd4), new Int(0x76f988da, 0x831153b5), 2100 new Int(0x983e5152, 0xee66dfab), new Int(0xa831c66d, 0x2db43210), 2101 new Int(0xb00327c8, 0x98fb213f), new Int(0xbf597fc7, 0xbeef0ee4), 2102 new Int(0xc6e00bf3, 0x3da88fc2), new Int(0xd5a79147, 0x930aa725), 2103 new Int(0x06ca6351, 0xe003826f), new Int(0x14292967, 0x0a0e6e70), 2104 new Int(0x27b70a85, 0x46d22ffc), new Int(0x2e1b2138, 0x5c26c926), 2105 new Int(0x4d2c6dfc, 0x5ac42aed), new Int(0x53380d13, 0x9d95b3df), 2106 new Int(0x650a7354, 0x8baf63de), new Int(0x766a0abb, 0x3c77b2a8), 2107 new Int(0x81c2c92e, 0x47edaee6), new Int(0x92722c85, 0x1482353b), 2108 new Int(0xa2bfe8a1, 0x4cf10364), new Int(0xa81a664b, 0xbc423001), 2109 new Int(0xc24b8b70, 0xd0f89791), new Int(0xc76c51a3, 0x0654be30), 2110 new Int(0xd192e819, 0xd6ef5218), new Int(0xd6990624, 0x5565a910), 2111 new Int(0xf40e3585, 0x5771202a), new Int(0x106aa070, 0x32bbd1b8), 2112 new Int(0x19a4c116, 0xb8d2d0c8), new Int(0x1e376c08, 0x5141ab53), 2113 new Int(0x2748774c, 0xdf8eeb99), new Int(0x34b0bcb5, 0xe19b48a8), 2114 new Int(0x391c0cb3, 0xc5c95a63), new Int(0x4ed8aa4a, 0xe3418acb), 2115 new Int(0x5b9cca4f, 0x7763e373), new Int(0x682e6ff3, 0xd6b2b8a3), 2116 new Int(0x748f82ee, 0x5defb2fc), new Int(0x78a5636f, 0x43172f60), 2117 new Int(0x84c87814, 0xa1f0ab72), new Int(0x8cc70208, 0x1a6439ec), 2118 new Int(0x90befffa, 0x23631e28), new Int(0xa4506ceb, 0xde82bde9), 2119 new Int(0xbef9a3f7, 0xb2c67915), new Int(0xc67178f2, 0xe372532b), 2120 new Int(0xca273ece, 0xea26619c), new Int(0xd186b8c7, 0x21c0c207), 2121 new Int(0xeada7dd6, 0xcde0eb1e), new Int(0xf57d4f7f, 0xee6ed178), 2122 new Int(0x06f067aa, 0x72176fba), new Int(0x0a637dc5, 0xa2c898a6), 2123 new Int(0x113f9804, 0xbef90dae), new Int(0x1b710b35, 0x131c471b), 2124 new Int(0x28db77f5, 0x23047d84), new Int(0x32caab7b, 0x40c72493), 2125 new Int(0x3c9ebe0a, 0x15c9bebc), new Int(0x431d67c4, 0x9c100d4c), 2126 new Int(0x4cc5d4be, 0xcb3e42b6), new Int(0x597f299c, 0xfc657e2a), 2127 new Int(0x5fcb6fab, 0x3ad6faec), new Int(0x6c44198c, 0x4a475817) 2128 ]; 2129 2130 if (variant === "SHA-384") 2131 { 2132 H = [ 2133 new Int(0xcbbb9d5d, 0xc1059ed8), new Int(0x0629a292a, 0x367cd507), 2134 new Int(0x9159015a, 0x3070dd17), new Int(0x0152fecd8, 0xf70e5939), 2135 new Int(0x67332667, 0xffc00b31), new Int(0x98eb44a87, 0x68581511), 2136 new Int(0xdb0c2e0d, 0x64f98fa7), new Int(0x047b5481d, 0xbefa4fa4) 2137 ]; 2138 } 2139 else 2140 { 2141 H = [ 2142 new Int(0x6a09e667, 0xf3bcc908), new Int(0xbb67ae85, 0x84caa73b), 2143 new Int(0x3c6ef372, 0xfe94f82b), new Int(0xa54ff53a, 0x5f1d36f1), 2144 new Int(0x510e527f, 0xade682d1), new Int(0x9b05688c, 0x2b3e6c1f), 2145 new Int(0x1f83d9ab, 0xfb41bd6b), new Int(0x5be0cd19, 0x137e2179) 2146 ]; 2147 } 2148 } 2149 2150 /* Append '1' at the end of the binary string */ 2151 message[messageLen >> 5] |= 0x80 << (24 - messageLen % 32); 2152 /* Append length of binary string in the position such that the new 2153 * length is correct */ 2154 message[lengthPosition] = messageLen; 2155 2156 appendedMessageLength = message.length; 2157 2158 for (i = 0; i < appendedMessageLength; i += binaryStringInc) 2159 { 2160 a = H[0]; 2161 b = H[1]; 2162 c = H[2]; 2163 d = H[3]; 2164 e = H[4]; 2165 f = H[5]; 2166 g = H[6]; 2167 h = H[7]; 2168 2169 for (t = 0; t < numRounds; t += 1) 2170 { 2171 if (t < 16) 2172 { 2173 /* Bit of a hack - for 32-bit, the second term is ignored */ 2174 W[t] = new Int(message[t * binaryStringMult + i], 2175 message[t * binaryStringMult + i + 1]); 2176 } 2177 else 2178 { 2179 W[t] = safeAdd_4( 2180 gamma1(W[t - 2]), W[t - 7], 2181 gamma0(W[t - 15]), W[t - 16] 2182 ); 2183 } 2184 2185 T1 = safeAdd_5(h, sigma1(e), ch(e, f, g), K[t], W[t]); 2186 T2 = safeAdd_2(sigma0(a), maj(a, b, c)); 2187 h = g; 2188 g = f; 2189 f = e; 2190 e = safeAdd_2(d, T1); 2191 d = c; 2192 c = b; 2193 b = a; 2194 a = safeAdd_2(T1, T2); 2195 } 2196 2197 H[0] = safeAdd_2(a, H[0]); 2198 H[1] = safeAdd_2(b, H[1]); 2199 H[2] = safeAdd_2(c, H[2]); 2200 H[3] = safeAdd_2(d, H[3]); 2201 H[4] = safeAdd_2(e, H[4]); 2202 H[5] = safeAdd_2(f, H[5]); 2203 H[6] = safeAdd_2(g, H[6]); 2204 H[7] = safeAdd_2(h, H[7]); 2205 } 2206 2207 switch (variant) 2208 { 2209 case "SHA-512": 2210 return [ 2211 H[0].highOrder, H[0].lowOrder, 2212 H[1].highOrder, H[1].lowOrder, 2213 H[2].highOrder, H[2].lowOrder, 2214 H[3].highOrder, H[3].lowOrder, 2215 H[4].highOrder, H[4].lowOrder, 2216 H[5].highOrder, H[5].lowOrder, 2217 H[6].highOrder, H[6].lowOrder, 2218 H[7].highOrder, H[7].lowOrder 2219 ]; 2220 default: 2221 /* This should never be reached */ 2222 return []; 2223 } 2224 }, 2225 2226/* 2227 * jsSHA is the workhorse of the library. Instantiate it with the string to 2228 * be hashed as the parameter 2229 * 2230 * @constructor 2231 * @param {String} srcString The string to be hashed 2232 * @param {String} inputFormat The format of srcString, ASCII or HEX 2233 */ 2234 jsSHA = function (srcString, inputFormat) 2235 { 2236 2237 this.sha512 = null; 2238 2239 this.strBinLen = null; 2240 this.strToHash = null; 2241 2242 /* Convert the input string into the correct type */ 2243 if ("HEX" === inputFormat) 2244 { 2245 if (0 !== (srcString.length % 2)) 2246 { 2247 return "TEXT MUST BE IN BYTE INCREMENTS"; 2248 } 2249 this.strBinLen = srcString.length * 4; 2250 this.strToHash = hex2binb(srcString); 2251 } 2252 else if (("ASCII" === inputFormat) || 2253 ('undefined' === typeof(inputFormat))) 2254 { 2255 this.strBinLen = srcString.length * charSize; 2256 this.strToHash = str2binb(srcString); 2257 } 2258 else 2259 { 2260 return "UNKNOWN TEXT INPUT TYPE"; 2261 } 2262 }; 2263 2264jsSHA.prototype = { 2265 /* 2266 * Returns the desired SHA hash of the string specified at instantiation 2267 * using the specified parameters 2268 * 2269 * @param {String} variant The desired SHA variant (SHA-1, SHA-224, 2270 * SHA-256, SHA-384, or SHA-512) 2271 * @param {String} format The desired output formatting (B64 or HEX) 2272 * @return The string representation of the hash in the format specified 2273 */ 2274 getHash : function (variant, format) 2275 { 2276 var formatFunc = null, message = this.strToHash.slice(); 2277 2278 switch (format) 2279 { 2280 case "HEX": 2281 formatFunc = binb2hex; 2282 break; 2283 case "B64": 2284 formatFunc = binb2b64; 2285 break; 2286 default: 2287 return "FORMAT NOT RECOGNIZED"; 2288 } 2289 2290 switch (variant) 2291 { 2292 case "SHA-512": 2293 if (null === this.sha512) 2294 { 2295 this.sha512 = coreSHA2(message, this.strBinLen, variant); 2296 } 2297 return formatFunc(this.sha512); 2298 default: 2299 return "HASH NOT RECOGNIZED"; 2300 } 2301 }, 2302 2303 /* 2304 * Returns the desired HMAC of the string specified at instantiation 2305 * using the key and variant param. 2306 * 2307 * @param {String} key The key used to calculate the HMAC 2308 * @param {String} inputFormat The format of key, ASCII or HEX 2309 * @param {String} variant The desired SHA variant (SHA-1, SHA-224, 2310 * SHA-256, SHA-384, or SHA-512) 2311 * @param {String} outputFormat The desired output formatting 2312 * (B64 or HEX) 2313 * @return The string representation of the hash in the format specified 2314 */ 2315 getHMAC : function (key, inputFormat, variant, outputFormat) 2316 { 2317 var formatFunc, keyToUse, blockByteSize, blockBitSize, i, 2318 retVal, lastArrayIndex, keyBinLen, hashBitSize, 2319 keyWithIPad = [], keyWithOPad = []; 2320 2321 /* Validate the output format selection */ 2322 switch (outputFormat) 2323 { 2324 case "HEX": 2325 formatFunc = binb2hex; 2326 break; 2327 case "B64": 2328 formatFunc = binb2b64; 2329 break; 2330 default: 2331 return "FORMAT NOT RECOGNIZED"; 2332 } 2333 2334 /* Validate the hash variant selection and set needed variables */ 2335 switch (variant) 2336 { 2337 case "SHA-512": 2338 blockByteSize = 128; 2339 hashBitSize = 512; 2340 break; 2341 default: 2342 return "HASH NOT RECOGNIZED"; 2343 } 2344 2345 /* Validate input format selection */ 2346 if ("HEX" === inputFormat) 2347 { 2348 /* Nibbles must come in pairs */ 2349 if (0 !== (key.length % 2)) 2350 { 2351 return "KEY MUST BE IN BYTE INCREMENTS"; 2352 } 2353 keyToUse = hex2binb(key); 2354 keyBinLen = key.length * 4; 2355 } 2356 else if ("ASCII" === inputFormat) 2357 { 2358 keyToUse = str2binb(key); 2359 keyBinLen = key.length * charSize; 2360 } 2361 else 2362 { 2363 return "UNKNOWN KEY INPUT TYPE"; 2364 } 2365 2366 /* These are used multiple times, calculate and store them */ 2367 blockBitSize = blockByteSize * 8; 2368 lastArrayIndex = (blockByteSize / 4) - 1; 2369 2370 /* Figure out what to do with the key based on its size relative to 2371 * the hash's block size */ 2372 if (blockByteSize < (keyBinLen / 8)) 2373 { 2374 if ("SHA-1" === variant) 2375 { 2376 keyToUse = coreSHA1(keyToUse, keyBinLen); 2377 } 2378 else 2379 { 2380 keyToUse = coreSHA2(keyToUse, keyBinLen, variant); 2381 } 2382 /* For all variants, the block size is bigger than the output 2383 * size so there will never be a useful byte at the end of the 2384 * string */ 2385 keyToUse[lastArrayIndex] &= 0xFFFFFF00; 2386 } 2387 else if (blockByteSize > (keyBinLen / 8)) 2388 { 2389 /* If the blockByteSize is greater than the key length, there 2390 * will always be at LEAST one "useless" byte at the end of the 2391 * string */ 2392 keyToUse[lastArrayIndex] &= 0xFFFFFF00; 2393 } 2394 2395 /* Create ipad and opad */ 2396 for (i = 0; i <= lastArrayIndex; i += 1) 2397 { 2398 keyWithIPad[i] = keyToUse[i] ^ 0x36363636; 2399 keyWithOPad[i] = keyToUse[i] ^ 0x5C5C5C5C; 2400 } 2401 2402 /* Calculate the HMAC */ 2403 if ("SHA-1" === variant) 2404 { 2405 retVal = coreSHA1( 2406 keyWithIPad.concat(this.strToHash), 2407 blockBitSize + this.strBinLen); 2408 retVal = coreSHA1( 2409 keyWithOPad.concat(retVal), 2410 blockBitSize + hashBitSize); 2411 } 2412 else 2413 { 2414 retVal = coreSHA2( 2415 keyWithIPad.concat(this.strToHash), 2416 blockBitSize + this.strBinLen, variant); 2417 retVal = coreSHA2( 2418 keyWithOPad.concat(retVal), 2419 blockBitSize + hashBitSize, variant); 2420 } 2421 2422 return (formatFunc(retVal)); 2423 } 2424}; 2425 2426window.jsSHA = jsSHA;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.