PageSourceSearch

https://siata.gov.co/siata_nuevo/application/assets/plugins/jquery.jcryption.js?v=4.14.18

js siata.gov.co collected 2026-10-02 06:42:08 UTC 83,343 bytes, 2,426 lines download raw bytes

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.