/******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ "./node_modules/crypto-js/aes.js":
/*!***************************************!*\
  !*** ./node_modules/crypto-js/aes.js ***!
  \***************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./enc-base64 */ "./node_modules/crypto-js/enc-base64.js"), __webpack_require__(/*! ./md5 */ "./node_modules/crypto-js/md5.js"), __webpack_require__(/*! ./evpkdf */ "./node_modules/crypto-js/evpkdf.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var BlockCipher = C_lib.BlockCipher;
	    var C_algo = C.algo;

	    // Lookup tables
	    var SBOX = [];
	    var INV_SBOX = [];
	    var SUB_MIX_0 = [];
	    var SUB_MIX_1 = [];
	    var SUB_MIX_2 = [];
	    var SUB_MIX_3 = [];
	    var INV_SUB_MIX_0 = [];
	    var INV_SUB_MIX_1 = [];
	    var INV_SUB_MIX_2 = [];
	    var INV_SUB_MIX_3 = [];

	    // Compute lookup tables
	    (function () {
	        // Compute double table
	        var d = [];
	        for (var i = 0; i < 256; i++) {
	            if (i < 128) {
	                d[i] = i << 1;
	            } else {
	                d[i] = (i << 1) ^ 0x11b;
	            }
	        }

	        // Walk GF(2^8)
	        var x = 0;
	        var xi = 0;
	        for (var i = 0; i < 256; i++) {
	            // Compute sbox
	            var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);
	            sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;
	            SBOX[x] = sx;
	            INV_SBOX[sx] = x;

	            // Compute multiplication
	            var x2 = d[x];
	            var x4 = d[x2];
	            var x8 = d[x4];

	            // Compute sub bytes, mix columns tables
	            var t = (d[sx] * 0x101) ^ (sx * 0x1010100);
	            SUB_MIX_0[x] = (t << 24) | (t >>> 8);
	            SUB_MIX_1[x] = (t << 16) | (t >>> 16);
	            SUB_MIX_2[x] = (t << 8)  | (t >>> 24);
	            SUB_MIX_3[x] = t;

	            // Compute inv sub bytes, inv mix columns tables
	            var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);
	            INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8);
	            INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16);
	            INV_SUB_MIX_2[sx] = (t << 8)  | (t >>> 24);
	            INV_SUB_MIX_3[sx] = t;

	            // Compute next counter
	            if (!x) {
	                x = xi = 1;
	            } else {
	                x = x2 ^ d[d[d[x8 ^ x2]]];
	                xi ^= d[d[xi]];
	            }
	        }
	    }());

	    // Precomputed Rcon lookup
	    var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];

	    /**
	     * AES block cipher algorithm.
	     */
	    var AES = C_algo.AES = BlockCipher.extend({
	        _doReset: function () {
	            var t;

	            // Skip reset of nRounds has been set before and key did not change
	            if (this._nRounds && this._keyPriorReset === this._key) {
	                return;
	            }

	            // Shortcuts
	            var key = this._keyPriorReset = this._key;
	            var keyWords = key.words;
	            var keySize = key.sigBytes / 4;

	            // Compute number of rounds
	            var nRounds = this._nRounds = keySize + 6;

	            // Compute number of key schedule rows
	            var ksRows = (nRounds + 1) * 4;

	            // Compute key schedule
	            var keySchedule = this._keySchedule = [];
	            for (var ksRow = 0; ksRow < ksRows; ksRow++) {
	                if (ksRow < keySize) {
	                    keySchedule[ksRow] = keyWords[ksRow];
	                } else {
	                    t = keySchedule[ksRow - 1];

	                    if (!(ksRow % keySize)) {
	                        // Rot word
	                        t = (t << 8) | (t >>> 24);

	                        // Sub word
	                        t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];

	                        // Mix Rcon
	                        t ^= RCON[(ksRow / keySize) | 0] << 24;
	                    } else if (keySize > 6 && ksRow % keySize == 4) {
	                        // Sub word
	                        t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
	                    }

	                    keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t;
	                }
	            }

	            // Compute inv key schedule
	            var invKeySchedule = this._invKeySchedule = [];
	            for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) {
	                var ksRow = ksRows - invKsRow;

	                if (invKsRow % 4) {
	                    var t = keySchedule[ksRow];
	                } else {
	                    var t = keySchedule[ksRow - 4];
	                }

	                if (invKsRow < 4 || ksRow <= 4) {
	                    invKeySchedule[invKsRow] = t;
	                } else {
	                    invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^
	                                               INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]];
	                }
	            }
	        },

	        encryptBlock: function (M, offset) {
	            this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX);
	        },

	        decryptBlock: function (M, offset) {
	            // Swap 2nd and 4th rows
	            var t = M[offset + 1];
	            M[offset + 1] = M[offset + 3];
	            M[offset + 3] = t;

	            this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX);

	            // Inv swap 2nd and 4th rows
	            var t = M[offset + 1];
	            M[offset + 1] = M[offset + 3];
	            M[offset + 3] = t;
	        },

	        _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) {
	            // Shortcut
	            var nRounds = this._nRounds;

	            // Get input, add round key
	            var s0 = M[offset]     ^ keySchedule[0];
	            var s1 = M[offset + 1] ^ keySchedule[1];
	            var s2 = M[offset + 2] ^ keySchedule[2];
	            var s3 = M[offset + 3] ^ keySchedule[3];

	            // Key schedule row counter
	            var ksRow = 4;

	            // Rounds
	            for (var round = 1; round < nRounds; round++) {
	                // Shift rows, sub bytes, mix columns, add round key
	                var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++];
	                var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++];
	                var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++];
	                var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++];

	                // Update state
	                s0 = t0;
	                s1 = t1;
	                s2 = t2;
	                s3 = t3;
	            }

	            // Shift rows, sub bytes, add round key
	            var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++];
	            var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++];
	            var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++];
	            var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++];

	            // Set output
	            M[offset]     = t0;
	            M[offset + 1] = t1;
	            M[offset + 2] = t2;
	            M[offset + 3] = t3;
	        },

	        keySize: 256/32
	    });

	    /**
	     * Shortcut functions to the cipher's object interface.
	     *
	     * @example
	     *
	     *     var ciphertext = CryptoJS.AES.encrypt(message, key, cfg);
	     *     var plaintext  = CryptoJS.AES.decrypt(ciphertext, key, cfg);
	     */
	    C.AES = BlockCipher._createHelper(AES);
	}());


	return CryptoJS.AES;

}));

/***/ }),

/***/ "./node_modules/crypto-js/blowfish.js":
/*!********************************************!*\
  !*** ./node_modules/crypto-js/blowfish.js ***!
  \********************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./enc-base64 */ "./node_modules/crypto-js/enc-base64.js"), __webpack_require__(/*! ./md5 */ "./node_modules/crypto-js/md5.js"), __webpack_require__(/*! ./evpkdf */ "./node_modules/crypto-js/evpkdf.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var BlockCipher = C_lib.BlockCipher;
	    var C_algo = C.algo;

	    const N = 16;

	    //Origin pbox and sbox, derived from PI
	    const ORIG_P = [
	        0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
	        0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
	        0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
	        0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
	        0x9216D5D9, 0x8979FB1B
	    ];

	    const ORIG_S = [
	        [   0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
	            0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
	            0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
	            0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
	            0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
	            0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
	            0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
	            0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
	            0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
	            0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
	            0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
	            0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
	            0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
	            0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
	            0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
	            0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
	            0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
	            0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
	            0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
	            0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
	            0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
	            0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
	            0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
	            0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
	            0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
	            0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
	            0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
	            0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
	            0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
	            0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
	            0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
	            0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
	            0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
	            0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
	            0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
	            0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
	            0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
	            0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
	            0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
	            0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
	            0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
	            0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
	            0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
	            0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
	            0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
	            0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
	            0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
	            0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
	            0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
	            0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
	            0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
	            0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
	            0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
	            0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
	            0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
	            0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
	            0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
	            0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
	            0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
	            0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
	            0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
	            0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
	            0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
	            0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A   ],
	        [   0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
	            0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
	            0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
	            0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
	            0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
	            0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
	            0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
	            0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
	            0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
	            0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
	            0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
	            0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
	            0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
	            0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
	            0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
	            0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
	            0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
	            0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
	            0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
	            0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
	            0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
	            0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
	            0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
	            0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
	            0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
	            0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
	            0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
	            0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
	            0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
	            0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
	            0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
	            0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
	            0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
	            0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
	            0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
	            0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
	            0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
	            0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
	            0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
	            0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
	            0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
	            0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
	            0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
	            0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
	            0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
	            0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
	            0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
	            0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
	            0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
	            0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
	            0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
	            0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
	            0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
	            0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
	            0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
	            0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
	            0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
	            0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
	            0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
	            0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
	            0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
	            0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
	            0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
	            0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7   ],
	        [   0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
	            0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
	            0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
	            0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
	            0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
	            0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
	            0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
	            0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
	            0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
	            0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
	            0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
	            0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
	            0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
	            0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
	            0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
	            0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
	            0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
	            0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
	            0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
	            0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
	            0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
	            0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
	            0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
	            0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
	            0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
	            0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
	            0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
	            0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
	            0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
	            0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
	            0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
	            0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
	            0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
	            0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
	            0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
	            0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
	            0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
	            0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
	            0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
	            0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
	            0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
	            0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
	            0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
	            0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
	            0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
	            0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
	            0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
	            0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
	            0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
	            0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
	            0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
	            0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
	            0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
	            0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
	            0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
	            0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
	            0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
	            0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
	            0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
	            0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
	            0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
	            0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
	            0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
	            0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0  ],
	        [   0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
	            0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
	            0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
	            0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
	            0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
	            0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
	            0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
	            0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
	            0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
	            0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
	            0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
	            0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
	            0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
	            0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
	            0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
	            0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
	            0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
	            0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
	            0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
	            0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
	            0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
	            0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
	            0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
	            0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
	            0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
	            0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
	            0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
	            0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
	            0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
	            0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
	            0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
	            0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
	            0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
	            0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
	            0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
	            0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
	            0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
	            0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
	            0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
	            0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
	            0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
	            0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
	            0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
	            0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
	            0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
	            0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
	            0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
	            0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
	            0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
	            0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
	            0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
	            0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
	            0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
	            0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
	            0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
	            0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
	            0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
	            0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
	            0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
	            0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
	            0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
	            0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
	            0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
	            0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6  ]
	    ];

	    var BLOWFISH_CTX = {
	        pbox: [],
	        sbox: []
	    }

	    function F(ctx, x){
	        let a = (x >> 24) & 0xFF;
	        let b = (x >> 16) & 0xFF;
	        let c = (x >> 8) & 0xFF;
	        let d = x & 0xFF;

	        let y = ctx.sbox[0][a] + ctx.sbox[1][b];
	        y = y ^ ctx.sbox[2][c];
	        y = y + ctx.sbox[3][d];

	        return y;
	    }

	    function BlowFish_Encrypt(ctx, left, right){
	        let Xl = left;
	        let Xr = right;
	        let temp;

	        for(let i = 0; i < N; ++i){
	            Xl = Xl ^ ctx.pbox[i];
	            Xr = F(ctx, Xl) ^ Xr;

	            temp = Xl;
	            Xl = Xr;
	            Xr = temp;
	        }

	        temp = Xl;
	        Xl = Xr;
	        Xr = temp;

	        Xr = Xr ^ ctx.pbox[N];
	        Xl = Xl ^ ctx.pbox[N + 1];

	        return {left: Xl, right: Xr};
	    }

	    function BlowFish_Decrypt(ctx, left, right){
	        let Xl = left;
	        let Xr = right;
	        let temp;

	        for(let i = N + 1; i > 1; --i){
	            Xl = Xl ^ ctx.pbox[i];
	            Xr = F(ctx, Xl) ^ Xr;

	            temp = Xl;
	            Xl = Xr;
	            Xr = temp;
	        }

	        temp = Xl;
	        Xl = Xr;
	        Xr = temp;

	        Xr = Xr ^ ctx.pbox[1];
	        Xl = Xl ^ ctx.pbox[0];

	        return {left: Xl, right: Xr};
	    }

	    /**
	     * Initialization ctx's pbox and sbox.
	     *
	     * @param {Object} ctx The object has pbox and sbox.
	     * @param {Array} key An array of 32-bit words.
	     * @param {int} keysize The length of the key.
	     *
	     * @example
	     *
	     *     BlowFishInit(BLOWFISH_CTX, key, 128/32);
	     */
	    function BlowFishInit(ctx, key, keysize)
	    {
	        for(let Row = 0; Row < 4; Row++)
	        {
	            ctx.sbox[Row] = [];
	            for(let Col = 0; Col < 256; Col++)
	            {
	                ctx.sbox[Row][Col] = ORIG_S[Row][Col];
	            }
	        }

	        let keyIndex = 0;
	        for(let index = 0; index < N + 2; index++)
	        {
	            ctx.pbox[index] = ORIG_P[index] ^ key[keyIndex];
	            keyIndex++;
	            if(keyIndex >= keysize)
	            {
	                keyIndex = 0;
	            }
	        }

	        let Data1 = 0;
	        let Data2 = 0;
	        let res = 0;
	        for(let i = 0; i < N + 2; i += 2)
	        {
	            res = BlowFish_Encrypt(ctx, Data1, Data2);
	            Data1 = res.left;
	            Data2 = res.right;
	            ctx.pbox[i] = Data1;
	            ctx.pbox[i + 1] = Data2;
	        }

	        for(let i = 0; i < 4; i++)
	        {
	            for(let j = 0; j < 256; j += 2)
	            {
	                res = BlowFish_Encrypt(ctx, Data1, Data2);
	                Data1 = res.left;
	                Data2 = res.right;
	                ctx.sbox[i][j] = Data1;
	                ctx.sbox[i][j + 1] = Data2;
	            }
	        }

	        return true;
	    }

	    /**
	     * Blowfish block cipher algorithm.
	     */
	    var Blowfish = C_algo.Blowfish = BlockCipher.extend({
	        _doReset: function () {
	            // Skip reset of nRounds has been set before and key did not change
	            if (this._keyPriorReset === this._key) {
	                return;
	            }

	            // Shortcuts
	            var key = this._keyPriorReset = this._key;
	            var keyWords = key.words;
	            var keySize = key.sigBytes / 4;

	            //Initialization pbox and sbox
	            BlowFishInit(BLOWFISH_CTX, keyWords, keySize);
	        },

	        encryptBlock: function (M, offset) {
	            var res = BlowFish_Encrypt(BLOWFISH_CTX, M[offset], M[offset + 1]);
	            M[offset] = res.left;
	            M[offset + 1] = res.right;
	        },

	        decryptBlock: function (M, offset) {
	            var res = BlowFish_Decrypt(BLOWFISH_CTX, M[offset], M[offset + 1]);
	            M[offset] = res.left;
	            M[offset + 1] = res.right;
	        },

	        blockSize: 64/32,

	        keySize: 128/32,

	        ivSize: 64/32
	    });

	    /**
	     * Shortcut functions to the cipher's object interface.
	     *
	     * @example
	     *
	     *     var ciphertext = CryptoJS.Blowfish.encrypt(message, key, cfg);
	     *     var plaintext  = CryptoJS.Blowfish.decrypt(ciphertext, key, cfg);
	     */
	    C.Blowfish = BlockCipher._createHelper(Blowfish);
	}());


	return CryptoJS.Blowfish;

}));

/***/ }),

/***/ "./node_modules/crypto-js/cipher-core.js":
/*!***********************************************!*\
  !*** ./node_modules/crypto-js/cipher-core.js ***!
  \***********************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./evpkdf */ "./node_modules/crypto-js/evpkdf.js"));
	}
	else {}
}(this, function (CryptoJS) {

	/**
	 * Cipher core components.
	 */
	CryptoJS.lib.Cipher || (function (undefined) {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var Base = C_lib.Base;
	    var WordArray = C_lib.WordArray;
	    var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm;
	    var C_enc = C.enc;
	    var Utf8 = C_enc.Utf8;
	    var Base64 = C_enc.Base64;
	    var C_algo = C.algo;
	    var EvpKDF = C_algo.EvpKDF;

	    /**
	     * Abstract base cipher template.
	     *
	     * @property {number} keySize This cipher's key size. Default: 4 (128 bits)
	     * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits)
	     * @property {number} _ENC_XFORM_MODE A constant representing encryption mode.
	     * @property {number} _DEC_XFORM_MODE A constant representing decryption mode.
	     */
	    var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({
	        /**
	         * Configuration options.
	         *
	         * @property {WordArray} iv The IV to use for this operation.
	         */
	        cfg: Base.extend(),

	        /**
	         * Creates this cipher in encryption mode.
	         *
	         * @param {WordArray} key The key.
	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
	         *
	         * @return {Cipher} A cipher instance.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray });
	         */
	        createEncryptor: function (key, cfg) {
	            return this.create(this._ENC_XFORM_MODE, key, cfg);
	        },

	        /**
	         * Creates this cipher in decryption mode.
	         *
	         * @param {WordArray} key The key.
	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
	         *
	         * @return {Cipher} A cipher instance.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray });
	         */
	        createDecryptor: function (key, cfg) {
	            return this.create(this._DEC_XFORM_MODE, key, cfg);
	        },

	        /**
	         * Initializes a newly created cipher.
	         *
	         * @param {number} xformMode Either the encryption or decryption transormation mode constant.
	         * @param {WordArray} key The key.
	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
	         *
	         * @example
	         *
	         *     var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray });
	         */
	        init: function (xformMode, key, cfg) {
	            // Apply config defaults
	            this.cfg = this.cfg.extend(cfg);

	            // Store transform mode and key
	            this._xformMode = xformMode;
	            this._key = key;

	            // Set initial values
	            this.reset();
	        },

	        /**
	         * Resets this cipher to its initial state.
	         *
	         * @example
	         *
	         *     cipher.reset();
	         */
	        reset: function () {
	            // Reset data buffer
	            BufferedBlockAlgorithm.reset.call(this);

	            // Perform concrete-cipher logic
	            this._doReset();
	        },

	        /**
	         * Adds data to be encrypted or decrypted.
	         *
	         * @param {WordArray|string} dataUpdate The data to encrypt or decrypt.
	         *
	         * @return {WordArray} The data after processing.
	         *
	         * @example
	         *
	         *     var encrypted = cipher.process('data');
	         *     var encrypted = cipher.process(wordArray);
	         */
	        process: function (dataUpdate) {
	            // Append
	            this._append(dataUpdate);

	            // Process available blocks
	            return this._process();
	        },

	        /**
	         * Finalizes the encryption or decryption process.
	         * Note that the finalize operation is effectively a destructive, read-once operation.
	         *
	         * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt.
	         *
	         * @return {WordArray} The data after final processing.
	         *
	         * @example
	         *
	         *     var encrypted = cipher.finalize();
	         *     var encrypted = cipher.finalize('data');
	         *     var encrypted = cipher.finalize(wordArray);
	         */
	        finalize: function (dataUpdate) {
	            // Final data update
	            if (dataUpdate) {
	                this._append(dataUpdate);
	            }

	            // Perform concrete-cipher logic
	            var finalProcessedData = this._doFinalize();

	            return finalProcessedData;
	        },

	        keySize: 128/32,

	        ivSize: 128/32,

	        _ENC_XFORM_MODE: 1,

	        _DEC_XFORM_MODE: 2,

	        /**
	         * Creates shortcut functions to a cipher's object interface.
	         *
	         * @param {Cipher} cipher The cipher to create a helper for.
	         *
	         * @return {Object} An object with encrypt and decrypt shortcut functions.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES);
	         */
	        _createHelper: (function () {
	            function selectCipherStrategy(key) {
	                if (typeof key == 'string') {
	                    return PasswordBasedCipher;
	                } else {
	                    return SerializableCipher;
	                }
	            }

	            return function (cipher) {
	                return {
	                    encrypt: function (message, key, cfg) {
	                        return selectCipherStrategy(key).encrypt(cipher, message, key, cfg);
	                    },

	                    decrypt: function (ciphertext, key, cfg) {
	                        return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg);
	                    }
	                };
	            };
	        }())
	    });

	    /**
	     * Abstract base stream cipher template.
	     *
	     * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits)
	     */
	    var StreamCipher = C_lib.StreamCipher = Cipher.extend({
	        _doFinalize: function () {
	            // Process partial blocks
	            var finalProcessedBlocks = this._process(!!'flush');

	            return finalProcessedBlocks;
	        },

	        blockSize: 1
	    });

	    /**
	     * Mode namespace.
	     */
	    var C_mode = C.mode = {};

	    /**
	     * Abstract base block cipher mode template.
	     */
	    var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({
	        /**
	         * Creates this mode for encryption.
	         *
	         * @param {Cipher} cipher A block cipher instance.
	         * @param {Array} iv The IV words.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words);
	         */
	        createEncryptor: function (cipher, iv) {
	            return this.Encryptor.create(cipher, iv);
	        },

	        /**
	         * Creates this mode for decryption.
	         *
	         * @param {Cipher} cipher A block cipher instance.
	         * @param {Array} iv The IV words.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words);
	         */
	        createDecryptor: function (cipher, iv) {
	            return this.Decryptor.create(cipher, iv);
	        },

	        /**
	         * Initializes a newly created mode.
	         *
	         * @param {Cipher} cipher A block cipher instance.
	         * @param {Array} iv The IV words.
	         *
	         * @example
	         *
	         *     var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words);
	         */
	        init: function (cipher, iv) {
	            this._cipher = cipher;
	            this._iv = iv;
	        }
	    });

	    /**
	     * Cipher Block Chaining mode.
	     */
	    var CBC = C_mode.CBC = (function () {
	        /**
	         * Abstract base CBC mode.
	         */
	        var CBC = BlockCipherMode.extend();

	        /**
	         * CBC encryptor.
	         */
	        CBC.Encryptor = CBC.extend({
	            /**
	             * Processes the data block at offset.
	             *
	             * @param {Array} words The data words to operate on.
	             * @param {number} offset The offset where the block starts.
	             *
	             * @example
	             *
	             *     mode.processBlock(data.words, offset);
	             */
	            processBlock: function (words, offset) {
	                // Shortcuts
	                var cipher = this._cipher;
	                var blockSize = cipher.blockSize;

	                // XOR and encrypt
	                xorBlock.call(this, words, offset, blockSize);
	                cipher.encryptBlock(words, offset);

	                // Remember this block to use with next block
	                this._prevBlock = words.slice(offset, offset + blockSize);
	            }
	        });

	        /**
	         * CBC decryptor.
	         */
	        CBC.Decryptor = CBC.extend({
	            /**
	             * Processes the data block at offset.
	             *
	             * @param {Array} words The data words to operate on.
	             * @param {number} offset The offset where the block starts.
	             *
	             * @example
	             *
	             *     mode.processBlock(data.words, offset);
	             */
	            processBlock: function (words, offset) {
	                // Shortcuts
	                var cipher = this._cipher;
	                var blockSize = cipher.blockSize;

	                // Remember this block to use with next block
	                var thisBlock = words.slice(offset, offset + blockSize);

	                // Decrypt and XOR
	                cipher.decryptBlock(words, offset);
	                xorBlock.call(this, words, offset, blockSize);

	                // This block becomes the previous block
	                this._prevBlock = thisBlock;
	            }
	        });

	        function xorBlock(words, offset, blockSize) {
	            var block;

	            // Shortcut
	            var iv = this._iv;

	            // Choose mixing block
	            if (iv) {
	                block = iv;

	                // Remove IV for subsequent blocks
	                this._iv = undefined;
	            } else {
	                block = this._prevBlock;
	            }

	            // XOR blocks
	            for (var i = 0; i < blockSize; i++) {
	                words[offset + i] ^= block[i];
	            }
	        }

	        return CBC;
	    }());

	    /**
	     * Padding namespace.
	     */
	    var C_pad = C.pad = {};

	    /**
	     * PKCS #5/7 padding strategy.
	     */
	    var Pkcs7 = C_pad.Pkcs7 = {
	        /**
	         * Pads data using the algorithm defined in PKCS #5/7.
	         *
	         * @param {WordArray} data The data to pad.
	         * @param {number} blockSize The multiple that the data should be padded to.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     CryptoJS.pad.Pkcs7.pad(wordArray, 4);
	         */
	        pad: function (data, blockSize) {
	            // Shortcut
	            var blockSizeBytes = blockSize * 4;

	            // Count padding bytes
	            var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes;

	            // Create padding word
	            var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes;

	            // Create padding
	            var paddingWords = [];
	            for (var i = 0; i < nPaddingBytes; i += 4) {
	                paddingWords.push(paddingWord);
	            }
	            var padding = WordArray.create(paddingWords, nPaddingBytes);

	            // Add padding
	            data.concat(padding);
	        },

	        /**
	         * Unpads data that had been padded using the algorithm defined in PKCS #5/7.
	         *
	         * @param {WordArray} data The data to unpad.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     CryptoJS.pad.Pkcs7.unpad(wordArray);
	         */
	        unpad: function (data) {
	            // Get number of padding bytes from last byte
	            var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;

	            // Remove padding
	            data.sigBytes -= nPaddingBytes;
	        }
	    };

	    /**
	     * Abstract base block cipher template.
	     *
	     * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits)
	     */
	    var BlockCipher = C_lib.BlockCipher = Cipher.extend({
	        /**
	         * Configuration options.
	         *
	         * @property {Mode} mode The block mode to use. Default: CBC
	         * @property {Padding} padding The padding strategy to use. Default: Pkcs7
	         */
	        cfg: Cipher.cfg.extend({
	            mode: CBC,
	            padding: Pkcs7
	        }),

	        reset: function () {
	            var modeCreator;

	            // Reset cipher
	            Cipher.reset.call(this);

	            // Shortcuts
	            var cfg = this.cfg;
	            var iv = cfg.iv;
	            var mode = cfg.mode;

	            // Reset block mode
	            if (this._xformMode == this._ENC_XFORM_MODE) {
	                modeCreator = mode.createEncryptor;
	            } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
	                modeCreator = mode.createDecryptor;
	                // Keep at least one block in the buffer for unpadding
	                this._minBufferSize = 1;
	            }

	            if (this._mode && this._mode.__creator == modeCreator) {
	                this._mode.init(this, iv && iv.words);
	            } else {
	                this._mode = modeCreator.call(mode, this, iv && iv.words);
	                this._mode.__creator = modeCreator;
	            }
	        },

	        _doProcessBlock: function (words, offset) {
	            this._mode.processBlock(words, offset);
	        },

	        _doFinalize: function () {
	            var finalProcessedBlocks;

	            // Shortcut
	            var padding = this.cfg.padding;

	            // Finalize
	            if (this._xformMode == this._ENC_XFORM_MODE) {
	                // Pad data
	                padding.pad(this._data, this.blockSize);

	                // Process final blocks
	                finalProcessedBlocks = this._process(!!'flush');
	            } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
	                // Process final blocks
	                finalProcessedBlocks = this._process(!!'flush');

	                // Unpad data
	                padding.unpad(finalProcessedBlocks);
	            }

	            return finalProcessedBlocks;
	        },

	        blockSize: 128/32
	    });

	    /**
	     * A collection of cipher parameters.
	     *
	     * @property {WordArray} ciphertext The raw ciphertext.
	     * @property {WordArray} key The key to this ciphertext.
	     * @property {WordArray} iv The IV used in the ciphering operation.
	     * @property {WordArray} salt The salt used with a key derivation function.
	     * @property {Cipher} algorithm The cipher algorithm.
	     * @property {Mode} mode The block mode used in the ciphering operation.
	     * @property {Padding} padding The padding scheme used in the ciphering operation.
	     * @property {number} blockSize The block size of the cipher.
	     * @property {Format} formatter The default formatting strategy to convert this cipher params object to a string.
	     */
	    var CipherParams = C_lib.CipherParams = Base.extend({
	        /**
	         * Initializes a newly created cipher params object.
	         *
	         * @param {Object} cipherParams An object with any of the possible cipher parameters.
	         *
	         * @example
	         *
	         *     var cipherParams = CryptoJS.lib.CipherParams.create({
	         *         ciphertext: ciphertextWordArray,
	         *         key: keyWordArray,
	         *         iv: ivWordArray,
	         *         salt: saltWordArray,
	         *         algorithm: CryptoJS.algo.AES,
	         *         mode: CryptoJS.mode.CBC,
	         *         padding: CryptoJS.pad.PKCS7,
	         *         blockSize: 4,
	         *         formatter: CryptoJS.format.OpenSSL
	         *     });
	         */
	        init: function (cipherParams) {
	            this.mixIn(cipherParams);
	        },

	        /**
	         * Converts this cipher params object to a string.
	         *
	         * @param {Format} formatter (Optional) The formatting strategy to use.
	         *
	         * @return {string} The stringified cipher params.
	         *
	         * @throws Error If neither the formatter nor the default formatter is set.
	         *
	         * @example
	         *
	         *     var string = cipherParams + '';
	         *     var string = cipherParams.toString();
	         *     var string = cipherParams.toString(CryptoJS.format.OpenSSL);
	         */
	        toString: function (formatter) {
	            return (formatter || this.formatter).stringify(this);
	        }
	    });

	    /**
	     * Format namespace.
	     */
	    var C_format = C.format = {};

	    /**
	     * OpenSSL formatting strategy.
	     */
	    var OpenSSLFormatter = C_format.OpenSSL = {
	        /**
	         * Converts a cipher params object to an OpenSSL-compatible string.
	         *
	         * @param {CipherParams} cipherParams The cipher params object.
	         *
	         * @return {string} The OpenSSL-compatible string.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams);
	         */
	        stringify: function (cipherParams) {
	            var wordArray;

	            // Shortcuts
	            var ciphertext = cipherParams.ciphertext;
	            var salt = cipherParams.salt;

	            // Format
	            if (salt) {
	                wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext);
	            } else {
	                wordArray = ciphertext;
	            }

	            return wordArray.toString(Base64);
	        },

	        /**
	         * Converts an OpenSSL-compatible string to a cipher params object.
	         *
	         * @param {string} openSSLStr The OpenSSL-compatible string.
	         *
	         * @return {CipherParams} The cipher params object.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString);
	         */
	        parse: function (openSSLStr) {
	            var salt;

	            // Parse base64
	            var ciphertext = Base64.parse(openSSLStr);

	            // Shortcut
	            var ciphertextWords = ciphertext.words;

	            // Test for salt
	            if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) {
	                // Extract salt
	                salt = WordArray.create(ciphertextWords.slice(2, 4));

	                // Remove salt from ciphertext
	                ciphertextWords.splice(0, 4);
	                ciphertext.sigBytes -= 16;
	            }

	            return CipherParams.create({ ciphertext: ciphertext, salt: salt });
	        }
	    };

	    /**
	     * A cipher wrapper that returns ciphertext as a serializable cipher params object.
	     */
	    var SerializableCipher = C_lib.SerializableCipher = Base.extend({
	        /**
	         * Configuration options.
	         *
	         * @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL
	         */
	        cfg: Base.extend({
	            format: OpenSSLFormatter
	        }),

	        /**
	         * Encrypts a message.
	         *
	         * @param {Cipher} cipher The cipher algorithm to use.
	         * @param {WordArray|string} message The message to encrypt.
	         * @param {WordArray} key The key.
	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
	         *
	         * @return {CipherParams} A cipher params object.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key);
	         *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv });
	         *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL });
	         */
	        encrypt: function (cipher, message, key, cfg) {
	            // Apply config defaults
	            cfg = this.cfg.extend(cfg);

	            // Encrypt
	            var encryptor = cipher.createEncryptor(key, cfg);
	            var ciphertext = encryptor.finalize(message);

	            // Shortcut
	            var cipherCfg = encryptor.cfg;

	            // Create and return serializable cipher params
	            return CipherParams.create({
	                ciphertext: ciphertext,
	                key: key,
	                iv: cipherCfg.iv,
	                algorithm: cipher,
	                mode: cipherCfg.mode,
	                padding: cipherCfg.padding,
	                blockSize: cipher.blockSize,
	                formatter: cfg.format
	            });
	        },

	        /**
	         * Decrypts serialized ciphertext.
	         *
	         * @param {Cipher} cipher The cipher algorithm to use.
	         * @param {CipherParams|string} ciphertext The ciphertext to decrypt.
	         * @param {WordArray} key The key.
	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
	         *
	         * @return {WordArray} The plaintext.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL });
	         *     var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL });
	         */
	        decrypt: function (cipher, ciphertext, key, cfg) {
	            // Apply config defaults
	            cfg = this.cfg.extend(cfg);

	            // Convert string to CipherParams
	            ciphertext = this._parse(ciphertext, cfg.format);

	            // Decrypt
	            var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext);

	            return plaintext;
	        },

	        /**
	         * Converts serialized ciphertext to CipherParams,
	         * else assumed CipherParams already and returns ciphertext unchanged.
	         *
	         * @param {CipherParams|string} ciphertext The ciphertext.
	         * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext.
	         *
	         * @return {CipherParams} The unserialized ciphertext.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format);
	         */
	        _parse: function (ciphertext, format) {
	            if (typeof ciphertext == 'string') {
	                return format.parse(ciphertext, this);
	            } else {
	                return ciphertext;
	            }
	        }
	    });

	    /**
	     * Key derivation function namespace.
	     */
	    var C_kdf = C.kdf = {};

	    /**
	     * OpenSSL key derivation function.
	     */
	    var OpenSSLKdf = C_kdf.OpenSSL = {
	        /**
	         * Derives a key and IV from a password.
	         *
	         * @param {string} password The password to derive from.
	         * @param {number} keySize The size in words of the key to generate.
	         * @param {number} ivSize The size in words of the IV to generate.
	         * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly.
	         *
	         * @return {CipherParams} A cipher params object with the key, IV, and salt.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32);
	         *     var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
	         */
	        execute: function (password, keySize, ivSize, salt, hasher) {
	            // Generate random salt
	            if (!salt) {
	                salt = WordArray.random(64/8);
	            }

	            // Derive key and IV
	            if (!hasher) {
	                var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
	            } else {
	                var key = EvpKDF.create({ keySize: keySize + ivSize, hasher: hasher }).compute(password, salt);
	            }


	            // Separate key and IV
	            var iv = WordArray.create(key.words.slice(keySize), ivSize * 4);
	            key.sigBytes = keySize * 4;

	            // Return params
	            return CipherParams.create({ key: key, iv: iv, salt: salt });
	        }
	    };

	    /**
	     * A serializable cipher wrapper that derives the key from a password,
	     * and returns ciphertext as a serializable cipher params object.
	     */
	    var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({
	        /**
	         * Configuration options.
	         *
	         * @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL
	         */
	        cfg: SerializableCipher.cfg.extend({
	            kdf: OpenSSLKdf
	        }),

	        /**
	         * Encrypts a message using a password.
	         *
	         * @param {Cipher} cipher The cipher algorithm to use.
	         * @param {WordArray|string} message The message to encrypt.
	         * @param {string} password The password.
	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
	         *
	         * @return {CipherParams} A cipher params object.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password');
	         *     var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL });
	         */
	        encrypt: function (cipher, message, password, cfg) {
	            // Apply config defaults
	            cfg = this.cfg.extend(cfg);

	            // Derive key and other params
	            var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, cfg.salt, cfg.hasher);

	            // Add IV to config
	            cfg.iv = derivedParams.iv;

	            // Encrypt
	            var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg);

	            // Mix in derived params
	            ciphertext.mixIn(derivedParams);

	            return ciphertext;
	        },

	        /**
	         * Decrypts serialized ciphertext using a password.
	         *
	         * @param {Cipher} cipher The cipher algorithm to use.
	         * @param {CipherParams|string} ciphertext The ciphertext to decrypt.
	         * @param {string} password The password.
	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
	         *
	         * @return {WordArray} The plaintext.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL });
	         *     var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL });
	         */
	        decrypt: function (cipher, ciphertext, password, cfg) {
	            // Apply config defaults
	            cfg = this.cfg.extend(cfg);

	            // Convert string to CipherParams
	            ciphertext = this._parse(ciphertext, cfg.format);

	            // Derive key and other params
	            var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt, cfg.hasher);

	            // Add IV to config
	            cfg.iv = derivedParams.iv;

	            // Decrypt
	            var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg);

	            return plaintext;
	        }
	    });
	}());


}));

/***/ }),

/***/ "./node_modules/crypto-js/core.js":
/*!****************************************!*\
  !*** ./node_modules/crypto-js/core.js ***!
  \****************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory) {
	if (true) {
		// CommonJS
		module.exports = exports = factory();
	}
	else {}
}(this, function () {

	/*globals window, global, require*/

	/**
	 * CryptoJS core components.
	 */
	var CryptoJS = CryptoJS || (function (Math, undefined) {

	    var crypto;

	    // Native crypto from window (Browser)
	    if (typeof window !== 'undefined' && window.crypto) {
	        crypto = window.crypto;
	    }

	    // Native crypto in web worker (Browser)
	    if (typeof self !== 'undefined' && self.crypto) {
	        crypto = self.crypto;
	    }

	    // Native crypto from worker
	    if (typeof globalThis !== 'undefined' && globalThis.crypto) {
	        crypto = globalThis.crypto;
	    }

	    // Native (experimental IE 11) crypto from window (Browser)
	    if (!crypto && typeof window !== 'undefined' && window.msCrypto) {
	        crypto = window.msCrypto;
	    }

	    // Native crypto from global (NodeJS)
	    if (!crypto && typeof __webpack_require__.g !== 'undefined' && __webpack_require__.g.crypto) {
	        crypto = __webpack_require__.g.crypto;
	    }

	    // Native crypto import via require (NodeJS)
	    if (!crypto && "function" === 'function') {
	        try {
	            crypto = __webpack_require__(/*! crypto */ "?9157");
	        } catch (err) {}
	    }

	    /*
	     * Cryptographically secure pseudorandom number generator
	     *
	     * As Math.random() is cryptographically not safe to use
	     */
	    var cryptoSecureRandomInt = function () {
	        if (crypto) {
	            // Use getRandomValues method (Browser)
	            if (typeof crypto.getRandomValues === 'function') {
	                try {
	                    return crypto.getRandomValues(new Uint32Array(1))[0];
	                } catch (err) {}
	            }

	            // Use randomBytes method (NodeJS)
	            if (typeof crypto.randomBytes === 'function') {
	                try {
	                    return crypto.randomBytes(4).readInt32LE();
	                } catch (err) {}
	            }
	        }

	        throw new Error('Native crypto module could not be used to get secure random number.');
	    };

	    /*
	     * Local polyfill of Object.create

	     */
	    var create = Object.create || (function () {
	        function F() {}

	        return function (obj) {
	            var subtype;

	            F.prototype = obj;

	            subtype = new F();

	            F.prototype = null;

	            return subtype;
	        };
	    }());

	    /**
	     * CryptoJS namespace.
	     */
	    var C = {};

	    /**
	     * Library namespace.
	     */
	    var C_lib = C.lib = {};

	    /**
	     * Base object for prototypal inheritance.
	     */
	    var Base = C_lib.Base = (function () {


	        return {
	            /**
	             * Creates a new object that inherits from this object.
	             *
	             * @param {Object} overrides Properties to copy into the new object.
	             *
	             * @return {Object} The new object.
	             *
	             * @static
	             *
	             * @example
	             *
	             *     var MyType = CryptoJS.lib.Base.extend({
	             *         field: 'value',
	             *
	             *         method: function () {
	             *         }
	             *     });
	             */
	            extend: function (overrides) {
	                // Spawn
	                var subtype = create(this);

	                // Augment
	                if (overrides) {
	                    subtype.mixIn(overrides);
	                }

	                // Create default initializer
	                if (!subtype.hasOwnProperty('init') || this.init === subtype.init) {
	                    subtype.init = function () {
	                        subtype.$super.init.apply(this, arguments);
	                    };
	                }

	                // Initializer's prototype is the subtype object
	                subtype.init.prototype = subtype;

	                // Reference supertype
	                subtype.$super = this;

	                return subtype;
	            },

	            /**
	             * Extends this object and runs the init method.
	             * Arguments to create() will be passed to init().
	             *
	             * @return {Object} The new object.
	             *
	             * @static
	             *
	             * @example
	             *
	             *     var instance = MyType.create();
	             */
	            create: function () {
	                var instance = this.extend();
	                instance.init.apply(instance, arguments);

	                return instance;
	            },

	            /**
	             * Initializes a newly created object.
	             * Override this method to add some logic when your objects are created.
	             *
	             * @example
	             *
	             *     var MyType = CryptoJS.lib.Base.extend({
	             *         init: function () {
	             *             // ...
	             *         }
	             *     });
	             */
	            init: function () {
	            },

	            /**
	             * Copies properties into this object.
	             *
	             * @param {Object} properties The properties to mix in.
	             *
	             * @example
	             *
	             *     MyType.mixIn({
	             *         field: 'value'
	             *     });
	             */
	            mixIn: function (properties) {
	                for (var propertyName in properties) {
	                    if (properties.hasOwnProperty(propertyName)) {
	                        this[propertyName] = properties[propertyName];
	                    }
	                }

	                // IE won't copy toString using the loop above
	                if (properties.hasOwnProperty('toString')) {
	                    this.toString = properties.toString;
	                }
	            },

	            /**
	             * Creates a copy of this object.
	             *
	             * @return {Object} The clone.
	             *
	             * @example
	             *
	             *     var clone = instance.clone();
	             */
	            clone: function () {
	                return this.init.prototype.extend(this);
	            }
	        };
	    }());

	    /**
	     * An array of 32-bit words.
	     *
	     * @property {Array} words The array of 32-bit words.
	     * @property {number} sigBytes The number of significant bytes in this word array.
	     */
	    var WordArray = C_lib.WordArray = Base.extend({
	        /**
	         * Initializes a newly created word array.
	         *
	         * @param {Array} words (Optional) An array of 32-bit words.
	         * @param {number} sigBytes (Optional) The number of significant bytes in the words.
	         *
	         * @example
	         *
	         *     var wordArray = CryptoJS.lib.WordArray.create();
	         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
	         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
	         */
	        init: function (words, sigBytes) {
	            words = this.words = words || [];

	            if (sigBytes != undefined) {
	                this.sigBytes = sigBytes;
	            } else {
	                this.sigBytes = words.length * 4;
	            }
	        },

	        /**
	         * Converts this word array to a string.
	         *
	         * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
	         *
	         * @return {string} The stringified word array.
	         *
	         * @example
	         *
	         *     var string = wordArray + '';
	         *     var string = wordArray.toString();
	         *     var string = wordArray.toString(CryptoJS.enc.Utf8);
	         */
	        toString: function (encoder) {
	            return (encoder || Hex).stringify(this);
	        },

	        /**
	         * Concatenates a word array to this word array.
	         *
	         * @param {WordArray} wordArray The word array to append.
	         *
	         * @return {WordArray} This word array.
	         *
	         * @example
	         *
	         *     wordArray1.concat(wordArray2);
	         */
	        concat: function (wordArray) {
	            // Shortcuts
	            var thisWords = this.words;
	            var thatWords = wordArray.words;
	            var thisSigBytes = this.sigBytes;
	            var thatSigBytes = wordArray.sigBytes;

	            // Clamp excess bits
	            this.clamp();

	            // Concat
	            if (thisSigBytes % 4) {
	                // Copy one byte at a time
	                for (var i = 0; i < thatSigBytes; i++) {
	                    var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
	                    thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
	                }
	            } else {
	                // Copy one word at a time
	                for (var j = 0; j < thatSigBytes; j += 4) {
	                    thisWords[(thisSigBytes + j) >>> 2] = thatWords[j >>> 2];
	                }
	            }
	            this.sigBytes += thatSigBytes;

	            // Chainable
	            return this;
	        },

	        /**
	         * Removes insignificant bits.
	         *
	         * @example
	         *
	         *     wordArray.clamp();
	         */
	        clamp: function () {
	            // Shortcuts
	            var words = this.words;
	            var sigBytes = this.sigBytes;

	            // Clamp
	            words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
	            words.length = Math.ceil(sigBytes / 4);
	        },

	        /**
	         * Creates a copy of this word array.
	         *
	         * @return {WordArray} The clone.
	         *
	         * @example
	         *
	         *     var clone = wordArray.clone();
	         */
	        clone: function () {
	            var clone = Base.clone.call(this);
	            clone.words = this.words.slice(0);

	            return clone;
	        },

	        /**
	         * Creates a word array filled with random bytes.
	         *
	         * @param {number} nBytes The number of random bytes to generate.
	         *
	         * @return {WordArray} The random word array.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var wordArray = CryptoJS.lib.WordArray.random(16);
	         */
	        random: function (nBytes) {
	            var words = [];

	            for (var i = 0; i < nBytes; i += 4) {
	                words.push(cryptoSecureRandomInt());
	            }

	            return new WordArray.init(words, nBytes);
	        }
	    });

	    /**
	     * Encoder namespace.
	     */
	    var C_enc = C.enc = {};

	    /**
	     * Hex encoding strategy.
	     */
	    var Hex = C_enc.Hex = {
	        /**
	         * Converts a word array to a hex string.
	         *
	         * @param {WordArray} wordArray The word array.
	         *
	         * @return {string} The hex string.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var hexString = CryptoJS.enc.Hex.stringify(wordArray);
	         */
	        stringify: function (wordArray) {
	            // Shortcuts
	            var words = wordArray.words;
	            var sigBytes = wordArray.sigBytes;

	            // Convert
	            var hexChars = [];
	            for (var i = 0; i < sigBytes; i++) {
	                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
	                hexChars.push((bite >>> 4).toString(16));
	                hexChars.push((bite & 0x0f).toString(16));
	            }

	            return hexChars.join('');
	        },

	        /**
	         * Converts a hex string to a word array.
	         *
	         * @param {string} hexStr The hex string.
	         *
	         * @return {WordArray} The word array.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var wordArray = CryptoJS.enc.Hex.parse(hexString);
	         */
	        parse: function (hexStr) {
	            // Shortcut
	            var hexStrLength = hexStr.length;

	            // Convert
	            var words = [];
	            for (var i = 0; i < hexStrLength; i += 2) {
	                words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
	            }

	            return new WordArray.init(words, hexStrLength / 2);
	        }
	    };

	    /**
	     * Latin1 encoding strategy.
	     */
	    var Latin1 = C_enc.Latin1 = {
	        /**
	         * Converts a word array to a Latin1 string.
	         *
	         * @param {WordArray} wordArray The word array.
	         *
	         * @return {string} The Latin1 string.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
	         */
	        stringify: function (wordArray) {
	            // Shortcuts
	            var words = wordArray.words;
	            var sigBytes = wordArray.sigBytes;

	            // Convert
	            var latin1Chars = [];
	            for (var i = 0; i < sigBytes; i++) {
	                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
	                latin1Chars.push(String.fromCharCode(bite));
	            }

	            return latin1Chars.join('');
	        },

	        /**
	         * Converts a Latin1 string to a word array.
	         *
	         * @param {string} latin1Str The Latin1 string.
	         *
	         * @return {WordArray} The word array.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
	         */
	        parse: function (latin1Str) {
	            // Shortcut
	            var latin1StrLength = latin1Str.length;

	            // Convert
	            var words = [];
	            for (var i = 0; i < latin1StrLength; i++) {
	                words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
	            }

	            return new WordArray.init(words, latin1StrLength);
	        }
	    };

	    /**
	     * UTF-8 encoding strategy.
	     */
	    var Utf8 = C_enc.Utf8 = {
	        /**
	         * Converts a word array to a UTF-8 string.
	         *
	         * @param {WordArray} wordArray The word array.
	         *
	         * @return {string} The UTF-8 string.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
	         */
	        stringify: function (wordArray) {
	            try {
	                return decodeURIComponent(escape(Latin1.stringify(wordArray)));
	            } catch (e) {
	                throw new Error('Malformed UTF-8 data');
	            }
	        },

	        /**
	         * Converts a UTF-8 string to a word array.
	         *
	         * @param {string} utf8Str The UTF-8 string.
	         *
	         * @return {WordArray} The word array.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
	         */
	        parse: function (utf8Str) {
	            return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
	        }
	    };

	    /**
	     * Abstract buffered block algorithm template.
	     *
	     * The property blockSize must be implemented in a concrete subtype.
	     *
	     * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
	     */
	    var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
	        /**
	         * Resets this block algorithm's data buffer to its initial state.
	         *
	         * @example
	         *
	         *     bufferedBlockAlgorithm.reset();
	         */
	        reset: function () {
	            // Initial values
	            this._data = new WordArray.init();
	            this._nDataBytes = 0;
	        },

	        /**
	         * Adds new data to this block algorithm's buffer.
	         *
	         * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
	         *
	         * @example
	         *
	         *     bufferedBlockAlgorithm._append('data');
	         *     bufferedBlockAlgorithm._append(wordArray);
	         */
	        _append: function (data) {
	            // Convert string to WordArray, else assume WordArray already
	            if (typeof data == 'string') {
	                data = Utf8.parse(data);
	            }

	            // Append
	            this._data.concat(data);
	            this._nDataBytes += data.sigBytes;
	        },

	        /**
	         * Processes available data blocks.
	         *
	         * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
	         *
	         * @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
	         *
	         * @return {WordArray} The processed data.
	         *
	         * @example
	         *
	         *     var processedData = bufferedBlockAlgorithm._process();
	         *     var processedData = bufferedBlockAlgorithm._process(!!'flush');
	         */
	        _process: function (doFlush) {
	            var processedWords;

	            // Shortcuts
	            var data = this._data;
	            var dataWords = data.words;
	            var dataSigBytes = data.sigBytes;
	            var blockSize = this.blockSize;
	            var blockSizeBytes = blockSize * 4;

	            // Count blocks ready
	            var nBlocksReady = dataSigBytes / blockSizeBytes;
	            if (doFlush) {
	                // Round up to include partial blocks
	                nBlocksReady = Math.ceil(nBlocksReady);
	            } else {
	                // Round down to include only full blocks,
	                // less the number of blocks that must remain in the buffer
	                nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
	            }

	            // Count words ready
	            var nWordsReady = nBlocksReady * blockSize;

	            // Count bytes ready
	            var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);

	            // Process blocks
	            if (nWordsReady) {
	                for (var offset = 0; offset < nWordsReady; offset += blockSize) {
	                    // Perform concrete-algorithm logic
	                    this._doProcessBlock(dataWords, offset);
	                }

	                // Remove processed words
	                processedWords = dataWords.splice(0, nWordsReady);
	                data.sigBytes -= nBytesReady;
	            }

	            // Return processed words
	            return new WordArray.init(processedWords, nBytesReady);
	        },

	        /**
	         * Creates a copy of this object.
	         *
	         * @return {Object} The clone.
	         *
	         * @example
	         *
	         *     var clone = bufferedBlockAlgorithm.clone();
	         */
	        clone: function () {
	            var clone = Base.clone.call(this);
	            clone._data = this._data.clone();

	            return clone;
	        },

	        _minBufferSize: 0
	    });

	    /**
	     * Abstract hasher template.
	     *
	     * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
	     */
	    var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
	        /**
	         * Configuration options.
	         */
	        cfg: Base.extend(),

	        /**
	         * Initializes a newly created hasher.
	         *
	         * @param {Object} cfg (Optional) The configuration options to use for this hash computation.
	         *
	         * @example
	         *
	         *     var hasher = CryptoJS.algo.SHA256.create();
	         */
	        init: function (cfg) {
	            // Apply config defaults
	            this.cfg = this.cfg.extend(cfg);

	            // Set initial values
	            this.reset();
	        },

	        /**
	         * Resets this hasher to its initial state.
	         *
	         * @example
	         *
	         *     hasher.reset();
	         */
	        reset: function () {
	            // Reset data buffer
	            BufferedBlockAlgorithm.reset.call(this);

	            // Perform concrete-hasher logic
	            this._doReset();
	        },

	        /**
	         * Updates this hasher with a message.
	         *
	         * @param {WordArray|string} messageUpdate The message to append.
	         *
	         * @return {Hasher} This hasher.
	         *
	         * @example
	         *
	         *     hasher.update('message');
	         *     hasher.update(wordArray);
	         */
	        update: function (messageUpdate) {
	            // Append
	            this._append(messageUpdate);

	            // Update the hash
	            this._process();

	            // Chainable
	            return this;
	        },

	        /**
	         * Finalizes the hash computation.
	         * Note that the finalize operation is effectively a destructive, read-once operation.
	         *
	         * @param {WordArray|string} messageUpdate (Optional) A final message update.
	         *
	         * @return {WordArray} The hash.
	         *
	         * @example
	         *
	         *     var hash = hasher.finalize();
	         *     var hash = hasher.finalize('message');
	         *     var hash = hasher.finalize(wordArray);
	         */
	        finalize: function (messageUpdate) {
	            // Final message update
	            if (messageUpdate) {
	                this._append(messageUpdate);
	            }

	            // Perform concrete-hasher logic
	            var hash = this._doFinalize();

	            return hash;
	        },

	        blockSize: 512/32,

	        /**
	         * Creates a shortcut function to a hasher's object interface.
	         *
	         * @param {Hasher} hasher The hasher to create a helper for.
	         *
	         * @return {Function} The shortcut function.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
	         */
	        _createHelper: function (hasher) {
	            return function (message, cfg) {
	                return new hasher.init(cfg).finalize(message);
	            };
	        },

	        /**
	         * Creates a shortcut function to the HMAC's object interface.
	         *
	         * @param {Hasher} hasher The hasher to use in this HMAC helper.
	         *
	         * @return {Function} The shortcut function.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
	         */
	        _createHmacHelper: function (hasher) {
	            return function (message, key) {
	                return new C_algo.HMAC.init(hasher, key).finalize(message);
	            };
	        }
	    });

	    /**
	     * Algorithm namespace.
	     */
	    var C_algo = C.algo = {};

	    return C;
	}(Math));


	return CryptoJS;

}));

/***/ }),

/***/ "./node_modules/crypto-js/enc-base64.js":
/*!**********************************************!*\
  !*** ./node_modules/crypto-js/enc-base64.js ***!
  \**********************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var WordArray = C_lib.WordArray;
	    var C_enc = C.enc;

	    /**
	     * Base64 encoding strategy.
	     */
	    var Base64 = C_enc.Base64 = {
	        /**
	         * Converts a word array to a Base64 string.
	         *
	         * @param {WordArray} wordArray The word array.
	         *
	         * @return {string} The Base64 string.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var base64String = CryptoJS.enc.Base64.stringify(wordArray);
	         */
	        stringify: function (wordArray) {
	            // Shortcuts
	            var words = wordArray.words;
	            var sigBytes = wordArray.sigBytes;
	            var map = this._map;

	            // Clamp excess bits
	            wordArray.clamp();

	            // Convert
	            var base64Chars = [];
	            for (var i = 0; i < sigBytes; i += 3) {
	                var byte1 = (words[i >>> 2]       >>> (24 - (i % 4) * 8))       & 0xff;
	                var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
	                var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;

	                var triplet = (byte1 << 16) | (byte2 << 8) | byte3;

	                for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) {
	                    base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
	                }
	            }

	            // Add padding
	            var paddingChar = map.charAt(64);
	            if (paddingChar) {
	                while (base64Chars.length % 4) {
	                    base64Chars.push(paddingChar);
	                }
	            }

	            return base64Chars.join('');
	        },

	        /**
	         * Converts a Base64 string to a word array.
	         *
	         * @param {string} base64Str The Base64 string.
	         *
	         * @return {WordArray} The word array.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var wordArray = CryptoJS.enc.Base64.parse(base64String);
	         */
	        parse: function (base64Str) {
	            // Shortcuts
	            var base64StrLength = base64Str.length;
	            var map = this._map;
	            var reverseMap = this._reverseMap;

	            if (!reverseMap) {
	                    reverseMap = this._reverseMap = [];
	                    for (var j = 0; j < map.length; j++) {
	                        reverseMap[map.charCodeAt(j)] = j;
	                    }
	            }

	            // Ignore padding
	            var paddingChar = map.charAt(64);
	            if (paddingChar) {
	                var paddingIndex = base64Str.indexOf(paddingChar);
	                if (paddingIndex !== -1) {
	                    base64StrLength = paddingIndex;
	                }
	            }

	            // Convert
	            return parseLoop(base64Str, base64StrLength, reverseMap);

	        },

	        _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
	    };

	    function parseLoop(base64Str, base64StrLength, reverseMap) {
	      var words = [];
	      var nBytes = 0;
	      for (var i = 0; i < base64StrLength; i++) {
	          if (i % 4) {
	              var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2);
	              var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2);
	              var bitsCombined = bits1 | bits2;
	              words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8);
	              nBytes++;
	          }
	      }
	      return WordArray.create(words, nBytes);
	    }
	}());


	return CryptoJS.enc.Base64;

}));

/***/ }),

/***/ "./node_modules/crypto-js/enc-base64url.js":
/*!*************************************************!*\
  !*** ./node_modules/crypto-js/enc-base64url.js ***!
  \*************************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var WordArray = C_lib.WordArray;
	    var C_enc = C.enc;

	    /**
	     * Base64url encoding strategy.
	     */
	    var Base64url = C_enc.Base64url = {
	        /**
	         * Converts a word array to a Base64url string.
	         *
	         * @param {WordArray} wordArray The word array.
	         *
	         * @param {boolean} urlSafe Whether to use url safe
	         *
	         * @return {string} The Base64url string.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var base64String = CryptoJS.enc.Base64url.stringify(wordArray);
	         */
	        stringify: function (wordArray, urlSafe) {
	            if (urlSafe === undefined) {
	                urlSafe = true
	            }
	            // Shortcuts
	            var words = wordArray.words;
	            var sigBytes = wordArray.sigBytes;
	            var map = urlSafe ? this._safe_map : this._map;

	            // Clamp excess bits
	            wordArray.clamp();

	            // Convert
	            var base64Chars = [];
	            for (var i = 0; i < sigBytes; i += 3) {
	                var byte1 = (words[i >>> 2]       >>> (24 - (i % 4) * 8))       & 0xff;
	                var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
	                var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;

	                var triplet = (byte1 << 16) | (byte2 << 8) | byte3;

	                for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) {
	                    base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
	                }
	            }

	            // Add padding
	            var paddingChar = map.charAt(64);
	            if (paddingChar) {
	                while (base64Chars.length % 4) {
	                    base64Chars.push(paddingChar);
	                }
	            }

	            return base64Chars.join('');
	        },

	        /**
	         * Converts a Base64url string to a word array.
	         *
	         * @param {string} base64Str The Base64url string.
	         *
	         * @param {boolean} urlSafe Whether to use url safe
	         *
	         * @return {WordArray} The word array.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var wordArray = CryptoJS.enc.Base64url.parse(base64String);
	         */
	        parse: function (base64Str, urlSafe) {
	            if (urlSafe === undefined) {
	                urlSafe = true
	            }

	            // Shortcuts
	            var base64StrLength = base64Str.length;
	            var map = urlSafe ? this._safe_map : this._map;
	            var reverseMap = this._reverseMap;

	            if (!reverseMap) {
	                reverseMap = this._reverseMap = [];
	                for (var j = 0; j < map.length; j++) {
	                    reverseMap[map.charCodeAt(j)] = j;
	                }
	            }

	            // Ignore padding
	            var paddingChar = map.charAt(64);
	            if (paddingChar) {
	                var paddingIndex = base64Str.indexOf(paddingChar);
	                if (paddingIndex !== -1) {
	                    base64StrLength = paddingIndex;
	                }
	            }

	            // Convert
	            return parseLoop(base64Str, base64StrLength, reverseMap);

	        },

	        _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
	        _safe_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
	    };

	    function parseLoop(base64Str, base64StrLength, reverseMap) {
	        var words = [];
	        var nBytes = 0;
	        for (var i = 0; i < base64StrLength; i++) {
	            if (i % 4) {
	                var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2);
	                var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2);
	                var bitsCombined = bits1 | bits2;
	                words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8);
	                nBytes++;
	            }
	        }
	        return WordArray.create(words, nBytes);
	    }
	}());


	return CryptoJS.enc.Base64url;

}));

/***/ }),

/***/ "./node_modules/crypto-js/enc-utf16.js":
/*!*********************************************!*\
  !*** ./node_modules/crypto-js/enc-utf16.js ***!
  \*********************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var WordArray = C_lib.WordArray;
	    var C_enc = C.enc;

	    /**
	     * UTF-16 BE encoding strategy.
	     */
	    var Utf16BE = C_enc.Utf16 = C_enc.Utf16BE = {
	        /**
	         * Converts a word array to a UTF-16 BE string.
	         *
	         * @param {WordArray} wordArray The word array.
	         *
	         * @return {string} The UTF-16 BE string.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var utf16String = CryptoJS.enc.Utf16.stringify(wordArray);
	         */
	        stringify: function (wordArray) {
	            // Shortcuts
	            var words = wordArray.words;
	            var sigBytes = wordArray.sigBytes;

	            // Convert
	            var utf16Chars = [];
	            for (var i = 0; i < sigBytes; i += 2) {
	                var codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff;
	                utf16Chars.push(String.fromCharCode(codePoint));
	            }

	            return utf16Chars.join('');
	        },

	        /**
	         * Converts a UTF-16 BE string to a word array.
	         *
	         * @param {string} utf16Str The UTF-16 BE string.
	         *
	         * @return {WordArray} The word array.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var wordArray = CryptoJS.enc.Utf16.parse(utf16String);
	         */
	        parse: function (utf16Str) {
	            // Shortcut
	            var utf16StrLength = utf16Str.length;

	            // Convert
	            var words = [];
	            for (var i = 0; i < utf16StrLength; i++) {
	                words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16);
	            }

	            return WordArray.create(words, utf16StrLength * 2);
	        }
	    };

	    /**
	     * UTF-16 LE encoding strategy.
	     */
	    C_enc.Utf16LE = {
	        /**
	         * Converts a word array to a UTF-16 LE string.
	         *
	         * @param {WordArray} wordArray The word array.
	         *
	         * @return {string} The UTF-16 LE string.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray);
	         */
	        stringify: function (wordArray) {
	            // Shortcuts
	            var words = wordArray.words;
	            var sigBytes = wordArray.sigBytes;

	            // Convert
	            var utf16Chars = [];
	            for (var i = 0; i < sigBytes; i += 2) {
	                var codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff);
	                utf16Chars.push(String.fromCharCode(codePoint));
	            }

	            return utf16Chars.join('');
	        },

	        /**
	         * Converts a UTF-16 LE string to a word array.
	         *
	         * @param {string} utf16Str The UTF-16 LE string.
	         *
	         * @return {WordArray} The word array.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str);
	         */
	        parse: function (utf16Str) {
	            // Shortcut
	            var utf16StrLength = utf16Str.length;

	            // Convert
	            var words = [];
	            for (var i = 0; i < utf16StrLength; i++) {
	                words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16));
	            }

	            return WordArray.create(words, utf16StrLength * 2);
	        }
	    };

	    function swapEndian(word) {
	        return ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff);
	    }
	}());


	return CryptoJS.enc.Utf16;

}));

/***/ }),

/***/ "./node_modules/crypto-js/evpkdf.js":
/*!******************************************!*\
  !*** ./node_modules/crypto-js/evpkdf.js ***!
  \******************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./sha1 */ "./node_modules/crypto-js/sha1.js"), __webpack_require__(/*! ./hmac */ "./node_modules/crypto-js/hmac.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var Base = C_lib.Base;
	    var WordArray = C_lib.WordArray;
	    var C_algo = C.algo;
	    var MD5 = C_algo.MD5;

	    /**
	     * This key derivation function is meant to conform with EVP_BytesToKey.
	     * www.openssl.org/docs/crypto/EVP_BytesToKey.html
	     */
	    var EvpKDF = C_algo.EvpKDF = Base.extend({
	        /**
	         * Configuration options.
	         *
	         * @property {number} keySize The key size in words to generate. Default: 4 (128 bits)
	         * @property {Hasher} hasher The hash algorithm to use. Default: MD5
	         * @property {number} iterations The number of iterations to perform. Default: 1
	         */
	        cfg: Base.extend({
	            keySize: 128/32,
	            hasher: MD5,
	            iterations: 1
	        }),

	        /**
	         * Initializes a newly created key derivation function.
	         *
	         * @param {Object} cfg (Optional) The configuration options to use for the derivation.
	         *
	         * @example
	         *
	         *     var kdf = CryptoJS.algo.EvpKDF.create();
	         *     var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 });
	         *     var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 });
	         */
	        init: function (cfg) {
	            this.cfg = this.cfg.extend(cfg);
	        },

	        /**
	         * Derives a key from a password.
	         *
	         * @param {WordArray|string} password The password.
	         * @param {WordArray|string} salt A salt.
	         *
	         * @return {WordArray} The derived key.
	         *
	         * @example
	         *
	         *     var key = kdf.compute(password, salt);
	         */
	        compute: function (password, salt) {
	            var block;

	            // Shortcut
	            var cfg = this.cfg;

	            // Init hasher
	            var hasher = cfg.hasher.create();

	            // Initial values
	            var derivedKey = WordArray.create();

	            // Shortcuts
	            var derivedKeyWords = derivedKey.words;
	            var keySize = cfg.keySize;
	            var iterations = cfg.iterations;

	            // Generate key
	            while (derivedKeyWords.length < keySize) {
	                if (block) {
	                    hasher.update(block);
	                }
	                block = hasher.update(password).finalize(salt);
	                hasher.reset();

	                // Iterations
	                for (var i = 1; i < iterations; i++) {
	                    block = hasher.finalize(block);
	                    hasher.reset();
	                }

	                derivedKey.concat(block);
	            }
	            derivedKey.sigBytes = keySize * 4;

	            return derivedKey;
	        }
	    });

	    /**
	     * Derives a key from a password.
	     *
	     * @param {WordArray|string} password The password.
	     * @param {WordArray|string} salt A salt.
	     * @param {Object} cfg (Optional) The configuration options to use for this computation.
	     *
	     * @return {WordArray} The derived key.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var key = CryptoJS.EvpKDF(password, salt);
	     *     var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 });
	     *     var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 });
	     */
	    C.EvpKDF = function (password, salt, cfg) {
	        return EvpKDF.create(cfg).compute(password, salt);
	    };
	}());


	return CryptoJS.EvpKDF;

}));

/***/ }),

/***/ "./node_modules/crypto-js/format-hex.js":
/*!**********************************************!*\
  !*** ./node_modules/crypto-js/format-hex.js ***!
  \**********************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function (undefined) {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var CipherParams = C_lib.CipherParams;
	    var C_enc = C.enc;
	    var Hex = C_enc.Hex;
	    var C_format = C.format;

	    var HexFormatter = C_format.Hex = {
	        /**
	         * Converts the ciphertext of a cipher params object to a hexadecimally encoded string.
	         *
	         * @param {CipherParams} cipherParams The cipher params object.
	         *
	         * @return {string} The hexadecimally encoded string.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var hexString = CryptoJS.format.Hex.stringify(cipherParams);
	         */
	        stringify: function (cipherParams) {
	            return cipherParams.ciphertext.toString(Hex);
	        },

	        /**
	         * Converts a hexadecimally encoded ciphertext string to a cipher params object.
	         *
	         * @param {string} input The hexadecimally encoded string.
	         *
	         * @return {CipherParams} The cipher params object.
	         *
	         * @static
	         *
	         * @example
	         *
	         *     var cipherParams = CryptoJS.format.Hex.parse(hexString);
	         */
	        parse: function (input) {
	            var ciphertext = Hex.parse(input);
	            return CipherParams.create({ ciphertext: ciphertext });
	        }
	    };
	}());


	return CryptoJS.format.Hex;

}));

/***/ }),

/***/ "./node_modules/crypto-js/hmac.js":
/*!****************************************!*\
  !*** ./node_modules/crypto-js/hmac.js ***!
  \****************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var Base = C_lib.Base;
	    var C_enc = C.enc;
	    var Utf8 = C_enc.Utf8;
	    var C_algo = C.algo;

	    /**
	     * HMAC algorithm.
	     */
	    var HMAC = C_algo.HMAC = Base.extend({
	        /**
	         * Initializes a newly created HMAC.
	         *
	         * @param {Hasher} hasher The hash algorithm to use.
	         * @param {WordArray|string} key The secret key.
	         *
	         * @example
	         *
	         *     var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
	         */
	        init: function (hasher, key) {
	            // Init hasher
	            hasher = this._hasher = new hasher.init();

	            // Convert string to WordArray, else assume WordArray already
	            if (typeof key == 'string') {
	                key = Utf8.parse(key);
	            }

	            // Shortcuts
	            var hasherBlockSize = hasher.blockSize;
	            var hasherBlockSizeBytes = hasherBlockSize * 4;

	            // Allow arbitrary length keys
	            if (key.sigBytes > hasherBlockSizeBytes) {
	                key = hasher.finalize(key);
	            }

	            // Clamp excess bits
	            key.clamp();

	            // Clone key for inner and outer pads
	            var oKey = this._oKey = key.clone();
	            var iKey = this._iKey = key.clone();

	            // Shortcuts
	            var oKeyWords = oKey.words;
	            var iKeyWords = iKey.words;

	            // XOR keys with pad constants
	            for (var i = 0; i < hasherBlockSize; i++) {
	                oKeyWords[i] ^= 0x5c5c5c5c;
	                iKeyWords[i] ^= 0x36363636;
	            }
	            oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes;

	            // Set initial values
	            this.reset();
	        },

	        /**
	         * Resets this HMAC to its initial state.
	         *
	         * @example
	         *
	         *     hmacHasher.reset();
	         */
	        reset: function () {
	            // Shortcut
	            var hasher = this._hasher;

	            // Reset
	            hasher.reset();
	            hasher.update(this._iKey);
	        },

	        /**
	         * Updates this HMAC with a message.
	         *
	         * @param {WordArray|string} messageUpdate The message to append.
	         *
	         * @return {HMAC} This HMAC instance.
	         *
	         * @example
	         *
	         *     hmacHasher.update('message');
	         *     hmacHasher.update(wordArray);
	         */
	        update: function (messageUpdate) {
	            this._hasher.update(messageUpdate);

	            // Chainable
	            return this;
	        },

	        /**
	         * Finalizes the HMAC computation.
	         * Note that the finalize operation is effectively a destructive, read-once operation.
	         *
	         * @param {WordArray|string} messageUpdate (Optional) A final message update.
	         *
	         * @return {WordArray} The HMAC.
	         *
	         * @example
	         *
	         *     var hmac = hmacHasher.finalize();
	         *     var hmac = hmacHasher.finalize('message');
	         *     var hmac = hmacHasher.finalize(wordArray);
	         */
	        finalize: function (messageUpdate) {
	            // Shortcut
	            var hasher = this._hasher;

	            // Compute HMAC
	            var innerHash = hasher.finalize(messageUpdate);
	            hasher.reset();
	            var hmac = hasher.finalize(this._oKey.clone().concat(innerHash));

	            return hmac;
	        }
	    });
	}());


}));

/***/ }),

/***/ "./node_modules/crypto-js/index.js":
/*!*****************************************!*\
  !*** ./node_modules/crypto-js/index.js ***!
  \*****************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./x64-core */ "./node_modules/crypto-js/x64-core.js"), __webpack_require__(/*! ./lib-typedarrays */ "./node_modules/crypto-js/lib-typedarrays.js"), __webpack_require__(/*! ./enc-utf16 */ "./node_modules/crypto-js/enc-utf16.js"), __webpack_require__(/*! ./enc-base64 */ "./node_modules/crypto-js/enc-base64.js"), __webpack_require__(/*! ./enc-base64url */ "./node_modules/crypto-js/enc-base64url.js"), __webpack_require__(/*! ./md5 */ "./node_modules/crypto-js/md5.js"), __webpack_require__(/*! ./sha1 */ "./node_modules/crypto-js/sha1.js"), __webpack_require__(/*! ./sha256 */ "./node_modules/crypto-js/sha256.js"), __webpack_require__(/*! ./sha224 */ "./node_modules/crypto-js/sha224.js"), __webpack_require__(/*! ./sha512 */ "./node_modules/crypto-js/sha512.js"), __webpack_require__(/*! ./sha384 */ "./node_modules/crypto-js/sha384.js"), __webpack_require__(/*! ./sha3 */ "./node_modules/crypto-js/sha3.js"), __webpack_require__(/*! ./ripemd160 */ "./node_modules/crypto-js/ripemd160.js"), __webpack_require__(/*! ./hmac */ "./node_modules/crypto-js/hmac.js"), __webpack_require__(/*! ./pbkdf2 */ "./node_modules/crypto-js/pbkdf2.js"), __webpack_require__(/*! ./evpkdf */ "./node_modules/crypto-js/evpkdf.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"), __webpack_require__(/*! ./mode-cfb */ "./node_modules/crypto-js/mode-cfb.js"), __webpack_require__(/*! ./mode-ctr */ "./node_modules/crypto-js/mode-ctr.js"), __webpack_require__(/*! ./mode-ctr-gladman */ "./node_modules/crypto-js/mode-ctr-gladman.js"), __webpack_require__(/*! ./mode-ofb */ "./node_modules/crypto-js/mode-ofb.js"), __webpack_require__(/*! ./mode-ecb */ "./node_modules/crypto-js/mode-ecb.js"), __webpack_require__(/*! ./pad-ansix923 */ "./node_modules/crypto-js/pad-ansix923.js"), __webpack_require__(/*! ./pad-iso10126 */ "./node_modules/crypto-js/pad-iso10126.js"), __webpack_require__(/*! ./pad-iso97971 */ "./node_modules/crypto-js/pad-iso97971.js"), __webpack_require__(/*! ./pad-zeropadding */ "./node_modules/crypto-js/pad-zeropadding.js"), __webpack_require__(/*! ./pad-nopadding */ "./node_modules/crypto-js/pad-nopadding.js"), __webpack_require__(/*! ./format-hex */ "./node_modules/crypto-js/format-hex.js"), __webpack_require__(/*! ./aes */ "./node_modules/crypto-js/aes.js"), __webpack_require__(/*! ./tripledes */ "./node_modules/crypto-js/tripledes.js"), __webpack_require__(/*! ./rc4 */ "./node_modules/crypto-js/rc4.js"), __webpack_require__(/*! ./rabbit */ "./node_modules/crypto-js/rabbit.js"), __webpack_require__(/*! ./rabbit-legacy */ "./node_modules/crypto-js/rabbit-legacy.js"), __webpack_require__(/*! ./blowfish */ "./node_modules/crypto-js/blowfish.js"));
	}
	else {}
}(this, function (CryptoJS) {

	return CryptoJS;

}));

/***/ }),

/***/ "./node_modules/crypto-js/lib-typedarrays.js":
/*!***************************************************!*\
  !*** ./node_modules/crypto-js/lib-typedarrays.js ***!
  \***************************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Check if typed arrays are supported
	    if (typeof ArrayBuffer != 'function') {
	        return;
	    }

	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var WordArray = C_lib.WordArray;

	    // Reference original init
	    var superInit = WordArray.init;

	    // Augment WordArray.init to handle typed arrays
	    var subInit = WordArray.init = function (typedArray) {
	        // Convert buffers to uint8
	        if (typedArray instanceof ArrayBuffer) {
	            typedArray = new Uint8Array(typedArray);
	        }

	        // Convert other array views to uint8
	        if (
	            typedArray instanceof Int8Array ||
	            (typeof Uint8ClampedArray !== "undefined" && typedArray instanceof Uint8ClampedArray) ||
	            typedArray instanceof Int16Array ||
	            typedArray instanceof Uint16Array ||
	            typedArray instanceof Int32Array ||
	            typedArray instanceof Uint32Array ||
	            typedArray instanceof Float32Array ||
	            typedArray instanceof Float64Array
	        ) {
	            typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);
	        }

	        // Handle Uint8Array
	        if (typedArray instanceof Uint8Array) {
	            // Shortcut
	            var typedArrayByteLength = typedArray.byteLength;

	            // Extract bytes
	            var words = [];
	            for (var i = 0; i < typedArrayByteLength; i++) {
	                words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8);
	            }

	            // Initialize this word array
	            superInit.call(this, words, typedArrayByteLength);
	        } else {
	            // Else call normal init
	            superInit.apply(this, arguments);
	        }
	    };

	    subInit.prototype = WordArray;
	}());


	return CryptoJS.lib.WordArray;

}));

/***/ }),

/***/ "./node_modules/crypto-js/md5.js":
/*!***************************************!*\
  !*** ./node_modules/crypto-js/md5.js ***!
  \***************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function (Math) {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var WordArray = C_lib.WordArray;
	    var Hasher = C_lib.Hasher;
	    var C_algo = C.algo;

	    // Constants table
	    var T = [];

	    // Compute constants
	    (function () {
	        for (var i = 0; i < 64; i++) {
	            T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0;
	        }
	    }());

	    /**
	     * MD5 hash algorithm.
	     */
	    var MD5 = C_algo.MD5 = Hasher.extend({
	        _doReset: function () {
	            this._hash = new WordArray.init([
	                0x67452301, 0xefcdab89,
	                0x98badcfe, 0x10325476
	            ]);
	        },

	        _doProcessBlock: function (M, offset) {
	            // Swap endian
	            for (var i = 0; i < 16; i++) {
	                // Shortcuts
	                var offset_i = offset + i;
	                var M_offset_i = M[offset_i];

	                M[offset_i] = (
	                    (((M_offset_i << 8)  | (M_offset_i >>> 24)) & 0x00ff00ff) |
	                    (((M_offset_i << 24) | (M_offset_i >>> 8))  & 0xff00ff00)
	                );
	            }

	            // Shortcuts
	            var H = this._hash.words;

	            var M_offset_0  = M[offset + 0];
	            var M_offset_1  = M[offset + 1];
	            var M_offset_2  = M[offset + 2];
	            var M_offset_3  = M[offset + 3];
	            var M_offset_4  = M[offset + 4];
	            var M_offset_5  = M[offset + 5];
	            var M_offset_6  = M[offset + 6];
	            var M_offset_7  = M[offset + 7];
	            var M_offset_8  = M[offset + 8];
	            var M_offset_9  = M[offset + 9];
	            var M_offset_10 = M[offset + 10];
	            var M_offset_11 = M[offset + 11];
	            var M_offset_12 = M[offset + 12];
	            var M_offset_13 = M[offset + 13];
	            var M_offset_14 = M[offset + 14];
	            var M_offset_15 = M[offset + 15];

	            // Working variables
	            var a = H[0];
	            var b = H[1];
	            var c = H[2];
	            var d = H[3];

	            // Computation
	            a = FF(a, b, c, d, M_offset_0,  7,  T[0]);
	            d = FF(d, a, b, c, M_offset_1,  12, T[1]);
	            c = FF(c, d, a, b, M_offset_2,  17, T[2]);
	            b = FF(b, c, d, a, M_offset_3,  22, T[3]);
	            a = FF(a, b, c, d, M_offset_4,  7,  T[4]);
	            d = FF(d, a, b, c, M_offset_5,  12, T[5]);
	            c = FF(c, d, a, b, M_offset_6,  17, T[6]);
	            b = FF(b, c, d, a, M_offset_7,  22, T[7]);
	            a = FF(a, b, c, d, M_offset_8,  7,  T[8]);
	            d = FF(d, a, b, c, M_offset_9,  12, T[9]);
	            c = FF(c, d, a, b, M_offset_10, 17, T[10]);
	            b = FF(b, c, d, a, M_offset_11, 22, T[11]);
	            a = FF(a, b, c, d, M_offset_12, 7,  T[12]);
	            d = FF(d, a, b, c, M_offset_13, 12, T[13]);
	            c = FF(c, d, a, b, M_offset_14, 17, T[14]);
	            b = FF(b, c, d, a, M_offset_15, 22, T[15]);

	            a = GG(a, b, c, d, M_offset_1,  5,  T[16]);
	            d = GG(d, a, b, c, M_offset_6,  9,  T[17]);
	            c = GG(c, d, a, b, M_offset_11, 14, T[18]);
	            b = GG(b, c, d, a, M_offset_0,  20, T[19]);
	            a = GG(a, b, c, d, M_offset_5,  5,  T[20]);
	            d = GG(d, a, b, c, M_offset_10, 9,  T[21]);
	            c = GG(c, d, a, b, M_offset_15, 14, T[22]);
	            b = GG(b, c, d, a, M_offset_4,  20, T[23]);
	            a = GG(a, b, c, d, M_offset_9,  5,  T[24]);
	            d = GG(d, a, b, c, M_offset_14, 9,  T[25]);
	            c = GG(c, d, a, b, M_offset_3,  14, T[26]);
	            b = GG(b, c, d, a, M_offset_8,  20, T[27]);
	            a = GG(a, b, c, d, M_offset_13, 5,  T[28]);
	            d = GG(d, a, b, c, M_offset_2,  9,  T[29]);
	            c = GG(c, d, a, b, M_offset_7,  14, T[30]);
	            b = GG(b, c, d, a, M_offset_12, 20, T[31]);

	            a = HH(a, b, c, d, M_offset_5,  4,  T[32]);
	            d = HH(d, a, b, c, M_offset_8,  11, T[33]);
	            c = HH(c, d, a, b, M_offset_11, 16, T[34]);
	            b = HH(b, c, d, a, M_offset_14, 23, T[35]);
	            a = HH(a, b, c, d, M_offset_1,  4,  T[36]);
	            d = HH(d, a, b, c, M_offset_4,  11, T[37]);
	            c = HH(c, d, a, b, M_offset_7,  16, T[38]);
	            b = HH(b, c, d, a, M_offset_10, 23, T[39]);
	            a = HH(a, b, c, d, M_offset_13, 4,  T[40]);
	            d = HH(d, a, b, c, M_offset_0,  11, T[41]);
	            c = HH(c, d, a, b, M_offset_3,  16, T[42]);
	            b = HH(b, c, d, a, M_offset_6,  23, T[43]);
	            a = HH(a, b, c, d, M_offset_9,  4,  T[44]);
	            d = HH(d, a, b, c, M_offset_12, 11, T[45]);
	            c = HH(c, d, a, b, M_offset_15, 16, T[46]);
	            b = HH(b, c, d, a, M_offset_2,  23, T[47]);

	            a = II(a, b, c, d, M_offset_0,  6,  T[48]);
	            d = II(d, a, b, c, M_offset_7,  10, T[49]);
	            c = II(c, d, a, b, M_offset_14, 15, T[50]);
	            b = II(b, c, d, a, M_offset_5,  21, T[51]);
	            a = II(a, b, c, d, M_offset_12, 6,  T[52]);
	            d = II(d, a, b, c, M_offset_3,  10, T[53]);
	            c = II(c, d, a, b, M_offset_10, 15, T[54]);
	            b = II(b, c, d, a, M_offset_1,  21, T[55]);
	            a = II(a, b, c, d, M_offset_8,  6,  T[56]);
	            d = II(d, a, b, c, M_offset_15, 10, T[57]);
	            c = II(c, d, a, b, M_offset_6,  15, T[58]);
	            b = II(b, c, d, a, M_offset_13, 21, T[59]);
	            a = II(a, b, c, d, M_offset_4,  6,  T[60]);
	            d = II(d, a, b, c, M_offset_11, 10, T[61]);
	            c = II(c, d, a, b, M_offset_2,  15, T[62]);
	            b = II(b, c, d, a, M_offset_9,  21, T[63]);

	            // Intermediate hash value
	            H[0] = (H[0] + a) | 0;
	            H[1] = (H[1] + b) | 0;
	            H[2] = (H[2] + c) | 0;
	            H[3] = (H[3] + d) | 0;
	        },

	        _doFinalize: function () {
	            // Shortcuts
	            var data = this._data;
	            var dataWords = data.words;

	            var nBitsTotal = this._nDataBytes * 8;
	            var nBitsLeft = data.sigBytes * 8;

	            // Add padding
	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);

	            var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000);
	            var nBitsTotalL = nBitsTotal;
	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = (
	                (((nBitsTotalH << 8)  | (nBitsTotalH >>> 24)) & 0x00ff00ff) |
	                (((nBitsTotalH << 24) | (nBitsTotalH >>> 8))  & 0xff00ff00)
	            );
	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
	                (((nBitsTotalL << 8)  | (nBitsTotalL >>> 24)) & 0x00ff00ff) |
	                (((nBitsTotalL << 24) | (nBitsTotalL >>> 8))  & 0xff00ff00)
	            );

	            data.sigBytes = (dataWords.length + 1) * 4;

	            // Hash final blocks
	            this._process();

	            // Shortcuts
	            var hash = this._hash;
	            var H = hash.words;

	            // Swap endian
	            for (var i = 0; i < 4; i++) {
	                // Shortcut
	                var H_i = H[i];

	                H[i] = (((H_i << 8)  | (H_i >>> 24)) & 0x00ff00ff) |
	                       (((H_i << 24) | (H_i >>> 8))  & 0xff00ff00);
	            }

	            // Return final computed hash
	            return hash;
	        },

	        clone: function () {
	            var clone = Hasher.clone.call(this);
	            clone._hash = this._hash.clone();

	            return clone;
	        }
	    });

	    function FF(a, b, c, d, x, s, t) {
	        var n = a + ((b & c) | (~b & d)) + x + t;
	        return ((n << s) | (n >>> (32 - s))) + b;
	    }

	    function GG(a, b, c, d, x, s, t) {
	        var n = a + ((b & d) | (c & ~d)) + x + t;
	        return ((n << s) | (n >>> (32 - s))) + b;
	    }

	    function HH(a, b, c, d, x, s, t) {
	        var n = a + (b ^ c ^ d) + x + t;
	        return ((n << s) | (n >>> (32 - s))) + b;
	    }

	    function II(a, b, c, d, x, s, t) {
	        var n = a + (c ^ (b | ~d)) + x + t;
	        return ((n << s) | (n >>> (32 - s))) + b;
	    }

	    /**
	     * Shortcut function to the hasher's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     *
	     * @return {WordArray} The hash.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hash = CryptoJS.MD5('message');
	     *     var hash = CryptoJS.MD5(wordArray);
	     */
	    C.MD5 = Hasher._createHelper(MD5);

	    /**
	     * Shortcut function to the HMAC's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     * @param {WordArray|string} key The secret key.
	     *
	     * @return {WordArray} The HMAC.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hmac = CryptoJS.HmacMD5(message, key);
	     */
	    C.HmacMD5 = Hasher._createHmacHelper(MD5);
	}(Math));


	return CryptoJS.MD5;

}));

/***/ }),

/***/ "./node_modules/crypto-js/mode-cfb.js":
/*!********************************************!*\
  !*** ./node_modules/crypto-js/mode-cfb.js ***!
  \********************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	/**
	 * Cipher Feedback block mode.
	 */
	CryptoJS.mode.CFB = (function () {
	    var CFB = CryptoJS.lib.BlockCipherMode.extend();

	    CFB.Encryptor = CFB.extend({
	        processBlock: function (words, offset) {
	            // Shortcuts
	            var cipher = this._cipher;
	            var blockSize = cipher.blockSize;

	            generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher);

	            // Remember this block to use with next block
	            this._prevBlock = words.slice(offset, offset + blockSize);
	        }
	    });

	    CFB.Decryptor = CFB.extend({
	        processBlock: function (words, offset) {
	            // Shortcuts
	            var cipher = this._cipher;
	            var blockSize = cipher.blockSize;

	            // Remember this block to use with next block
	            var thisBlock = words.slice(offset, offset + blockSize);

	            generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher);

	            // This block becomes the previous block
	            this._prevBlock = thisBlock;
	        }
	    });

	    function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) {
	        var keystream;

	        // Shortcut
	        var iv = this._iv;

	        // Generate keystream
	        if (iv) {
	            keystream = iv.slice(0);

	            // Remove IV for subsequent blocks
	            this._iv = undefined;
	        } else {
	            keystream = this._prevBlock;
	        }
	        cipher.encryptBlock(keystream, 0);

	        // Encrypt
	        for (var i = 0; i < blockSize; i++) {
	            words[offset + i] ^= keystream[i];
	        }
	    }

	    return CFB;
	}());


	return CryptoJS.mode.CFB;

}));

/***/ }),

/***/ "./node_modules/crypto-js/mode-ctr-gladman.js":
/*!****************************************************!*\
  !*** ./node_modules/crypto-js/mode-ctr-gladman.js ***!
  \****************************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	/** @preserve
	 * Counter block mode compatible with  Dr Brian Gladman fileenc.c
	 * derived from CryptoJS.mode.CTR
	 * Jan Hruby jhruby.web@gmail.com
	 */
	CryptoJS.mode.CTRGladman = (function () {
	    var CTRGladman = CryptoJS.lib.BlockCipherMode.extend();

		function incWord(word)
		{
			if (((word >> 24) & 0xff) === 0xff) { //overflow
			var b1 = (word >> 16)&0xff;
			var b2 = (word >> 8)&0xff;
			var b3 = word & 0xff;

			if (b1 === 0xff) // overflow b1
			{
			b1 = 0;
			if (b2 === 0xff)
			{
				b2 = 0;
				if (b3 === 0xff)
				{
					b3 = 0;
				}
				else
				{
					++b3;
				}
			}
			else
			{
				++b2;
			}
			}
			else
			{
			++b1;
			}

			word = 0;
			word += (b1 << 16);
			word += (b2 << 8);
			word += b3;
			}
			else
			{
			word += (0x01 << 24);
			}
			return word;
		}

		function incCounter(counter)
		{
			if ((counter[0] = incWord(counter[0])) === 0)
			{
				// encr_data in fileenc.c from  Dr Brian Gladman's counts only with DWORD j < 8
				counter[1] = incWord(counter[1]);
			}
			return counter;
		}

	    var Encryptor = CTRGladman.Encryptor = CTRGladman.extend({
	        processBlock: function (words, offset) {
	            // Shortcuts
	            var cipher = this._cipher
	            var blockSize = cipher.blockSize;
	            var iv = this._iv;
	            var counter = this._counter;

	            // Generate keystream
	            if (iv) {
	                counter = this._counter = iv.slice(0);

	                // Remove IV for subsequent blocks
	                this._iv = undefined;
	            }

				incCounter(counter);

				var keystream = counter.slice(0);
	            cipher.encryptBlock(keystream, 0);

	            // Encrypt
	            for (var i = 0; i < blockSize; i++) {
	                words[offset + i] ^= keystream[i];
	            }
	        }
	    });

	    CTRGladman.Decryptor = Encryptor;

	    return CTRGladman;
	}());




	return CryptoJS.mode.CTRGladman;

}));

/***/ }),

/***/ "./node_modules/crypto-js/mode-ctr.js":
/*!********************************************!*\
  !*** ./node_modules/crypto-js/mode-ctr.js ***!
  \********************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	/**
	 * Counter block mode.
	 */
	CryptoJS.mode.CTR = (function () {
	    var CTR = CryptoJS.lib.BlockCipherMode.extend();

	    var Encryptor = CTR.Encryptor = CTR.extend({
	        processBlock: function (words, offset) {
	            // Shortcuts
	            var cipher = this._cipher
	            var blockSize = cipher.blockSize;
	            var iv = this._iv;
	            var counter = this._counter;

	            // Generate keystream
	            if (iv) {
	                counter = this._counter = iv.slice(0);

	                // Remove IV for subsequent blocks
	                this._iv = undefined;
	            }
	            var keystream = counter.slice(0);
	            cipher.encryptBlock(keystream, 0);

	            // Increment counter
	            counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0

	            // Encrypt
	            for (var i = 0; i < blockSize; i++) {
	                words[offset + i] ^= keystream[i];
	            }
	        }
	    });

	    CTR.Decryptor = Encryptor;

	    return CTR;
	}());


	return CryptoJS.mode.CTR;

}));

/***/ }),

/***/ "./node_modules/crypto-js/mode-ecb.js":
/*!********************************************!*\
  !*** ./node_modules/crypto-js/mode-ecb.js ***!
  \********************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	/**
	 * Electronic Codebook block mode.
	 */
	CryptoJS.mode.ECB = (function () {
	    var ECB = CryptoJS.lib.BlockCipherMode.extend();

	    ECB.Encryptor = ECB.extend({
	        processBlock: function (words, offset) {
	            this._cipher.encryptBlock(words, offset);
	        }
	    });

	    ECB.Decryptor = ECB.extend({
	        processBlock: function (words, offset) {
	            this._cipher.decryptBlock(words, offset);
	        }
	    });

	    return ECB;
	}());


	return CryptoJS.mode.ECB;

}));

/***/ }),

/***/ "./node_modules/crypto-js/mode-ofb.js":
/*!********************************************!*\
  !*** ./node_modules/crypto-js/mode-ofb.js ***!
  \********************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	/**
	 * Output Feedback block mode.
	 */
	CryptoJS.mode.OFB = (function () {
	    var OFB = CryptoJS.lib.BlockCipherMode.extend();

	    var Encryptor = OFB.Encryptor = OFB.extend({
	        processBlock: function (words, offset) {
	            // Shortcuts
	            var cipher = this._cipher
	            var blockSize = cipher.blockSize;
	            var iv = this._iv;
	            var keystream = this._keystream;

	            // Generate keystream
	            if (iv) {
	                keystream = this._keystream = iv.slice(0);

	                // Remove IV for subsequent blocks
	                this._iv = undefined;
	            }
	            cipher.encryptBlock(keystream, 0);

	            // Encrypt
	            for (var i = 0; i < blockSize; i++) {
	                words[offset + i] ^= keystream[i];
	            }
	        }
	    });

	    OFB.Decryptor = Encryptor;

	    return OFB;
	}());


	return CryptoJS.mode.OFB;

}));

/***/ }),

/***/ "./node_modules/crypto-js/pad-ansix923.js":
/*!************************************************!*\
  !*** ./node_modules/crypto-js/pad-ansix923.js ***!
  \************************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	/**
	 * ANSI X.923 padding strategy.
	 */
	CryptoJS.pad.AnsiX923 = {
	    pad: function (data, blockSize) {
	        // Shortcuts
	        var dataSigBytes = data.sigBytes;
	        var blockSizeBytes = blockSize * 4;

	        // Count padding bytes
	        var nPaddingBytes = blockSizeBytes - dataSigBytes % blockSizeBytes;

	        // Compute last byte position
	        var lastBytePos = dataSigBytes + nPaddingBytes - 1;

	        // Pad
	        data.clamp();
	        data.words[lastBytePos >>> 2] |= nPaddingBytes << (24 - (lastBytePos % 4) * 8);
	        data.sigBytes += nPaddingBytes;
	    },

	    unpad: function (data) {
	        // Get number of padding bytes from last byte
	        var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;

	        // Remove padding
	        data.sigBytes -= nPaddingBytes;
	    }
	};


	return CryptoJS.pad.Ansix923;

}));

/***/ }),

/***/ "./node_modules/crypto-js/pad-iso10126.js":
/*!************************************************!*\
  !*** ./node_modules/crypto-js/pad-iso10126.js ***!
  \************************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	/**
	 * ISO 10126 padding strategy.
	 */
	CryptoJS.pad.Iso10126 = {
	    pad: function (data, blockSize) {
	        // Shortcut
	        var blockSizeBytes = blockSize * 4;

	        // Count padding bytes
	        var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes;

	        // Pad
	        data.concat(CryptoJS.lib.WordArray.random(nPaddingBytes - 1)).
	             concat(CryptoJS.lib.WordArray.create([nPaddingBytes << 24], 1));
	    },

	    unpad: function (data) {
	        // Get number of padding bytes from last byte
	        var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;

	        // Remove padding
	        data.sigBytes -= nPaddingBytes;
	    }
	};


	return CryptoJS.pad.Iso10126;

}));

/***/ }),

/***/ "./node_modules/crypto-js/pad-iso97971.js":
/*!************************************************!*\
  !*** ./node_modules/crypto-js/pad-iso97971.js ***!
  \************************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	/**
	 * ISO/IEC 9797-1 Padding Method 2.
	 */
	CryptoJS.pad.Iso97971 = {
	    pad: function (data, blockSize) {
	        // Add 0x80 byte
	        data.concat(CryptoJS.lib.WordArray.create([0x80000000], 1));

	        // Zero pad the rest
	        CryptoJS.pad.ZeroPadding.pad(data, blockSize);
	    },

	    unpad: function (data) {
	        // Remove zero padding
	        CryptoJS.pad.ZeroPadding.unpad(data);

	        // Remove one more byte -- the 0x80 byte
	        data.sigBytes--;
	    }
	};


	return CryptoJS.pad.Iso97971;

}));

/***/ }),

/***/ "./node_modules/crypto-js/pad-nopadding.js":
/*!*************************************************!*\
  !*** ./node_modules/crypto-js/pad-nopadding.js ***!
  \*************************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	/**
	 * A noop padding strategy.
	 */
	CryptoJS.pad.NoPadding = {
	    pad: function () {
	    },

	    unpad: function () {
	    }
	};


	return CryptoJS.pad.NoPadding;

}));

/***/ }),

/***/ "./node_modules/crypto-js/pad-zeropadding.js":
/*!***************************************************!*\
  !*** ./node_modules/crypto-js/pad-zeropadding.js ***!
  \***************************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	/**
	 * Zero padding strategy.
	 */
	CryptoJS.pad.ZeroPadding = {
	    pad: function (data, blockSize) {
	        // Shortcut
	        var blockSizeBytes = blockSize * 4;

	        // Pad
	        data.clamp();
	        data.sigBytes += blockSizeBytes - ((data.sigBytes % blockSizeBytes) || blockSizeBytes);
	    },

	    unpad: function (data) {
	        // Shortcut
	        var dataWords = data.words;

	        // Unpad
	        var i = data.sigBytes - 1;
	        for (var i = data.sigBytes - 1; i >= 0; i--) {
	            if (((dataWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff)) {
	                data.sigBytes = i + 1;
	                break;
	            }
	        }
	    }
	};


	return CryptoJS.pad.ZeroPadding;

}));

/***/ }),

/***/ "./node_modules/crypto-js/pbkdf2.js":
/*!******************************************!*\
  !*** ./node_modules/crypto-js/pbkdf2.js ***!
  \******************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./sha256 */ "./node_modules/crypto-js/sha256.js"), __webpack_require__(/*! ./hmac */ "./node_modules/crypto-js/hmac.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var Base = C_lib.Base;
	    var WordArray = C_lib.WordArray;
	    var C_algo = C.algo;
	    var SHA256 = C_algo.SHA256;
	    var HMAC = C_algo.HMAC;

	    /**
	     * Password-Based Key Derivation Function 2 algorithm.
	     */
	    var PBKDF2 = C_algo.PBKDF2 = Base.extend({
	        /**
	         * Configuration options.
	         *
	         * @property {number} keySize The key size in words to generate. Default: 4 (128 bits)
	         * @property {Hasher} hasher The hasher to use. Default: SHA256
	         * @property {number} iterations The number of iterations to perform. Default: 250000
	         */
	        cfg: Base.extend({
	            keySize: 128/32,
	            hasher: SHA256,
	            iterations: 250000
	        }),

	        /**
	         * Initializes a newly created key derivation function.
	         *
	         * @param {Object} cfg (Optional) The configuration options to use for the derivation.
	         *
	         * @example
	         *
	         *     var kdf = CryptoJS.algo.PBKDF2.create();
	         *     var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 });
	         *     var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 });
	         */
	        init: function (cfg) {
	            this.cfg = this.cfg.extend(cfg);
	        },

	        /**
	         * Computes the Password-Based Key Derivation Function 2.
	         *
	         * @param {WordArray|string} password The password.
	         * @param {WordArray|string} salt A salt.
	         *
	         * @return {WordArray} The derived key.
	         *
	         * @example
	         *
	         *     var key = kdf.compute(password, salt);
	         */
	        compute: function (password, salt) {
	            // Shortcut
	            var cfg = this.cfg;

	            // Init HMAC
	            var hmac = HMAC.create(cfg.hasher, password);

	            // Initial values
	            var derivedKey = WordArray.create();
	            var blockIndex = WordArray.create([0x00000001]);

	            // Shortcuts
	            var derivedKeyWords = derivedKey.words;
	            var blockIndexWords = blockIndex.words;
	            var keySize = cfg.keySize;
	            var iterations = cfg.iterations;

	            // Generate key
	            while (derivedKeyWords.length < keySize) {
	                var block = hmac.update(salt).finalize(blockIndex);
	                hmac.reset();

	                // Shortcuts
	                var blockWords = block.words;
	                var blockWordsLength = blockWords.length;

	                // Iterations
	                var intermediate = block;
	                for (var i = 1; i < iterations; i++) {
	                    intermediate = hmac.finalize(intermediate);
	                    hmac.reset();

	                    // Shortcut
	                    var intermediateWords = intermediate.words;

	                    // XOR intermediate with block
	                    for (var j = 0; j < blockWordsLength; j++) {
	                        blockWords[j] ^= intermediateWords[j];
	                    }
	                }

	                derivedKey.concat(block);
	                blockIndexWords[0]++;
	            }
	            derivedKey.sigBytes = keySize * 4;

	            return derivedKey;
	        }
	    });

	    /**
	     * Computes the Password-Based Key Derivation Function 2.
	     *
	     * @param {WordArray|string} password The password.
	     * @param {WordArray|string} salt A salt.
	     * @param {Object} cfg (Optional) The configuration options to use for this computation.
	     *
	     * @return {WordArray} The derived key.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var key = CryptoJS.PBKDF2(password, salt);
	     *     var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 });
	     *     var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 });
	     */
	    C.PBKDF2 = function (password, salt, cfg) {
	        return PBKDF2.create(cfg).compute(password, salt);
	    };
	}());


	return CryptoJS.PBKDF2;

}));

/***/ }),

/***/ "./node_modules/crypto-js/rabbit-legacy.js":
/*!*************************************************!*\
  !*** ./node_modules/crypto-js/rabbit-legacy.js ***!
  \*************************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./enc-base64 */ "./node_modules/crypto-js/enc-base64.js"), __webpack_require__(/*! ./md5 */ "./node_modules/crypto-js/md5.js"), __webpack_require__(/*! ./evpkdf */ "./node_modules/crypto-js/evpkdf.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var StreamCipher = C_lib.StreamCipher;
	    var C_algo = C.algo;

	    // Reusable objects
	    var S  = [];
	    var C_ = [];
	    var G  = [];

	    /**
	     * Rabbit stream cipher algorithm.
	     *
	     * This is a legacy version that neglected to convert the key to little-endian.
	     * This error doesn't affect the cipher's security,
	     * but it does affect its compatibility with other implementations.
	     */
	    var RabbitLegacy = C_algo.RabbitLegacy = StreamCipher.extend({
	        _doReset: function () {
	            // Shortcuts
	            var K = this._key.words;
	            var iv = this.cfg.iv;

	            // Generate initial state values
	            var X = this._X = [
	                K[0], (K[3] << 16) | (K[2] >>> 16),
	                K[1], (K[0] << 16) | (K[3] >>> 16),
	                K[2], (K[1] << 16) | (K[0] >>> 16),
	                K[3], (K[2] << 16) | (K[1] >>> 16)
	            ];

	            // Generate initial counter values
	            var C = this._C = [
	                (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff),
	                (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff),
	                (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff),
	                (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff)
	            ];

	            // Carry bit
	            this._b = 0;

	            // Iterate the system four times
	            for (var i = 0; i < 4; i++) {
	                nextState.call(this);
	            }

	            // Modify the counters
	            for (var i = 0; i < 8; i++) {
	                C[i] ^= X[(i + 4) & 7];
	            }

	            // IV setup
	            if (iv) {
	                // Shortcuts
	                var IV = iv.words;
	                var IV_0 = IV[0];
	                var IV_1 = IV[1];

	                // Generate four subvectors
	                var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00);
	                var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00);
	                var i1 = (i0 >>> 16) | (i2 & 0xffff0000);
	                var i3 = (i2 << 16)  | (i0 & 0x0000ffff);

	                // Modify counter values
	                C[0] ^= i0;
	                C[1] ^= i1;
	                C[2] ^= i2;
	                C[3] ^= i3;
	                C[4] ^= i0;
	                C[5] ^= i1;
	                C[6] ^= i2;
	                C[7] ^= i3;

	                // Iterate the system four times
	                for (var i = 0; i < 4; i++) {
	                    nextState.call(this);
	                }
	            }
	        },

	        _doProcessBlock: function (M, offset) {
	            // Shortcut
	            var X = this._X;

	            // Iterate the system
	            nextState.call(this);

	            // Generate four keystream words
	            S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16);
	            S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16);
	            S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16);
	            S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16);

	            for (var i = 0; i < 4; i++) {
	                // Swap endian
	                S[i] = (((S[i] << 8)  | (S[i] >>> 24)) & 0x00ff00ff) |
	                       (((S[i] << 24) | (S[i] >>> 8))  & 0xff00ff00);

	                // Encrypt
	                M[offset + i] ^= S[i];
	            }
	        },

	        blockSize: 128/32,

	        ivSize: 64/32
	    });

	    function nextState() {
	        // Shortcuts
	        var X = this._X;
	        var C = this._C;

	        // Save old counter values
	        for (var i = 0; i < 8; i++) {
	            C_[i] = C[i];
	        }

	        // Calculate new counter values
	        C[0] = (C[0] + 0x4d34d34d + this._b) | 0;
	        C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0;
	        C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0;
	        C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0;
	        C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0;
	        C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0;
	        C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0;
	        C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0;
	        this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0;

	        // Calculate the g-values
	        for (var i = 0; i < 8; i++) {
	            var gx = X[i] + C[i];

	            // Construct high and low argument for squaring
	            var ga = gx & 0xffff;
	            var gb = gx >>> 16;

	            // Calculate high and low result of squaring
	            var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb;
	            var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0);

	            // High XOR low
	            G[i] = gh ^ gl;
	        }

	        // Calculate new state values
	        X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0;
	        X[1] = (G[1] + ((G[0] << 8)  | (G[0] >>> 24)) + G[7]) | 0;
	        X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0;
	        X[3] = (G[3] + ((G[2] << 8)  | (G[2] >>> 24)) + G[1]) | 0;
	        X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0;
	        X[5] = (G[5] + ((G[4] << 8)  | (G[4] >>> 24)) + G[3]) | 0;
	        X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0;
	        X[7] = (G[7] + ((G[6] << 8)  | (G[6] >>> 24)) + G[5]) | 0;
	    }

	    /**
	     * Shortcut functions to the cipher's object interface.
	     *
	     * @example
	     *
	     *     var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg);
	     *     var plaintext  = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg);
	     */
	    C.RabbitLegacy = StreamCipher._createHelper(RabbitLegacy);
	}());


	return CryptoJS.RabbitLegacy;

}));

/***/ }),

/***/ "./node_modules/crypto-js/rabbit.js":
/*!******************************************!*\
  !*** ./node_modules/crypto-js/rabbit.js ***!
  \******************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./enc-base64 */ "./node_modules/crypto-js/enc-base64.js"), __webpack_require__(/*! ./md5 */ "./node_modules/crypto-js/md5.js"), __webpack_require__(/*! ./evpkdf */ "./node_modules/crypto-js/evpkdf.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var StreamCipher = C_lib.StreamCipher;
	    var C_algo = C.algo;

	    // Reusable objects
	    var S  = [];
	    var C_ = [];
	    var G  = [];

	    /**
	     * Rabbit stream cipher algorithm
	     */
	    var Rabbit = C_algo.Rabbit = StreamCipher.extend({
	        _doReset: function () {
	            // Shortcuts
	            var K = this._key.words;
	            var iv = this.cfg.iv;

	            // Swap endian
	            for (var i = 0; i < 4; i++) {
	                K[i] = (((K[i] << 8)  | (K[i] >>> 24)) & 0x00ff00ff) |
	                       (((K[i] << 24) | (K[i] >>> 8))  & 0xff00ff00);
	            }

	            // Generate initial state values
	            var X = this._X = [
	                K[0], (K[3] << 16) | (K[2] >>> 16),
	                K[1], (K[0] << 16) | (K[3] >>> 16),
	                K[2], (K[1] << 16) | (K[0] >>> 16),
	                K[3], (K[2] << 16) | (K[1] >>> 16)
	            ];

	            // Generate initial counter values
	            var C = this._C = [
	                (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff),
	                (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff),
	                (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff),
	                (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff)
	            ];

	            // Carry bit
	            this._b = 0;

	            // Iterate the system four times
	            for (var i = 0; i < 4; i++) {
	                nextState.call(this);
	            }

	            // Modify the counters
	            for (var i = 0; i < 8; i++) {
	                C[i] ^= X[(i + 4) & 7];
	            }

	            // IV setup
	            if (iv) {
	                // Shortcuts
	                var IV = iv.words;
	                var IV_0 = IV[0];
	                var IV_1 = IV[1];

	                // Generate four subvectors
	                var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00);
	                var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00);
	                var i1 = (i0 >>> 16) | (i2 & 0xffff0000);
	                var i3 = (i2 << 16)  | (i0 & 0x0000ffff);

	                // Modify counter values
	                C[0] ^= i0;
	                C[1] ^= i1;
	                C[2] ^= i2;
	                C[3] ^= i3;
	                C[4] ^= i0;
	                C[5] ^= i1;
	                C[6] ^= i2;
	                C[7] ^= i3;

	                // Iterate the system four times
	                for (var i = 0; i < 4; i++) {
	                    nextState.call(this);
	                }
	            }
	        },

	        _doProcessBlock: function (M, offset) {
	            // Shortcut
	            var X = this._X;

	            // Iterate the system
	            nextState.call(this);

	            // Generate four keystream words
	            S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16);
	            S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16);
	            S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16);
	            S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16);

	            for (var i = 0; i < 4; i++) {
	                // Swap endian
	                S[i] = (((S[i] << 8)  | (S[i] >>> 24)) & 0x00ff00ff) |
	                       (((S[i] << 24) | (S[i] >>> 8))  & 0xff00ff00);

	                // Encrypt
	                M[offset + i] ^= S[i];
	            }
	        },

	        blockSize: 128/32,

	        ivSize: 64/32
	    });

	    function nextState() {
	        // Shortcuts
	        var X = this._X;
	        var C = this._C;

	        // Save old counter values
	        for (var i = 0; i < 8; i++) {
	            C_[i] = C[i];
	        }

	        // Calculate new counter values
	        C[0] = (C[0] + 0x4d34d34d + this._b) | 0;
	        C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0;
	        C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0;
	        C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0;
	        C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0;
	        C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0;
	        C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0;
	        C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0;
	        this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0;

	        // Calculate the g-values
	        for (var i = 0; i < 8; i++) {
	            var gx = X[i] + C[i];

	            // Construct high and low argument for squaring
	            var ga = gx & 0xffff;
	            var gb = gx >>> 16;

	            // Calculate high and low result of squaring
	            var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb;
	            var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0);

	            // High XOR low
	            G[i] = gh ^ gl;
	        }

	        // Calculate new state values
	        X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0;
	        X[1] = (G[1] + ((G[0] << 8)  | (G[0] >>> 24)) + G[7]) | 0;
	        X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0;
	        X[3] = (G[3] + ((G[2] << 8)  | (G[2] >>> 24)) + G[1]) | 0;
	        X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0;
	        X[5] = (G[5] + ((G[4] << 8)  | (G[4] >>> 24)) + G[3]) | 0;
	        X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0;
	        X[7] = (G[7] + ((G[6] << 8)  | (G[6] >>> 24)) + G[5]) | 0;
	    }

	    /**
	     * Shortcut functions to the cipher's object interface.
	     *
	     * @example
	     *
	     *     var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg);
	     *     var plaintext  = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg);
	     */
	    C.Rabbit = StreamCipher._createHelper(Rabbit);
	}());


	return CryptoJS.Rabbit;

}));

/***/ }),

/***/ "./node_modules/crypto-js/rc4.js":
/*!***************************************!*\
  !*** ./node_modules/crypto-js/rc4.js ***!
  \***************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./enc-base64 */ "./node_modules/crypto-js/enc-base64.js"), __webpack_require__(/*! ./md5 */ "./node_modules/crypto-js/md5.js"), __webpack_require__(/*! ./evpkdf */ "./node_modules/crypto-js/evpkdf.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var StreamCipher = C_lib.StreamCipher;
	    var C_algo = C.algo;

	    /**
	     * RC4 stream cipher algorithm.
	     */
	    var RC4 = C_algo.RC4 = StreamCipher.extend({
	        _doReset: function () {
	            // Shortcuts
	            var key = this._key;
	            var keyWords = key.words;
	            var keySigBytes = key.sigBytes;

	            // Init sbox
	            var S = this._S = [];
	            for (var i = 0; i < 256; i++) {
	                S[i] = i;
	            }

	            // Key setup
	            for (var i = 0, j = 0; i < 256; i++) {
	                var keyByteIndex = i % keySigBytes;
	                var keyByte = (keyWords[keyByteIndex >>> 2] >>> (24 - (keyByteIndex % 4) * 8)) & 0xff;

	                j = (j + S[i] + keyByte) % 256;

	                // Swap
	                var t = S[i];
	                S[i] = S[j];
	                S[j] = t;
	            }

	            // Counters
	            this._i = this._j = 0;
	        },

	        _doProcessBlock: function (M, offset) {
	            M[offset] ^= generateKeystreamWord.call(this);
	        },

	        keySize: 256/32,

	        ivSize: 0
	    });

	    function generateKeystreamWord() {
	        // Shortcuts
	        var S = this._S;
	        var i = this._i;
	        var j = this._j;

	        // Generate keystream word
	        var keystreamWord = 0;
	        for (var n = 0; n < 4; n++) {
	            i = (i + 1) % 256;
	            j = (j + S[i]) % 256;

	            // Swap
	            var t = S[i];
	            S[i] = S[j];
	            S[j] = t;

	            keystreamWord |= S[(S[i] + S[j]) % 256] << (24 - n * 8);
	        }

	        // Update counters
	        this._i = i;
	        this._j = j;

	        return keystreamWord;
	    }

	    /**
	     * Shortcut functions to the cipher's object interface.
	     *
	     * @example
	     *
	     *     var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg);
	     *     var plaintext  = CryptoJS.RC4.decrypt(ciphertext, key, cfg);
	     */
	    C.RC4 = StreamCipher._createHelper(RC4);

	    /**
	     * Modified RC4 stream cipher algorithm.
	     */
	    var RC4Drop = C_algo.RC4Drop = RC4.extend({
	        /**
	         * Configuration options.
	         *
	         * @property {number} drop The number of keystream words to drop. Default 192
	         */
	        cfg: RC4.cfg.extend({
	            drop: 192
	        }),

	        _doReset: function () {
	            RC4._doReset.call(this);

	            // Drop
	            for (var i = this.cfg.drop; i > 0; i--) {
	                generateKeystreamWord.call(this);
	            }
	        }
	    });

	    /**
	     * Shortcut functions to the cipher's object interface.
	     *
	     * @example
	     *
	     *     var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg);
	     *     var plaintext  = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg);
	     */
	    C.RC4Drop = StreamCipher._createHelper(RC4Drop);
	}());


	return CryptoJS.RC4;

}));

/***/ }),

/***/ "./node_modules/crypto-js/ripemd160.js":
/*!*********************************************!*\
  !*** ./node_modules/crypto-js/ripemd160.js ***!
  \*********************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	/** @preserve
	(c) 2012 by Cédric Mesnil. All rights reserved.

	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

	    - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
	    - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	*/

	(function (Math) {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var WordArray = C_lib.WordArray;
	    var Hasher = C_lib.Hasher;
	    var C_algo = C.algo;

	    // Constants table
	    var _zl = WordArray.create([
	        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 _zr = WordArray.create([
	        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 _sl = WordArray.create([
	         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 _sr = WordArray.create([
	        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 ]);

	    var _hl =  WordArray.create([ 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]);
	    var _hr =  WordArray.create([ 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]);

	    /**
	     * RIPEMD160 hash algorithm.
	     */
	    var RIPEMD160 = C_algo.RIPEMD160 = Hasher.extend({
	        _doReset: function () {
	            this._hash  = WordArray.create([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]);
	        },

	        _doProcessBlock: function (M, offset) {

	            // Swap endian
	            for (var i = 0; i < 16; i++) {
	                // Shortcuts
	                var offset_i = offset + i;
	                var M_offset_i = M[offset_i];

	                // Swap
	                M[offset_i] = (
	                    (((M_offset_i << 8)  | (M_offset_i >>> 24)) & 0x00ff00ff) |
	                    (((M_offset_i << 24) | (M_offset_i >>> 8))  & 0xff00ff00)
	                );
	            }
	            // Shortcut
	            var H  = this._hash.words;
	            var hl = _hl.words;
	            var hr = _hr.words;
	            var zl = _zl.words;
	            var zr = _zr.words;
	            var sl = _sl.words;
	            var sr = _sr.words;

	            // Working variables
	            var al, bl, cl, dl, el;
	            var ar, br, cr, dr, er;

	            ar = al = H[0];
	            br = bl = H[1];
	            cr = cl = H[2];
	            dr = dl = H[3];
	            er = el = H[4];
	            // Computation
	            var t;
	            for (var i = 0; i < 80; i += 1) {
	                t = (al +  M[offset+zl[i]])|0;
	                if (i<16){
		            t +=  f1(bl,cl,dl) + hl[0];
	                } else if (i<32) {
		            t +=  f2(bl,cl,dl) + hl[1];
	                } else if (i<48) {
		            t +=  f3(bl,cl,dl) + hl[2];
	                } else if (i<64) {
		            t +=  f4(bl,cl,dl) + hl[3];
	                } else {// if (i<80) {
		            t +=  f5(bl,cl,dl) + hl[4];
	                }
	                t = t|0;
	                t =  rotl(t,sl[i]);
	                t = (t+el)|0;
	                al = el;
	                el = dl;
	                dl = rotl(cl, 10);
	                cl = bl;
	                bl = t;

	                t = (ar + M[offset+zr[i]])|0;
	                if (i<16){
		            t +=  f5(br,cr,dr) + hr[0];
	                } else if (i<32) {
		            t +=  f4(br,cr,dr) + hr[1];
	                } else if (i<48) {
		            t +=  f3(br,cr,dr) + hr[2];
	                } else if (i<64) {
		            t +=  f2(br,cr,dr) + hr[3];
	                } else {// if (i<80) {
		            t +=  f1(br,cr,dr) + hr[4];
	                }
	                t = t|0;
	                t =  rotl(t,sr[i]) ;
	                t = (t+er)|0;
	                ar = er;
	                er = dr;
	                dr = rotl(cr, 10);
	                cr = br;
	                br = t;
	            }
	            // Intermediate hash value
	            t    = (H[1] + cl + dr)|0;
	            H[1] = (H[2] + dl + er)|0;
	            H[2] = (H[3] + el + ar)|0;
	            H[3] = (H[4] + al + br)|0;
	            H[4] = (H[0] + bl + cr)|0;
	            H[0] =  t;
	        },

	        _doFinalize: function () {
	            // Shortcuts
	            var data = this._data;
	            var dataWords = data.words;

	            var nBitsTotal = this._nDataBytes * 8;
	            var nBitsLeft = data.sigBytes * 8;

	            // Add padding
	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
	                (((nBitsTotal << 8)  | (nBitsTotal >>> 24)) & 0x00ff00ff) |
	                (((nBitsTotal << 24) | (nBitsTotal >>> 8))  & 0xff00ff00)
	            );
	            data.sigBytes = (dataWords.length + 1) * 4;

	            // Hash final blocks
	            this._process();

	            // Shortcuts
	            var hash = this._hash;
	            var H = hash.words;

	            // Swap endian
	            for (var i = 0; i < 5; i++) {
	                // Shortcut
	                var H_i = H[i];

	                // Swap
	                H[i] = (((H_i << 8)  | (H_i >>> 24)) & 0x00ff00ff) |
	                       (((H_i << 24) | (H_i >>> 8))  & 0xff00ff00);
	            }

	            // Return final computed hash
	            return hash;
	        },

	        clone: function () {
	            var clone = Hasher.clone.call(this);
	            clone._hash = this._hash.clone();

	            return clone;
	        }
	    });


	    function f1(x, y, z) {
	        return ((x) ^ (y) ^ (z));

	    }

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

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

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

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

	    }

	    function rotl(x,n) {
	        return (x<<n) | (x>>>(32-n));
	    }


	    /**
	     * Shortcut function to the hasher's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     *
	     * @return {WordArray} The hash.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hash = CryptoJS.RIPEMD160('message');
	     *     var hash = CryptoJS.RIPEMD160(wordArray);
	     */
	    C.RIPEMD160 = Hasher._createHelper(RIPEMD160);

	    /**
	     * Shortcut function to the HMAC's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     * @param {WordArray|string} key The secret key.
	     *
	     * @return {WordArray} The HMAC.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hmac = CryptoJS.HmacRIPEMD160(message, key);
	     */
	    C.HmacRIPEMD160 = Hasher._createHmacHelper(RIPEMD160);
	}(Math));


	return CryptoJS.RIPEMD160;

}));

/***/ }),

/***/ "./node_modules/crypto-js/sha1.js":
/*!****************************************!*\
  !*** ./node_modules/crypto-js/sha1.js ***!
  \****************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var WordArray = C_lib.WordArray;
	    var Hasher = C_lib.Hasher;
	    var C_algo = C.algo;

	    // Reusable object
	    var W = [];

	    /**
	     * SHA-1 hash algorithm.
	     */
	    var SHA1 = C_algo.SHA1 = Hasher.extend({
	        _doReset: function () {
	            this._hash = new WordArray.init([
	                0x67452301, 0xefcdab89,
	                0x98badcfe, 0x10325476,
	                0xc3d2e1f0
	            ]);
	        },

	        _doProcessBlock: function (M, offset) {
	            // Shortcut
	            var H = this._hash.words;

	            // Working variables
	            var a = H[0];
	            var b = H[1];
	            var c = H[2];
	            var d = H[3];
	            var e = H[4];

	            // Computation
	            for (var i = 0; i < 80; i++) {
	                if (i < 16) {
	                    W[i] = M[offset + i] | 0;
	                } else {
	                    var n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
	                    W[i] = (n << 1) | (n >>> 31);
	                }

	                var t = ((a << 5) | (a >>> 27)) + e + W[i];
	                if (i < 20) {
	                    t += ((b & c) | (~b & d)) + 0x5a827999;
	                } else if (i < 40) {
	                    t += (b ^ c ^ d) + 0x6ed9eba1;
	                } else if (i < 60) {
	                    t += ((b & c) | (b & d) | (c & d)) - 0x70e44324;
	                } else /* if (i < 80) */ {
	                    t += (b ^ c ^ d) - 0x359d3e2a;
	                }

	                e = d;
	                d = c;
	                c = (b << 30) | (b >>> 2);
	                b = a;
	                a = t;
	            }

	            // Intermediate hash value
	            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;
	        },

	        _doFinalize: function () {
	            // Shortcuts
	            var data = this._data;
	            var dataWords = data.words;

	            var nBitsTotal = this._nDataBytes * 8;
	            var nBitsLeft = data.sigBytes * 8;

	            // Add padding
	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
	            data.sigBytes = dataWords.length * 4;

	            // Hash final blocks
	            this._process();

	            // Return final computed hash
	            return this._hash;
	        },

	        clone: function () {
	            var clone = Hasher.clone.call(this);
	            clone._hash = this._hash.clone();

	            return clone;
	        }
	    });

	    /**
	     * Shortcut function to the hasher's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     *
	     * @return {WordArray} The hash.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hash = CryptoJS.SHA1('message');
	     *     var hash = CryptoJS.SHA1(wordArray);
	     */
	    C.SHA1 = Hasher._createHelper(SHA1);

	    /**
	     * Shortcut function to the HMAC's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     * @param {WordArray|string} key The secret key.
	     *
	     * @return {WordArray} The HMAC.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hmac = CryptoJS.HmacSHA1(message, key);
	     */
	    C.HmacSHA1 = Hasher._createHmacHelper(SHA1);
	}());


	return CryptoJS.SHA1;

}));

/***/ }),

/***/ "./node_modules/crypto-js/sha224.js":
/*!******************************************!*\
  !*** ./node_modules/crypto-js/sha224.js ***!
  \******************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./sha256 */ "./node_modules/crypto-js/sha256.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var WordArray = C_lib.WordArray;
	    var C_algo = C.algo;
	    var SHA256 = C_algo.SHA256;

	    /**
	     * SHA-224 hash algorithm.
	     */
	    var SHA224 = C_algo.SHA224 = SHA256.extend({
	        _doReset: function () {
	            this._hash = new WordArray.init([
	                0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
	                0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
	            ]);
	        },

	        _doFinalize: function () {
	            var hash = SHA256._doFinalize.call(this);

	            hash.sigBytes -= 4;

	            return hash;
	        }
	    });

	    /**
	     * Shortcut function to the hasher's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     *
	     * @return {WordArray} The hash.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hash = CryptoJS.SHA224('message');
	     *     var hash = CryptoJS.SHA224(wordArray);
	     */
	    C.SHA224 = SHA256._createHelper(SHA224);

	    /**
	     * Shortcut function to the HMAC's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     * @param {WordArray|string} key The secret key.
	     *
	     * @return {WordArray} The HMAC.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hmac = CryptoJS.HmacSHA224(message, key);
	     */
	    C.HmacSHA224 = SHA256._createHmacHelper(SHA224);
	}());


	return CryptoJS.SHA224;

}));

/***/ }),

/***/ "./node_modules/crypto-js/sha256.js":
/*!******************************************!*\
  !*** ./node_modules/crypto-js/sha256.js ***!
  \******************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function (Math) {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var WordArray = C_lib.WordArray;
	    var Hasher = C_lib.Hasher;
	    var C_algo = C.algo;

	    // Initialization and round constants tables
	    var H = [];
	    var K = [];

	    // Compute constants
	    (function () {
	        function isPrime(n) {
	            var sqrtN = Math.sqrt(n);
	            for (var factor = 2; factor <= sqrtN; factor++) {
	                if (!(n % factor)) {
	                    return false;
	                }
	            }

	            return true;
	        }

	        function getFractionalBits(n) {
	            return ((n - (n | 0)) * 0x100000000) | 0;
	        }

	        var n = 2;
	        var nPrime = 0;
	        while (nPrime < 64) {
	            if (isPrime(n)) {
	                if (nPrime < 8) {
	                    H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2));
	                }
	                K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3));

	                nPrime++;
	            }

	            n++;
	        }
	    }());

	    // Reusable object
	    var W = [];

	    /**
	     * SHA-256 hash algorithm.
	     */
	    var SHA256 = C_algo.SHA256 = Hasher.extend({
	        _doReset: function () {
	            this._hash = new WordArray.init(H.slice(0));
	        },

	        _doProcessBlock: function (M, offset) {
	            // Shortcut
	            var H = this._hash.words;

	            // Working variables
	            var a = H[0];
	            var b = H[1];
	            var c = H[2];
	            var d = H[3];
	            var e = H[4];
	            var f = H[5];
	            var g = H[6];
	            var h = H[7];

	            // Computation
	            for (var i = 0; i < 64; i++) {
	                if (i < 16) {
	                    W[i] = M[offset + i] | 0;
	                } else {
	                    var gamma0x = W[i - 15];
	                    var gamma0  = ((gamma0x << 25) | (gamma0x >>> 7))  ^
	                                  ((gamma0x << 14) | (gamma0x >>> 18)) ^
	                                   (gamma0x >>> 3);

	                    var gamma1x = W[i - 2];
	                    var gamma1  = ((gamma1x << 15) | (gamma1x >>> 17)) ^
	                                  ((gamma1x << 13) | (gamma1x >>> 19)) ^
	                                   (gamma1x >>> 10);

	                    W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
	                }

	                var ch  = (e & f) ^ (~e & g);
	                var maj = (a & b) ^ (a & c) ^ (b & c);

	                var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
	                var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7)  | (e >>> 25));

	                var t1 = h + sigma1 + ch + K[i] + W[i];
	                var t2 = sigma0 + maj;

	                h = g;
	                g = f;
	                f = e;
	                e = (d + t1) | 0;
	                d = c;
	                c = b;
	                b = a;
	                a = (t1 + t2) | 0;
	            }

	            // Intermediate hash value
	            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;
	            H[5] = (H[5] + f) | 0;
	            H[6] = (H[6] + g) | 0;
	            H[7] = (H[7] + h) | 0;
	        },

	        _doFinalize: function () {
	            // Shortcuts
	            var data = this._data;
	            var dataWords = data.words;

	            var nBitsTotal = this._nDataBytes * 8;
	            var nBitsLeft = data.sigBytes * 8;

	            // Add padding
	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
	            data.sigBytes = dataWords.length * 4;

	            // Hash final blocks
	            this._process();

	            // Return final computed hash
	            return this._hash;
	        },

	        clone: function () {
	            var clone = Hasher.clone.call(this);
	            clone._hash = this._hash.clone();

	            return clone;
	        }
	    });

	    /**
	     * Shortcut function to the hasher's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     *
	     * @return {WordArray} The hash.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hash = CryptoJS.SHA256('message');
	     *     var hash = CryptoJS.SHA256(wordArray);
	     */
	    C.SHA256 = Hasher._createHelper(SHA256);

	    /**
	     * Shortcut function to the HMAC's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     * @param {WordArray|string} key The secret key.
	     *
	     * @return {WordArray} The HMAC.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hmac = CryptoJS.HmacSHA256(message, key);
	     */
	    C.HmacSHA256 = Hasher._createHmacHelper(SHA256);
	}(Math));


	return CryptoJS.SHA256;

}));

/***/ }),

/***/ "./node_modules/crypto-js/sha3.js":
/*!****************************************!*\
  !*** ./node_modules/crypto-js/sha3.js ***!
  \****************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./x64-core */ "./node_modules/crypto-js/x64-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function (Math) {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var WordArray = C_lib.WordArray;
	    var Hasher = C_lib.Hasher;
	    var C_x64 = C.x64;
	    var X64Word = C_x64.Word;
	    var C_algo = C.algo;

	    // Constants tables
	    var RHO_OFFSETS = [];
	    var PI_INDEXES  = [];
	    var ROUND_CONSTANTS = [];

	    // Compute Constants
	    (function () {
	        // Compute rho offset constants
	        var x = 1, y = 0;
	        for (var t = 0; t < 24; t++) {
	            RHO_OFFSETS[x + 5 * y] = ((t + 1) * (t + 2) / 2) % 64;

	            var newX = y % 5;
	            var newY = (2 * x + 3 * y) % 5;
	            x = newX;
	            y = newY;
	        }

	        // Compute pi index constants
	        for (var x = 0; x < 5; x++) {
	            for (var y = 0; y < 5; y++) {
	                PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5;
	            }
	        }

	        // Compute round constants
	        var LFSR = 0x01;
	        for (var i = 0; i < 24; i++) {
	            var roundConstantMsw = 0;
	            var roundConstantLsw = 0;

	            for (var j = 0; j < 7; j++) {
	                if (LFSR & 0x01) {
	                    var bitPosition = (1 << j) - 1;
	                    if (bitPosition < 32) {
	                        roundConstantLsw ^= 1 << bitPosition;
	                    } else /* if (bitPosition >= 32) */ {
	                        roundConstantMsw ^= 1 << (bitPosition - 32);
	                    }
	                }

	                // Compute next LFSR
	                if (LFSR & 0x80) {
	                    // Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1
	                    LFSR = (LFSR << 1) ^ 0x71;
	                } else {
	                    LFSR <<= 1;
	                }
	            }

	            ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw);
	        }
	    }());

	    // Reusable objects for temporary values
	    var T = [];
	    (function () {
	        for (var i = 0; i < 25; i++) {
	            T[i] = X64Word.create();
	        }
	    }());

	    /**
	     * SHA-3 hash algorithm.
	     */
	    var SHA3 = C_algo.SHA3 = Hasher.extend({
	        /**
	         * Configuration options.
	         *
	         * @property {number} outputLength
	         *   The desired number of bits in the output hash.
	         *   Only values permitted are: 224, 256, 384, 512.
	         *   Default: 512
	         */
	        cfg: Hasher.cfg.extend({
	            outputLength: 512
	        }),

	        _doReset: function () {
	            var state = this._state = []
	            for (var i = 0; i < 25; i++) {
	                state[i] = new X64Word.init();
	            }

	            this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32;
	        },

	        _doProcessBlock: function (M, offset) {
	            // Shortcuts
	            var state = this._state;
	            var nBlockSizeLanes = this.blockSize / 2;

	            // Absorb
	            for (var i = 0; i < nBlockSizeLanes; i++) {
	                // Shortcuts
	                var M2i  = M[offset + 2 * i];
	                var M2i1 = M[offset + 2 * i + 1];

	                // Swap endian
	                M2i = (
	                    (((M2i << 8)  | (M2i >>> 24)) & 0x00ff00ff) |
	                    (((M2i << 24) | (M2i >>> 8))  & 0xff00ff00)
	                );
	                M2i1 = (
	                    (((M2i1 << 8)  | (M2i1 >>> 24)) & 0x00ff00ff) |
	                    (((M2i1 << 24) | (M2i1 >>> 8))  & 0xff00ff00)
	                );

	                // Absorb message into state
	                var lane = state[i];
	                lane.high ^= M2i1;
	                lane.low  ^= M2i;
	            }

	            // Rounds
	            for (var round = 0; round < 24; round++) {
	                // Theta
	                for (var x = 0; x < 5; x++) {
	                    // Mix column lanes
	                    var tMsw = 0, tLsw = 0;
	                    for (var y = 0; y < 5; y++) {
	                        var lane = state[x + 5 * y];
	                        tMsw ^= lane.high;
	                        tLsw ^= lane.low;
	                    }

	                    // Temporary values
	                    var Tx = T[x];
	                    Tx.high = tMsw;
	                    Tx.low  = tLsw;
	                }
	                for (var x = 0; x < 5; x++) {
	                    // Shortcuts
	                    var Tx4 = T[(x + 4) % 5];
	                    var Tx1 = T[(x + 1) % 5];
	                    var Tx1Msw = Tx1.high;
	                    var Tx1Lsw = Tx1.low;

	                    // Mix surrounding columns
	                    var tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31));
	                    var tLsw = Tx4.low  ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31));
	                    for (var y = 0; y < 5; y++) {
	                        var lane = state[x + 5 * y];
	                        lane.high ^= tMsw;
	                        lane.low  ^= tLsw;
	                    }
	                }

	                // Rho Pi
	                for (var laneIndex = 1; laneIndex < 25; laneIndex++) {
	                    var tMsw;
	                    var tLsw;

	                    // Shortcuts
	                    var lane = state[laneIndex];
	                    var laneMsw = lane.high;
	                    var laneLsw = lane.low;
	                    var rhoOffset = RHO_OFFSETS[laneIndex];

	                    // Rotate lanes
	                    if (rhoOffset < 32) {
	                        tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset));
	                        tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset));
	                    } else /* if (rhoOffset >= 32) */ {
	                        tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset));
	                        tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset));
	                    }

	                    // Transpose lanes
	                    var TPiLane = T[PI_INDEXES[laneIndex]];
	                    TPiLane.high = tMsw;
	                    TPiLane.low  = tLsw;
	                }

	                // Rho pi at x = y = 0
	                var T0 = T[0];
	                var state0 = state[0];
	                T0.high = state0.high;
	                T0.low  = state0.low;

	                // Chi
	                for (var x = 0; x < 5; x++) {
	                    for (var y = 0; y < 5; y++) {
	                        // Shortcuts
	                        var laneIndex = x + 5 * y;
	                        var lane = state[laneIndex];
	                        var TLane = T[laneIndex];
	                        var Tx1Lane = T[((x + 1) % 5) + 5 * y];
	                        var Tx2Lane = T[((x + 2) % 5) + 5 * y];

	                        // Mix rows
	                        lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high);
	                        lane.low  = TLane.low  ^ (~Tx1Lane.low  & Tx2Lane.low);
	                    }
	                }

	                // Iota
	                var lane = state[0];
	                var roundConstant = ROUND_CONSTANTS[round];
	                lane.high ^= roundConstant.high;
	                lane.low  ^= roundConstant.low;
	            }
	        },

	        _doFinalize: function () {
	            // Shortcuts
	            var data = this._data;
	            var dataWords = data.words;
	            var nBitsTotal = this._nDataBytes * 8;
	            var nBitsLeft = data.sigBytes * 8;
	            var blockSizeBits = this.blockSize * 32;

	            // Add padding
	            dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - nBitsLeft % 32);
	            dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80;
	            data.sigBytes = dataWords.length * 4;

	            // Hash final blocks
	            this._process();

	            // Shortcuts
	            var state = this._state;
	            var outputLengthBytes = this.cfg.outputLength / 8;
	            var outputLengthLanes = outputLengthBytes / 8;

	            // Squeeze
	            var hashWords = [];
	            for (var i = 0; i < outputLengthLanes; i++) {
	                // Shortcuts
	                var lane = state[i];
	                var laneMsw = lane.high;
	                var laneLsw = lane.low;

	                // Swap endian
	                laneMsw = (
	                    (((laneMsw << 8)  | (laneMsw >>> 24)) & 0x00ff00ff) |
	                    (((laneMsw << 24) | (laneMsw >>> 8))  & 0xff00ff00)
	                );
	                laneLsw = (
	                    (((laneLsw << 8)  | (laneLsw >>> 24)) & 0x00ff00ff) |
	                    (((laneLsw << 24) | (laneLsw >>> 8))  & 0xff00ff00)
	                );

	                // Squeeze state to retrieve hash
	                hashWords.push(laneLsw);
	                hashWords.push(laneMsw);
	            }

	            // Return final computed hash
	            return new WordArray.init(hashWords, outputLengthBytes);
	        },

	        clone: function () {
	            var clone = Hasher.clone.call(this);

	            var state = clone._state = this._state.slice(0);
	            for (var i = 0; i < 25; i++) {
	                state[i] = state[i].clone();
	            }

	            return clone;
	        }
	    });

	    /**
	     * Shortcut function to the hasher's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     *
	     * @return {WordArray} The hash.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hash = CryptoJS.SHA3('message');
	     *     var hash = CryptoJS.SHA3(wordArray);
	     */
	    C.SHA3 = Hasher._createHelper(SHA3);

	    /**
	     * Shortcut function to the HMAC's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     * @param {WordArray|string} key The secret key.
	     *
	     * @return {WordArray} The HMAC.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hmac = CryptoJS.HmacSHA3(message, key);
	     */
	    C.HmacSHA3 = Hasher._createHmacHelper(SHA3);
	}(Math));


	return CryptoJS.SHA3;

}));

/***/ }),

/***/ "./node_modules/crypto-js/sha384.js":
/*!******************************************!*\
  !*** ./node_modules/crypto-js/sha384.js ***!
  \******************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./x64-core */ "./node_modules/crypto-js/x64-core.js"), __webpack_require__(/*! ./sha512 */ "./node_modules/crypto-js/sha512.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_x64 = C.x64;
	    var X64Word = C_x64.Word;
	    var X64WordArray = C_x64.WordArray;
	    var C_algo = C.algo;
	    var SHA512 = C_algo.SHA512;

	    /**
	     * SHA-384 hash algorithm.
	     */
	    var SHA384 = C_algo.SHA384 = SHA512.extend({
	        _doReset: function () {
	            this._hash = new X64WordArray.init([
	                new X64Word.init(0xcbbb9d5d, 0xc1059ed8), new X64Word.init(0x629a292a, 0x367cd507),
	                new X64Word.init(0x9159015a, 0x3070dd17), new X64Word.init(0x152fecd8, 0xf70e5939),
	                new X64Word.init(0x67332667, 0xffc00b31), new X64Word.init(0x8eb44a87, 0x68581511),
	                new X64Word.init(0xdb0c2e0d, 0x64f98fa7), new X64Word.init(0x47b5481d, 0xbefa4fa4)
	            ]);
	        },

	        _doFinalize: function () {
	            var hash = SHA512._doFinalize.call(this);

	            hash.sigBytes -= 16;

	            return hash;
	        }
	    });

	    /**
	     * Shortcut function to the hasher's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     *
	     * @return {WordArray} The hash.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hash = CryptoJS.SHA384('message');
	     *     var hash = CryptoJS.SHA384(wordArray);
	     */
	    C.SHA384 = SHA512._createHelper(SHA384);

	    /**
	     * Shortcut function to the HMAC's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     * @param {WordArray|string} key The secret key.
	     *
	     * @return {WordArray} The HMAC.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hmac = CryptoJS.HmacSHA384(message, key);
	     */
	    C.HmacSHA384 = SHA512._createHmacHelper(SHA384);
	}());


	return CryptoJS.SHA384;

}));

/***/ }),

/***/ "./node_modules/crypto-js/sha512.js":
/*!******************************************!*\
  !*** ./node_modules/crypto-js/sha512.js ***!
  \******************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./x64-core */ "./node_modules/crypto-js/x64-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var Hasher = C_lib.Hasher;
	    var C_x64 = C.x64;
	    var X64Word = C_x64.Word;
	    var X64WordArray = C_x64.WordArray;
	    var C_algo = C.algo;

	    function X64Word_create() {
	        return X64Word.create.apply(X64Word, arguments);
	    }

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

	    // Reusable objects
	    var W = [];
	    (function () {
	        for (var i = 0; i < 80; i++) {
	            W[i] = X64Word_create();
	        }
	    }());

	    /**
	     * SHA-512 hash algorithm.
	     */
	    var SHA512 = C_algo.SHA512 = Hasher.extend({
	        _doReset: function () {
	            this._hash = new X64WordArray.init([
	                new X64Word.init(0x6a09e667, 0xf3bcc908), new X64Word.init(0xbb67ae85, 0x84caa73b),
	                new X64Word.init(0x3c6ef372, 0xfe94f82b), new X64Word.init(0xa54ff53a, 0x5f1d36f1),
	                new X64Word.init(0x510e527f, 0xade682d1), new X64Word.init(0x9b05688c, 0x2b3e6c1f),
	                new X64Word.init(0x1f83d9ab, 0xfb41bd6b), new X64Word.init(0x5be0cd19, 0x137e2179)
	            ]);
	        },

	        _doProcessBlock: function (M, offset) {
	            // Shortcuts
	            var H = this._hash.words;

	            var H0 = H[0];
	            var H1 = H[1];
	            var H2 = H[2];
	            var H3 = H[3];
	            var H4 = H[4];
	            var H5 = H[5];
	            var H6 = H[6];
	            var H7 = H[7];

	            var H0h = H0.high;
	            var H0l = H0.low;
	            var H1h = H1.high;
	            var H1l = H1.low;
	            var H2h = H2.high;
	            var H2l = H2.low;
	            var H3h = H3.high;
	            var H3l = H3.low;
	            var H4h = H4.high;
	            var H4l = H4.low;
	            var H5h = H5.high;
	            var H5l = H5.low;
	            var H6h = H6.high;
	            var H6l = H6.low;
	            var H7h = H7.high;
	            var H7l = H7.low;

	            // Working variables
	            var ah = H0h;
	            var al = H0l;
	            var bh = H1h;
	            var bl = H1l;
	            var ch = H2h;
	            var cl = H2l;
	            var dh = H3h;
	            var dl = H3l;
	            var eh = H4h;
	            var el = H4l;
	            var fh = H5h;
	            var fl = H5l;
	            var gh = H6h;
	            var gl = H6l;
	            var hh = H7h;
	            var hl = H7l;

	            // Rounds
	            for (var i = 0; i < 80; i++) {
	                var Wil;
	                var Wih;

	                // Shortcut
	                var Wi = W[i];

	                // Extend message
	                if (i < 16) {
	                    Wih = Wi.high = M[offset + i * 2]     | 0;
	                    Wil = Wi.low  = M[offset + i * 2 + 1] | 0;
	                } else {
	                    // Gamma0
	                    var gamma0x  = W[i - 15];
	                    var gamma0xh = gamma0x.high;
	                    var gamma0xl = gamma0x.low;
	                    var gamma0h  = ((gamma0xh >>> 1) | (gamma0xl << 31)) ^ ((gamma0xh >>> 8) | (gamma0xl << 24)) ^ (gamma0xh >>> 7);
	                    var gamma0l  = ((gamma0xl >>> 1) | (gamma0xh << 31)) ^ ((gamma0xl >>> 8) | (gamma0xh << 24)) ^ ((gamma0xl >>> 7) | (gamma0xh << 25));

	                    // Gamma1
	                    var gamma1x  = W[i - 2];
	                    var gamma1xh = gamma1x.high;
	                    var gamma1xl = gamma1x.low;
	                    var gamma1h  = ((gamma1xh >>> 19) | (gamma1xl << 13)) ^ ((gamma1xh << 3) | (gamma1xl >>> 29)) ^ (gamma1xh >>> 6);
	                    var gamma1l  = ((gamma1xl >>> 19) | (gamma1xh << 13)) ^ ((gamma1xl << 3) | (gamma1xh >>> 29)) ^ ((gamma1xl >>> 6) | (gamma1xh << 26));

	                    // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]
	                    var Wi7  = W[i - 7];
	                    var Wi7h = Wi7.high;
	                    var Wi7l = Wi7.low;

	                    var Wi16  = W[i - 16];
	                    var Wi16h = Wi16.high;
	                    var Wi16l = Wi16.low;

	                    Wil = gamma0l + Wi7l;
	                    Wih = gamma0h + Wi7h + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0);
	                    Wil = Wil + gamma1l;
	                    Wih = Wih + gamma1h + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0);
	                    Wil = Wil + Wi16l;
	                    Wih = Wih + Wi16h + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0);

	                    Wi.high = Wih;
	                    Wi.low  = Wil;
	                }

	                var chh  = (eh & fh) ^ (~eh & gh);
	                var chl  = (el & fl) ^ (~el & gl);
	                var majh = (ah & bh) ^ (ah & ch) ^ (bh & ch);
	                var majl = (al & bl) ^ (al & cl) ^ (bl & cl);

	                var sigma0h = ((ah >>> 28) | (al << 4))  ^ ((ah << 30)  | (al >>> 2)) ^ ((ah << 25) | (al >>> 7));
	                var sigma0l = ((al >>> 28) | (ah << 4))  ^ ((al << 30)  | (ah >>> 2)) ^ ((al << 25) | (ah >>> 7));
	                var sigma1h = ((eh >>> 14) | (el << 18)) ^ ((eh >>> 18) | (el << 14)) ^ ((eh << 23) | (el >>> 9));
	                var sigma1l = ((el >>> 14) | (eh << 18)) ^ ((el >>> 18) | (eh << 14)) ^ ((el << 23) | (eh >>> 9));

	                // t1 = h + sigma1 + ch + K[i] + W[i]
	                var Ki  = K[i];
	                var Kih = Ki.high;
	                var Kil = Ki.low;

	                var t1l = hl + sigma1l;
	                var t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0);
	                var t1l = t1l + chl;
	                var t1h = t1h + chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0);
	                var t1l = t1l + Kil;
	                var t1h = t1h + Kih + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0);
	                var t1l = t1l + Wil;
	                var t1h = t1h + Wih + ((t1l >>> 0) < (Wil >>> 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 value
	            H0l = H0.low  = (H0l + al);
	            H0.high = (H0h + ah + ((H0l >>> 0) < (al >>> 0) ? 1 : 0));
	            H1l = H1.low  = (H1l + bl);
	            H1.high = (H1h + bh + ((H1l >>> 0) < (bl >>> 0) ? 1 : 0));
	            H2l = H2.low  = (H2l + cl);
	            H2.high = (H2h + ch + ((H2l >>> 0) < (cl >>> 0) ? 1 : 0));
	            H3l = H3.low  = (H3l + dl);
	            H3.high = (H3h + dh + ((H3l >>> 0) < (dl >>> 0) ? 1 : 0));
	            H4l = H4.low  = (H4l + el);
	            H4.high = (H4h + eh + ((H4l >>> 0) < (el >>> 0) ? 1 : 0));
	            H5l = H5.low  = (H5l + fl);
	            H5.high = (H5h + fh + ((H5l >>> 0) < (fl >>> 0) ? 1 : 0));
	            H6l = H6.low  = (H6l + gl);
	            H6.high = (H6h + gh + ((H6l >>> 0) < (gl >>> 0) ? 1 : 0));
	            H7l = H7.low  = (H7l + hl);
	            H7.high = (H7h + hh + ((H7l >>> 0) < (hl >>> 0) ? 1 : 0));
	        },

	        _doFinalize: function () {
	            // Shortcuts
	            var data = this._data;
	            var dataWords = data.words;

	            var nBitsTotal = this._nDataBytes * 8;
	            var nBitsLeft = data.sigBytes * 8;

	            // Add padding
	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
	            dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 30] = Math.floor(nBitsTotal / 0x100000000);
	            dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 31] = nBitsTotal;
	            data.sigBytes = dataWords.length * 4;

	            // Hash final blocks
	            this._process();

	            // Convert hash to 32-bit word array before returning
	            var hash = this._hash.toX32();

	            // Return final computed hash
	            return hash;
	        },

	        clone: function () {
	            var clone = Hasher.clone.call(this);
	            clone._hash = this._hash.clone();

	            return clone;
	        },

	        blockSize: 1024/32
	    });

	    /**
	     * Shortcut function to the hasher's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     *
	     * @return {WordArray} The hash.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hash = CryptoJS.SHA512('message');
	     *     var hash = CryptoJS.SHA512(wordArray);
	     */
	    C.SHA512 = Hasher._createHelper(SHA512);

	    /**
	     * Shortcut function to the HMAC's object interface.
	     *
	     * @param {WordArray|string} message The message to hash.
	     * @param {WordArray|string} key The secret key.
	     *
	     * @return {WordArray} The HMAC.
	     *
	     * @static
	     *
	     * @example
	     *
	     *     var hmac = CryptoJS.HmacSHA512(message, key);
	     */
	    C.HmacSHA512 = Hasher._createHmacHelper(SHA512);
	}());


	return CryptoJS.SHA512;

}));

/***/ }),

/***/ "./node_modules/crypto-js/tripledes.js":
/*!*********************************************!*\
  !*** ./node_modules/crypto-js/tripledes.js ***!
  \*********************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory, undef) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"), __webpack_require__(/*! ./enc-base64 */ "./node_modules/crypto-js/enc-base64.js"), __webpack_require__(/*! ./md5 */ "./node_modules/crypto-js/md5.js"), __webpack_require__(/*! ./evpkdf */ "./node_modules/crypto-js/evpkdf.js"), __webpack_require__(/*! ./cipher-core */ "./node_modules/crypto-js/cipher-core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function () {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var WordArray = C_lib.WordArray;
	    var BlockCipher = C_lib.BlockCipher;
	    var C_algo = C.algo;

	    // Permuted Choice 1 constants
	    var PC1 = [
	        57, 49, 41, 33, 25, 17, 9,  1,
	        58, 50, 42, 34, 26, 18, 10, 2,
	        59, 51, 43, 35, 27, 19, 11, 3,
	        60, 52, 44, 36, 63, 55, 47, 39,
	        31, 23, 15, 7,  62, 54, 46, 38,
	        30, 22, 14, 6,  61, 53, 45, 37,
	        29, 21, 13, 5,  28, 20, 12, 4
	    ];

	    // Permuted Choice 2 constants
	    var PC2 = [
	        14, 17, 11, 24, 1,  5,
	        3,  28, 15, 6,  21, 10,
	        23, 19, 12, 4,  26, 8,
	        16, 7,  27, 20, 13, 2,
	        41, 52, 31, 37, 47, 55,
	        30, 40, 51, 45, 33, 48,
	        44, 49, 39, 56, 34, 53,
	        46, 42, 50, 36, 29, 32
	    ];

	    // Cumulative bit shift constants
	    var BIT_SHIFTS = [1,  2,  4,  6,  8,  10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28];

	    // SBOXes and round permutation constants
	    var SBOX_P = [
	        {
	            0x0: 0x808200,
	            0x10000000: 0x8000,
	            0x20000000: 0x808002,
	            0x30000000: 0x2,
	            0x40000000: 0x200,
	            0x50000000: 0x808202,
	            0x60000000: 0x800202,
	            0x70000000: 0x800000,
	            0x80000000: 0x202,
	            0x90000000: 0x800200,
	            0xa0000000: 0x8200,
	            0xb0000000: 0x808000,
	            0xc0000000: 0x8002,
	            0xd0000000: 0x800002,
	            0xe0000000: 0x0,
	            0xf0000000: 0x8202,
	            0x8000000: 0x0,
	            0x18000000: 0x808202,
	            0x28000000: 0x8202,
	            0x38000000: 0x8000,
	            0x48000000: 0x808200,
	            0x58000000: 0x200,
	            0x68000000: 0x808002,
	            0x78000000: 0x2,
	            0x88000000: 0x800200,
	            0x98000000: 0x8200,
	            0xa8000000: 0x808000,
	            0xb8000000: 0x800202,
	            0xc8000000: 0x800002,
	            0xd8000000: 0x8002,
	            0xe8000000: 0x202,
	            0xf8000000: 0x800000,
	            0x1: 0x8000,
	            0x10000001: 0x2,
	            0x20000001: 0x808200,
	            0x30000001: 0x800000,
	            0x40000001: 0x808002,
	            0x50000001: 0x8200,
	            0x60000001: 0x200,
	            0x70000001: 0x800202,
	            0x80000001: 0x808202,
	            0x90000001: 0x808000,
	            0xa0000001: 0x800002,
	            0xb0000001: 0x8202,
	            0xc0000001: 0x202,
	            0xd0000001: 0x800200,
	            0xe0000001: 0x8002,
	            0xf0000001: 0x0,
	            0x8000001: 0x808202,
	            0x18000001: 0x808000,
	            0x28000001: 0x800000,
	            0x38000001: 0x200,
	            0x48000001: 0x8000,
	            0x58000001: 0x800002,
	            0x68000001: 0x2,
	            0x78000001: 0x8202,
	            0x88000001: 0x8002,
	            0x98000001: 0x800202,
	            0xa8000001: 0x202,
	            0xb8000001: 0x808200,
	            0xc8000001: 0x800200,
	            0xd8000001: 0x0,
	            0xe8000001: 0x8200,
	            0xf8000001: 0x808002
	        },
	        {
	            0x0: 0x40084010,
	            0x1000000: 0x4000,
	            0x2000000: 0x80000,
	            0x3000000: 0x40080010,
	            0x4000000: 0x40000010,
	            0x5000000: 0x40084000,
	            0x6000000: 0x40004000,
	            0x7000000: 0x10,
	            0x8000000: 0x84000,
	            0x9000000: 0x40004010,
	            0xa000000: 0x40000000,
	            0xb000000: 0x84010,
	            0xc000000: 0x80010,
	            0xd000000: 0x0,
	            0xe000000: 0x4010,
	            0xf000000: 0x40080000,
	            0x800000: 0x40004000,
	            0x1800000: 0x84010,
	            0x2800000: 0x10,
	            0x3800000: 0x40004010,
	            0x4800000: 0x40084010,
	            0x5800000: 0x40000000,
	            0x6800000: 0x80000,
	            0x7800000: 0x40080010,
	            0x8800000: 0x80010,
	            0x9800000: 0x0,
	            0xa800000: 0x4000,
	            0xb800000: 0x40080000,
	            0xc800000: 0x40000010,
	            0xd800000: 0x84000,
	            0xe800000: 0x40084000,
	            0xf800000: 0x4010,
	            0x10000000: 0x0,
	            0x11000000: 0x40080010,
	            0x12000000: 0x40004010,
	            0x13000000: 0x40084000,
	            0x14000000: 0x40080000,
	            0x15000000: 0x10,
	            0x16000000: 0x84010,
	            0x17000000: 0x4000,
	            0x18000000: 0x4010,
	            0x19000000: 0x80000,
	            0x1a000000: 0x80010,
	            0x1b000000: 0x40000010,
	            0x1c000000: 0x84000,
	            0x1d000000: 0x40004000,
	            0x1e000000: 0x40000000,
	            0x1f000000: 0x40084010,
	            0x10800000: 0x84010,
	            0x11800000: 0x80000,
	            0x12800000: 0x40080000,
	            0x13800000: 0x4000,
	            0x14800000: 0x40004000,
	            0x15800000: 0x40084010,
	            0x16800000: 0x10,
	            0x17800000: 0x40000000,
	            0x18800000: 0x40084000,
	            0x19800000: 0x40000010,
	            0x1a800000: 0x40004010,
	            0x1b800000: 0x80010,
	            0x1c800000: 0x0,
	            0x1d800000: 0x4010,
	            0x1e800000: 0x40080010,
	            0x1f800000: 0x84000
	        },
	        {
	            0x0: 0x104,
	            0x100000: 0x0,
	            0x200000: 0x4000100,
	            0x300000: 0x10104,
	            0x400000: 0x10004,
	            0x500000: 0x4000004,
	            0x600000: 0x4010104,
	            0x700000: 0x4010000,
	            0x800000: 0x4000000,
	            0x900000: 0x4010100,
	            0xa00000: 0x10100,
	            0xb00000: 0x4010004,
	            0xc00000: 0x4000104,
	            0xd00000: 0x10000,
	            0xe00000: 0x4,
	            0xf00000: 0x100,
	            0x80000: 0x4010100,
	            0x180000: 0x4010004,
	            0x280000: 0x0,
	            0x380000: 0x4000100,
	            0x480000: 0x4000004,
	            0x580000: 0x10000,
	            0x680000: 0x10004,
	            0x780000: 0x104,
	            0x880000: 0x4,
	            0x980000: 0x100,
	            0xa80000: 0x4010000,
	            0xb80000: 0x10104,
	            0xc80000: 0x10100,
	            0xd80000: 0x4000104,
	            0xe80000: 0x4010104,
	            0xf80000: 0x4000000,
	            0x1000000: 0x4010100,
	            0x1100000: 0x10004,
	            0x1200000: 0x10000,
	            0x1300000: 0x4000100,
	            0x1400000: 0x100,
	            0x1500000: 0x4010104,
	            0x1600000: 0x4000004,
	            0x1700000: 0x0,
	            0x1800000: 0x4000104,
	            0x1900000: 0x4000000,
	            0x1a00000: 0x4,
	            0x1b00000: 0x10100,
	            0x1c00000: 0x4010000,
	            0x1d00000: 0x104,
	            0x1e00000: 0x10104,
	            0x1f00000: 0x4010004,
	            0x1080000: 0x4000000,
	            0x1180000: 0x104,
	            0x1280000: 0x4010100,
	            0x1380000: 0x0,
	            0x1480000: 0x10004,
	            0x1580000: 0x4000100,
	            0x1680000: 0x100,
	            0x1780000: 0x4010004,
	            0x1880000: 0x10000,
	            0x1980000: 0x4010104,
	            0x1a80000: 0x10104,
	            0x1b80000: 0x4000004,
	            0x1c80000: 0x4000104,
	            0x1d80000: 0x4010000,
	            0x1e80000: 0x4,
	            0x1f80000: 0x10100
	        },
	        {
	            0x0: 0x80401000,
	            0x10000: 0x80001040,
	            0x20000: 0x401040,
	            0x30000: 0x80400000,
	            0x40000: 0x0,
	            0x50000: 0x401000,
	            0x60000: 0x80000040,
	            0x70000: 0x400040,
	            0x80000: 0x80000000,
	            0x90000: 0x400000,
	            0xa0000: 0x40,
	            0xb0000: 0x80001000,
	            0xc0000: 0x80400040,
	            0xd0000: 0x1040,
	            0xe0000: 0x1000,
	            0xf0000: 0x80401040,
	            0x8000: 0x80001040,
	            0x18000: 0x40,
	            0x28000: 0x80400040,
	            0x38000: 0x80001000,
	            0x48000: 0x401000,
	            0x58000: 0x80401040,
	            0x68000: 0x0,
	            0x78000: 0x80400000,
	            0x88000: 0x1000,
	            0x98000: 0x80401000,
	            0xa8000: 0x400000,
	            0xb8000: 0x1040,
	            0xc8000: 0x80000000,
	            0xd8000: 0x400040,
	            0xe8000: 0x401040,
	            0xf8000: 0x80000040,
	            0x100000: 0x400040,
	            0x110000: 0x401000,
	            0x120000: 0x80000040,
	            0x130000: 0x0,
	            0x140000: 0x1040,
	            0x150000: 0x80400040,
	            0x160000: 0x80401000,
	            0x170000: 0x80001040,
	            0x180000: 0x80401040,
	            0x190000: 0x80000000,
	            0x1a0000: 0x80400000,
	            0x1b0000: 0x401040,
	            0x1c0000: 0x80001000,
	            0x1d0000: 0x400000,
	            0x1e0000: 0x40,
	            0x1f0000: 0x1000,
	            0x108000: 0x80400000,
	            0x118000: 0x80401040,
	            0x128000: 0x0,
	            0x138000: 0x401000,
	            0x148000: 0x400040,
	            0x158000: 0x80000000,
	            0x168000: 0x80001040,
	            0x178000: 0x40,
	            0x188000: 0x80000040,
	            0x198000: 0x1000,
	            0x1a8000: 0x80001000,
	            0x1b8000: 0x80400040,
	            0x1c8000: 0x1040,
	            0x1d8000: 0x80401000,
	            0x1e8000: 0x400000,
	            0x1f8000: 0x401040
	        },
	        {
	            0x0: 0x80,
	            0x1000: 0x1040000,
	            0x2000: 0x40000,
	            0x3000: 0x20000000,
	            0x4000: 0x20040080,
	            0x5000: 0x1000080,
	            0x6000: 0x21000080,
	            0x7000: 0x40080,
	            0x8000: 0x1000000,
	            0x9000: 0x20040000,
	            0xa000: 0x20000080,
	            0xb000: 0x21040080,
	            0xc000: 0x21040000,
	            0xd000: 0x0,
	            0xe000: 0x1040080,
	            0xf000: 0x21000000,
	            0x800: 0x1040080,
	            0x1800: 0x21000080,
	            0x2800: 0x80,
	            0x3800: 0x1040000,
	            0x4800: 0x40000,
	            0x5800: 0x20040080,
	            0x6800: 0x21040000,
	            0x7800: 0x20000000,
	            0x8800: 0x20040000,
	            0x9800: 0x0,
	            0xa800: 0x21040080,
	            0xb800: 0x1000080,
	            0xc800: 0x20000080,
	            0xd800: 0x21000000,
	            0xe800: 0x1000000,
	            0xf800: 0x40080,
	            0x10000: 0x40000,
	            0x11000: 0x80,
	            0x12000: 0x20000000,
	            0x13000: 0x21000080,
	            0x14000: 0x1000080,
	            0x15000: 0x21040000,
	            0x16000: 0x20040080,
	            0x17000: 0x1000000,
	            0x18000: 0x21040080,
	            0x19000: 0x21000000,
	            0x1a000: 0x1040000,
	            0x1b000: 0x20040000,
	            0x1c000: 0x40080,
	            0x1d000: 0x20000080,
	            0x1e000: 0x0,
	            0x1f000: 0x1040080,
	            0x10800: 0x21000080,
	            0x11800: 0x1000000,
	            0x12800: 0x1040000,
	            0x13800: 0x20040080,
	            0x14800: 0x20000000,
	            0x15800: 0x1040080,
	            0x16800: 0x80,
	            0x17800: 0x21040000,
	            0x18800: 0x40080,
	            0x19800: 0x21040080,
	            0x1a800: 0x0,
	            0x1b800: 0x21000000,
	            0x1c800: 0x1000080,
	            0x1d800: 0x40000,
	            0x1e800: 0x20040000,
	            0x1f800: 0x20000080
	        },
	        {
	            0x0: 0x10000008,
	            0x100: 0x2000,
	            0x200: 0x10200000,
	            0x300: 0x10202008,
	            0x400: 0x10002000,
	            0x500: 0x200000,
	            0x600: 0x200008,
	            0x700: 0x10000000,
	            0x800: 0x0,
	            0x900: 0x10002008,
	            0xa00: 0x202000,
	            0xb00: 0x8,
	            0xc00: 0x10200008,
	            0xd00: 0x202008,
	            0xe00: 0x2008,
	            0xf00: 0x10202000,
	            0x80: 0x10200000,
	            0x180: 0x10202008,
	            0x280: 0x8,
	            0x380: 0x200000,
	            0x480: 0x202008,
	            0x580: 0x10000008,
	            0x680: 0x10002000,
	            0x780: 0x2008,
	            0x880: 0x200008,
	            0x980: 0x2000,
	            0xa80: 0x10002008,
	            0xb80: 0x10200008,
	            0xc80: 0x0,
	            0xd80: 0x10202000,
	            0xe80: 0x202000,
	            0xf80: 0x10000000,
	            0x1000: 0x10002000,
	            0x1100: 0x10200008,
	            0x1200: 0x10202008,
	            0x1300: 0x2008,
	            0x1400: 0x200000,
	            0x1500: 0x10000000,
	            0x1600: 0x10000008,
	            0x1700: 0x202000,
	            0x1800: 0x202008,
	            0x1900: 0x0,
	            0x1a00: 0x8,
	            0x1b00: 0x10200000,
	            0x1c00: 0x2000,
	            0x1d00: 0x10002008,
	            0x1e00: 0x10202000,
	            0x1f00: 0x200008,
	            0x1080: 0x8,
	            0x1180: 0x202000,
	            0x1280: 0x200000,
	            0x1380: 0x10000008,
	            0x1480: 0x10002000,
	            0x1580: 0x2008,
	            0x1680: 0x10202008,
	            0x1780: 0x10200000,
	            0x1880: 0x10202000,
	            0x1980: 0x10200008,
	            0x1a80: 0x2000,
	            0x1b80: 0x202008,
	            0x1c80: 0x200008,
	            0x1d80: 0x0,
	            0x1e80: 0x10000000,
	            0x1f80: 0x10002008
	        },
	        {
	            0x0: 0x100000,
	            0x10: 0x2000401,
	            0x20: 0x400,
	            0x30: 0x100401,
	            0x40: 0x2100401,
	            0x50: 0x0,
	            0x60: 0x1,
	            0x70: 0x2100001,
	            0x80: 0x2000400,
	            0x90: 0x100001,
	            0xa0: 0x2000001,
	            0xb0: 0x2100400,
	            0xc0: 0x2100000,
	            0xd0: 0x401,
	            0xe0: 0x100400,
	            0xf0: 0x2000000,
	            0x8: 0x2100001,
	            0x18: 0x0,
	            0x28: 0x2000401,
	            0x38: 0x2100400,
	            0x48: 0x100000,
	            0x58: 0x2000001,
	            0x68: 0x2000000,
	            0x78: 0x401,
	            0x88: 0x100401,
	            0x98: 0x2000400,
	            0xa8: 0x2100000,
	            0xb8: 0x100001,
	            0xc8: 0x400,
	            0xd8: 0x2100401,
	            0xe8: 0x1,
	            0xf8: 0x100400,
	            0x100: 0x2000000,
	            0x110: 0x100000,
	            0x120: 0x2000401,
	            0x130: 0x2100001,
	            0x140: 0x100001,
	            0x150: 0x2000400,
	            0x160: 0x2100400,
	            0x170: 0x100401,
	            0x180: 0x401,
	            0x190: 0x2100401,
	            0x1a0: 0x100400,
	            0x1b0: 0x1,
	            0x1c0: 0x0,
	            0x1d0: 0x2100000,
	            0x1e0: 0x2000001,
	            0x1f0: 0x400,
	            0x108: 0x100400,
	            0x118: 0x2000401,
	            0x128: 0x2100001,
	            0x138: 0x1,
	            0x148: 0x2000000,
	            0x158: 0x100000,
	            0x168: 0x401,
	            0x178: 0x2100400,
	            0x188: 0x2000001,
	            0x198: 0x2100000,
	            0x1a8: 0x0,
	            0x1b8: 0x2100401,
	            0x1c8: 0x100401,
	            0x1d8: 0x400,
	            0x1e8: 0x2000400,
	            0x1f8: 0x100001
	        },
	        {
	            0x0: 0x8000820,
	            0x1: 0x20000,
	            0x2: 0x8000000,
	            0x3: 0x20,
	            0x4: 0x20020,
	            0x5: 0x8020820,
	            0x6: 0x8020800,
	            0x7: 0x800,
	            0x8: 0x8020000,
	            0x9: 0x8000800,
	            0xa: 0x20800,
	            0xb: 0x8020020,
	            0xc: 0x820,
	            0xd: 0x0,
	            0xe: 0x8000020,
	            0xf: 0x20820,
	            0x80000000: 0x800,
	            0x80000001: 0x8020820,
	            0x80000002: 0x8000820,
	            0x80000003: 0x8000000,
	            0x80000004: 0x8020000,
	            0x80000005: 0x20800,
	            0x80000006: 0x20820,
	            0x80000007: 0x20,
	            0x80000008: 0x8000020,
	            0x80000009: 0x820,
	            0x8000000a: 0x20020,
	            0x8000000b: 0x8020800,
	            0x8000000c: 0x0,
	            0x8000000d: 0x8020020,
	            0x8000000e: 0x8000800,
	            0x8000000f: 0x20000,
	            0x10: 0x20820,
	            0x11: 0x8020800,
	            0x12: 0x20,
	            0x13: 0x800,
	            0x14: 0x8000800,
	            0x15: 0x8000020,
	            0x16: 0x8020020,
	            0x17: 0x20000,
	            0x18: 0x0,
	            0x19: 0x20020,
	            0x1a: 0x8020000,
	            0x1b: 0x8000820,
	            0x1c: 0x8020820,
	            0x1d: 0x20800,
	            0x1e: 0x820,
	            0x1f: 0x8000000,
	            0x80000010: 0x20000,
	            0x80000011: 0x800,
	            0x80000012: 0x8020020,
	            0x80000013: 0x20820,
	            0x80000014: 0x20,
	            0x80000015: 0x8020000,
	            0x80000016: 0x8000000,
	            0x80000017: 0x8000820,
	            0x80000018: 0x8020820,
	            0x80000019: 0x8000020,
	            0x8000001a: 0x8000800,
	            0x8000001b: 0x0,
	            0x8000001c: 0x20800,
	            0x8000001d: 0x820,
	            0x8000001e: 0x20020,
	            0x8000001f: 0x8020800
	        }
	    ];

	    // Masks that select the SBOX input
	    var SBOX_MASK = [
	        0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000,
	        0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f
	    ];

	    /**
	     * DES block cipher algorithm.
	     */
	    var DES = C_algo.DES = BlockCipher.extend({
	        _doReset: function () {
	            // Shortcuts
	            var key = this._key;
	            var keyWords = key.words;

	            // Select 56 bits according to PC1
	            var keyBits = [];
	            for (var i = 0; i < 56; i++) {
	                var keyBitPos = PC1[i] - 1;
	                keyBits[i] = (keyWords[keyBitPos >>> 5] >>> (31 - keyBitPos % 32)) & 1;
	            }

	            // Assemble 16 subkeys
	            var subKeys = this._subKeys = [];
	            for (var nSubKey = 0; nSubKey < 16; nSubKey++) {
	                // Create subkey
	                var subKey = subKeys[nSubKey] = [];

	                // Shortcut
	                var bitShift = BIT_SHIFTS[nSubKey];

	                // Select 48 bits according to PC2
	                for (var i = 0; i < 24; i++) {
	                    // Select from the left 28 key bits
	                    subKey[(i / 6) | 0] |= keyBits[((PC2[i] - 1) + bitShift) % 28] << (31 - i % 6);

	                    // Select from the right 28 key bits
	                    subKey[4 + ((i / 6) | 0)] |= keyBits[28 + (((PC2[i + 24] - 1) + bitShift) % 28)] << (31 - i % 6);
	                }

	                // Since each subkey is applied to an expanded 32-bit input,
	                // the subkey can be broken into 8 values scaled to 32-bits,
	                // which allows the key to be used without expansion
	                subKey[0] = (subKey[0] << 1) | (subKey[0] >>> 31);
	                for (var i = 1; i < 7; i++) {
	                    subKey[i] = subKey[i] >>> ((i - 1) * 4 + 3);
	                }
	                subKey[7] = (subKey[7] << 5) | (subKey[7] >>> 27);
	            }

	            // Compute inverse subkeys
	            var invSubKeys = this._invSubKeys = [];
	            for (var i = 0; i < 16; i++) {
	                invSubKeys[i] = subKeys[15 - i];
	            }
	        },

	        encryptBlock: function (M, offset) {
	            this._doCryptBlock(M, offset, this._subKeys);
	        },

	        decryptBlock: function (M, offset) {
	            this._doCryptBlock(M, offset, this._invSubKeys);
	        },

	        _doCryptBlock: function (M, offset, subKeys) {
	            // Get input
	            this._lBlock = M[offset];
	            this._rBlock = M[offset + 1];

	            // Initial permutation
	            exchangeLR.call(this, 4,  0x0f0f0f0f);
	            exchangeLR.call(this, 16, 0x0000ffff);
	            exchangeRL.call(this, 2,  0x33333333);
	            exchangeRL.call(this, 8,  0x00ff00ff);
	            exchangeLR.call(this, 1,  0x55555555);

	            // Rounds
	            for (var round = 0; round < 16; round++) {
	                // Shortcuts
	                var subKey = subKeys[round];
	                var lBlock = this._lBlock;
	                var rBlock = this._rBlock;

	                // Feistel function
	                var f = 0;
	                for (var i = 0; i < 8; i++) {
	                    f |= SBOX_P[i][((rBlock ^ subKey[i]) & SBOX_MASK[i]) >>> 0];
	                }
	                this._lBlock = rBlock;
	                this._rBlock = lBlock ^ f;
	            }

	            // Undo swap from last round
	            var t = this._lBlock;
	            this._lBlock = this._rBlock;
	            this._rBlock = t;

	            // Final permutation
	            exchangeLR.call(this, 1,  0x55555555);
	            exchangeRL.call(this, 8,  0x00ff00ff);
	            exchangeRL.call(this, 2,  0x33333333);
	            exchangeLR.call(this, 16, 0x0000ffff);
	            exchangeLR.call(this, 4,  0x0f0f0f0f);

	            // Set output
	            M[offset] = this._lBlock;
	            M[offset + 1] = this._rBlock;
	        },

	        keySize: 64/32,

	        ivSize: 64/32,

	        blockSize: 64/32
	    });

	    // Swap bits across the left and right words
	    function exchangeLR(offset, mask) {
	        var t = ((this._lBlock >>> offset) ^ this._rBlock) & mask;
	        this._rBlock ^= t;
	        this._lBlock ^= t << offset;
	    }

	    function exchangeRL(offset, mask) {
	        var t = ((this._rBlock >>> offset) ^ this._lBlock) & mask;
	        this._lBlock ^= t;
	        this._rBlock ^= t << offset;
	    }

	    /**
	     * Shortcut functions to the cipher's object interface.
	     *
	     * @example
	     *
	     *     var ciphertext = CryptoJS.DES.encrypt(message, key, cfg);
	     *     var plaintext  = CryptoJS.DES.decrypt(ciphertext, key, cfg);
	     */
	    C.DES = BlockCipher._createHelper(DES);

	    /**
	     * Triple-DES block cipher algorithm.
	     */
	    var TripleDES = C_algo.TripleDES = BlockCipher.extend({
	        _doReset: function () {
	            // Shortcuts
	            var key = this._key;
	            var keyWords = key.words;
	            // Make sure the key length is valid (64, 128 or >= 192 bit)
	            if (keyWords.length !== 2 && keyWords.length !== 4 && keyWords.length < 6) {
	                throw new Error('Invalid key length - 3DES requires the key length to be 64, 128, 192 or >192.');
	            }

	            // Extend the key according to the keying options defined in 3DES standard
	            var key1 = keyWords.slice(0, 2);
	            var key2 = keyWords.length < 4 ? keyWords.slice(0, 2) : keyWords.slice(2, 4);
	            var key3 = keyWords.length < 6 ? keyWords.slice(0, 2) : keyWords.slice(4, 6);

	            // Create DES instances
	            this._des1 = DES.createEncryptor(WordArray.create(key1));
	            this._des2 = DES.createEncryptor(WordArray.create(key2));
	            this._des3 = DES.createEncryptor(WordArray.create(key3));
	        },

	        encryptBlock: function (M, offset) {
	            this._des1.encryptBlock(M, offset);
	            this._des2.decryptBlock(M, offset);
	            this._des3.encryptBlock(M, offset);
	        },

	        decryptBlock: function (M, offset) {
	            this._des3.decryptBlock(M, offset);
	            this._des2.encryptBlock(M, offset);
	            this._des1.decryptBlock(M, offset);
	        },

	        keySize: 192/32,

	        ivSize: 64/32,

	        blockSize: 64/32
	    });

	    /**
	     * Shortcut functions to the cipher's object interface.
	     *
	     * @example
	     *
	     *     var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg);
	     *     var plaintext  = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg);
	     */
	    C.TripleDES = BlockCipher._createHelper(TripleDES);
	}());


	return CryptoJS.TripleDES;

}));

/***/ }),

/***/ "./node_modules/crypto-js/x64-core.js":
/*!********************************************!*\
  !*** ./node_modules/crypto-js/x64-core.js ***!
  \********************************************/
/***/ (function(module, exports, __webpack_require__) {

;(function (root, factory) {
	if (true) {
		// CommonJS
		module.exports = exports = factory(__webpack_require__(/*! ./core */ "./node_modules/crypto-js/core.js"));
	}
	else {}
}(this, function (CryptoJS) {

	(function (undefined) {
	    // Shortcuts
	    var C = CryptoJS;
	    var C_lib = C.lib;
	    var Base = C_lib.Base;
	    var X32WordArray = C_lib.WordArray;

	    /**
	     * x64 namespace.
	     */
	    var C_x64 = C.x64 = {};

	    /**
	     * A 64-bit word.
	     */
	    var X64Word = C_x64.Word = Base.extend({
	        /**
	         * Initializes a newly created 64-bit word.
	         *
	         * @param {number} high The high 32 bits.
	         * @param {number} low The low 32 bits.
	         *
	         * @example
	         *
	         *     var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607);
	         */
	        init: function (high, low) {
	            this.high = high;
	            this.low = low;
	        }

	        /**
	         * Bitwise NOTs this word.
	         *
	         * @return {X64Word} A new x64-Word object after negating.
	         *
	         * @example
	         *
	         *     var negated = x64Word.not();
	         */
	        // not: function () {
	            // var high = ~this.high;
	            // var low = ~this.low;

	            // return X64Word.create(high, low);
	        // },

	        /**
	         * Bitwise ANDs this word with the passed word.
	         *
	         * @param {X64Word} word The x64-Word to AND with this word.
	         *
	         * @return {X64Word} A new x64-Word object after ANDing.
	         *
	         * @example
	         *
	         *     var anded = x64Word.and(anotherX64Word);
	         */
	        // and: function (word) {
	            // var high = this.high & word.high;
	            // var low = this.low & word.low;

	            // return X64Word.create(high, low);
	        // },

	        /**
	         * Bitwise ORs this word with the passed word.
	         *
	         * @param {X64Word} word The x64-Word to OR with this word.
	         *
	         * @return {X64Word} A new x64-Word object after ORing.
	         *
	         * @example
	         *
	         *     var ored = x64Word.or(anotherX64Word);
	         */
	        // or: function (word) {
	            // var high = this.high | word.high;
	            // var low = this.low | word.low;

	            // return X64Word.create(high, low);
	        // },

	        /**
	         * Bitwise XORs this word with the passed word.
	         *
	         * @param {X64Word} word The x64-Word to XOR with this word.
	         *
	         * @return {X64Word} A new x64-Word object after XORing.
	         *
	         * @example
	         *
	         *     var xored = x64Word.xor(anotherX64Word);
	         */
	        // xor: function (word) {
	            // var high = this.high ^ word.high;
	            // var low = this.low ^ word.low;

	            // return X64Word.create(high, low);
	        // },

	        /**
	         * Shifts this word n bits to the left.
	         *
	         * @param {number} n The number of bits to shift.
	         *
	         * @return {X64Word} A new x64-Word object after shifting.
	         *
	         * @example
	         *
	         *     var shifted = x64Word.shiftL(25);
	         */
	        // shiftL: function (n) {
	            // if (n < 32) {
	                // var high = (this.high << n) | (this.low >>> (32 - n));
	                // var low = this.low << n;
	            // } else {
	                // var high = this.low << (n - 32);
	                // var low = 0;
	            // }

	            // return X64Word.create(high, low);
	        // },

	        /**
	         * Shifts this word n bits to the right.
	         *
	         * @param {number} n The number of bits to shift.
	         *
	         * @return {X64Word} A new x64-Word object after shifting.
	         *
	         * @example
	         *
	         *     var shifted = x64Word.shiftR(7);
	         */
	        // shiftR: function (n) {
	            // if (n < 32) {
	                // var low = (this.low >>> n) | (this.high << (32 - n));
	                // var high = this.high >>> n;
	            // } else {
	                // var low = this.high >>> (n - 32);
	                // var high = 0;
	            // }

	            // return X64Word.create(high, low);
	        // },

	        /**
	         * Rotates this word n bits to the left.
	         *
	         * @param {number} n The number of bits to rotate.
	         *
	         * @return {X64Word} A new x64-Word object after rotating.
	         *
	         * @example
	         *
	         *     var rotated = x64Word.rotL(25);
	         */
	        // rotL: function (n) {
	            // return this.shiftL(n).or(this.shiftR(64 - n));
	        // },

	        /**
	         * Rotates this word n bits to the right.
	         *
	         * @param {number} n The number of bits to rotate.
	         *
	         * @return {X64Word} A new x64-Word object after rotating.
	         *
	         * @example
	         *
	         *     var rotated = x64Word.rotR(7);
	         */
	        // rotR: function (n) {
	            // return this.shiftR(n).or(this.shiftL(64 - n));
	        // },

	        /**
	         * Adds this word with the passed word.
	         *
	         * @param {X64Word} word The x64-Word to add with this word.
	         *
	         * @return {X64Word} A new x64-Word object after adding.
	         *
	         * @example
	         *
	         *     var added = x64Word.add(anotherX64Word);
	         */
	        // add: function (word) {
	            // var low = (this.low + word.low) | 0;
	            // var carry = (low >>> 0) < (this.low >>> 0) ? 1 : 0;
	            // var high = (this.high + word.high + carry) | 0;

	            // return X64Word.create(high, low);
	        // }
	    });

	    /**
	     * An array of 64-bit words.
	     *
	     * @property {Array} words The array of CryptoJS.x64.Word objects.
	     * @property {number} sigBytes The number of significant bytes in this word array.
	     */
	    var X64WordArray = C_x64.WordArray = Base.extend({
	        /**
	         * Initializes a newly created word array.
	         *
	         * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects.
	         * @param {number} sigBytes (Optional) The number of significant bytes in the words.
	         *
	         * @example
	         *
	         *     var wordArray = CryptoJS.x64.WordArray.create();
	         *
	         *     var wordArray = CryptoJS.x64.WordArray.create([
	         *         CryptoJS.x64.Word.create(0x00010203, 0x04050607),
	         *         CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f)
	         *     ]);
	         *
	         *     var wordArray = CryptoJS.x64.WordArray.create([
	         *         CryptoJS.x64.Word.create(0x00010203, 0x04050607),
	         *         CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f)
	         *     ], 10);
	         */
	        init: function (words, sigBytes) {
	            words = this.words = words || [];

	            if (sigBytes != undefined) {
	                this.sigBytes = sigBytes;
	            } else {
	                this.sigBytes = words.length * 8;
	            }
	        },

	        /**
	         * Converts this 64-bit word array to a 32-bit word array.
	         *
	         * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array.
	         *
	         * @example
	         *
	         *     var x32WordArray = x64WordArray.toX32();
	         */
	        toX32: function () {
	            // Shortcuts
	            var x64Words = this.words;
	            var x64WordsLength = x64Words.length;

	            // Convert
	            var x32Words = [];
	            for (var i = 0; i < x64WordsLength; i++) {
	                var x64Word = x64Words[i];
	                x32Words.push(x64Word.high);
	                x32Words.push(x64Word.low);
	            }

	            return X32WordArray.create(x32Words, this.sigBytes);
	        },

	        /**
	         * Creates a copy of this word array.
	         *
	         * @return {X64WordArray} The clone.
	         *
	         * @example
	         *
	         *     var clone = x64WordArray.clone();
	         */
	        clone: function () {
	            var clone = Base.clone.call(this);

	            // Clone "words" array
	            var words = clone.words = this.words.slice(0);

	            // Clone each X64Word object
	            var wordsLength = words.length;
	            for (var i = 0; i < wordsLength; i++) {
	                words[i] = words[i].clone();
	            }

	            return clone;
	        }
	    });
	}());


	return CryptoJS;

}));

/***/ }),

/***/ "./node_modules/jsqr/dist/jsQR.js":
/*!****************************************!*\
  !*** ./node_modules/jsqr/dist/jsQR.js ***!
  \****************************************/
/***/ (function(module) {

(function webpackUniversalModuleDefinition(root, factory) {
	if(true)
		module.exports = factory();
	else {}
})(typeof self !== 'undefined' ? self : this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __nested_webpack_require_568__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __nested_webpack_require_568__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__nested_webpack_require_568__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__nested_webpack_require_568__.c = installedModules;
/******/
/******/ 	// define getter function for harmony exports
/******/ 	__nested_webpack_require_568__.d = function(exports, name, getter) {
/******/ 		if(!__nested_webpack_require_568__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, {
/******/ 				configurable: false,
/******/ 				enumerable: true,
/******/ 				get: getter
/******/ 			});
/******/ 		}
/******/ 	};
/******/
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__nested_webpack_require_568__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__nested_webpack_require_568__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};
/******/
/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__nested_webpack_require_568__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__nested_webpack_require_568__.p = "";
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __nested_webpack_require_568__(__nested_webpack_require_568__.s = 3);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var BitMatrix = /** @class */ (function () {
    function BitMatrix(data, width) {
        this.width = width;
        this.height = data.length / width;
        this.data = data;
    }
    BitMatrix.createEmpty = function (width, height) {
        return new BitMatrix(new Uint8ClampedArray(width * height), width);
    };
    BitMatrix.prototype.get = function (x, y) {
        if (x < 0 || x >= this.width || y < 0 || y >= this.height) {
            return false;
        }
        return !!this.data[y * this.width + x];
    };
    BitMatrix.prototype.set = function (x, y, v) {
        this.data[y * this.width + x] = v ? 1 : 0;
    };
    BitMatrix.prototype.setRegion = function (left, top, width, height, v) {
        for (var y = top; y < top + height; y++) {
            for (var x = left; x < left + width; x++) {
                this.set(x, y, !!v);
            }
        }
    };
    return BitMatrix;
}());
exports.BitMatrix = BitMatrix;


/***/ }),
/* 1 */
/***/ (function(module, exports, __nested_webpack_require_3952__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var GenericGFPoly_1 = __nested_webpack_require_3952__(2);
function addOrSubtractGF(a, b) {
    return a ^ b; // tslint:disable-line:no-bitwise
}
exports.addOrSubtractGF = addOrSubtractGF;
var GenericGF = /** @class */ (function () {
    function GenericGF(primitive, size, genBase) {
        this.primitive = primitive;
        this.size = size;
        this.generatorBase = genBase;
        this.expTable = new Array(this.size);
        this.logTable = new Array(this.size);
        var x = 1;
        for (var i = 0; i < this.size; i++) {
            this.expTable[i] = x;
            x = x * 2;
            if (x >= this.size) {
                x = (x ^ this.primitive) & (this.size - 1); // tslint:disable-line:no-bitwise
            }
        }
        for (var i = 0; i < this.size - 1; i++) {
            this.logTable[this.expTable[i]] = i;
        }
        this.zero = new GenericGFPoly_1.default(this, Uint8ClampedArray.from([0]));
        this.one = new GenericGFPoly_1.default(this, Uint8ClampedArray.from([1]));
    }
    GenericGF.prototype.multiply = function (a, b) {
        if (a === 0 || b === 0) {
            return 0;
        }
        return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.size - 1)];
    };
    GenericGF.prototype.inverse = function (a) {
        if (a === 0) {
            throw new Error("Can't invert 0");
        }
        return this.expTable[this.size - this.logTable[a] - 1];
    };
    GenericGF.prototype.buildMonomial = function (degree, coefficient) {
        if (degree < 0) {
            throw new Error("Invalid monomial degree less than 0");
        }
        if (coefficient === 0) {
            return this.zero;
        }
        var coefficients = new Uint8ClampedArray(degree + 1);
        coefficients[0] = coefficient;
        return new GenericGFPoly_1.default(this, coefficients);
    };
    GenericGF.prototype.log = function (a) {
        if (a === 0) {
            throw new Error("Can't take log(0)");
        }
        return this.logTable[a];
    };
    GenericGF.prototype.exp = function (a) {
        return this.expTable[a];
    };
    return GenericGF;
}());
exports.default = GenericGF;


/***/ }),
/* 2 */
/***/ (function(module, exports, __nested_webpack_require_6272__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var GenericGF_1 = __nested_webpack_require_6272__(1);
var GenericGFPoly = /** @class */ (function () {
    function GenericGFPoly(field, coefficients) {
        if (coefficients.length === 0) {
            throw new Error("No coefficients.");
        }
        this.field = field;
        var coefficientsLength = coefficients.length;
        if (coefficientsLength > 1 && coefficients[0] === 0) {
            // Leading term must be non-zero for anything except the constant polynomial "0"
            var firstNonZero = 1;
            while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) {
                firstNonZero++;
            }
            if (firstNonZero === coefficientsLength) {
                this.coefficients = field.zero.coefficients;
            }
            else {
                this.coefficients = new Uint8ClampedArray(coefficientsLength - firstNonZero);
                for (var i = 0; i < this.coefficients.length; i++) {
                    this.coefficients[i] = coefficients[firstNonZero + i];
                }
            }
        }
        else {
            this.coefficients = coefficients;
        }
    }
    GenericGFPoly.prototype.degree = function () {
        return this.coefficients.length - 1;
    };
    GenericGFPoly.prototype.isZero = function () {
        return this.coefficients[0] === 0;
    };
    GenericGFPoly.prototype.getCoefficient = function (degree) {
        return this.coefficients[this.coefficients.length - 1 - degree];
    };
    GenericGFPoly.prototype.addOrSubtract = function (other) {
        var _a;
        if (this.isZero()) {
            return other;
        }
        if (other.isZero()) {
            return this;
        }
        var smallerCoefficients = this.coefficients;
        var largerCoefficients = other.coefficients;
        if (smallerCoefficients.length > largerCoefficients.length) {
            _a = [largerCoefficients, smallerCoefficients], smallerCoefficients = _a[0], largerCoefficients = _a[1];
        }
        var sumDiff = new Uint8ClampedArray(largerCoefficients.length);
        var lengthDiff = largerCoefficients.length - smallerCoefficients.length;
        for (var i = 0; i < lengthDiff; i++) {
            sumDiff[i] = largerCoefficients[i];
        }
        for (var i = lengthDiff; i < largerCoefficients.length; i++) {
            sumDiff[i] = GenericGF_1.addOrSubtractGF(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);
        }
        return new GenericGFPoly(this.field, sumDiff);
    };
    GenericGFPoly.prototype.multiply = function (scalar) {
        if (scalar === 0) {
            return this.field.zero;
        }
        if (scalar === 1) {
            return this;
        }
        var size = this.coefficients.length;
        var product = new Uint8ClampedArray(size);
        for (var i = 0; i < size; i++) {
            product[i] = this.field.multiply(this.coefficients[i], scalar);
        }
        return new GenericGFPoly(this.field, product);
    };
    GenericGFPoly.prototype.multiplyPoly = function (other) {
        if (this.isZero() || other.isZero()) {
            return this.field.zero;
        }
        var aCoefficients = this.coefficients;
        var aLength = aCoefficients.length;
        var bCoefficients = other.coefficients;
        var bLength = bCoefficients.length;
        var product = new Uint8ClampedArray(aLength + bLength - 1);
        for (var i = 0; i < aLength; i++) {
            var aCoeff = aCoefficients[i];
            for (var j = 0; j < bLength; j++) {
                product[i + j] = GenericGF_1.addOrSubtractGF(product[i + j], this.field.multiply(aCoeff, bCoefficients[j]));
            }
        }
        return new GenericGFPoly(this.field, product);
    };
    GenericGFPoly.prototype.multiplyByMonomial = function (degree, coefficient) {
        if (degree < 0) {
            throw new Error("Invalid degree less than 0");
        }
        if (coefficient === 0) {
            return this.field.zero;
        }
        var size = this.coefficients.length;
        var product = new Uint8ClampedArray(size + degree);
        for (var i = 0; i < size; i++) {
            product[i] = this.field.multiply(this.coefficients[i], coefficient);
        }
        return new GenericGFPoly(this.field, product);
    };
    GenericGFPoly.prototype.evaluateAt = function (a) {
        var result = 0;
        if (a === 0) {
            // Just return the x^0 coefficient
            return this.getCoefficient(0);
        }
        var size = this.coefficients.length;
        if (a === 1) {
            // Just the sum of the coefficients
            this.coefficients.forEach(function (coefficient) {
                result = GenericGF_1.addOrSubtractGF(result, coefficient);
            });
            return result;
        }
        result = this.coefficients[0];
        for (var i = 1; i < size; i++) {
            result = GenericGF_1.addOrSubtractGF(this.field.multiply(a, result), this.coefficients[i]);
        }
        return result;
    };
    return GenericGFPoly;
}());
exports.default = GenericGFPoly;


/***/ }),
/* 3 */
/***/ (function(module, exports, __nested_webpack_require_11547__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var binarizer_1 = __nested_webpack_require_11547__(4);
var decoder_1 = __nested_webpack_require_11547__(5);
var extractor_1 = __nested_webpack_require_11547__(11);
var locator_1 = __nested_webpack_require_11547__(12);
function scan(matrix) {
    var locations = locator_1.locate(matrix);
    if (!locations) {
        return null;
    }
    for (var _i = 0, locations_1 = locations; _i < locations_1.length; _i++) {
        var location_1 = locations_1[_i];
        var extracted = extractor_1.extract(matrix, location_1);
        var decoded = decoder_1.decode(extracted.matrix);
        if (decoded) {
            return {
                binaryData: decoded.bytes,
                data: decoded.text,
                chunks: decoded.chunks,
                version: decoded.version,
                location: {
                    topRightCorner: extracted.mappingFunction(location_1.dimension, 0),
                    topLeftCorner: extracted.mappingFunction(0, 0),
                    bottomRightCorner: extracted.mappingFunction(location_1.dimension, location_1.dimension),
                    bottomLeftCorner: extracted.mappingFunction(0, location_1.dimension),
                    topRightFinderPattern: location_1.topRight,
                    topLeftFinderPattern: location_1.topLeft,
                    bottomLeftFinderPattern: location_1.bottomLeft,
                    bottomRightAlignmentPattern: location_1.alignmentPattern,
                },
            };
        }
    }
    return null;
}
var defaultOptions = {
    inversionAttempts: "attemptBoth",
};
function jsQR(data, width, height, providedOptions) {
    if (providedOptions === void 0) { providedOptions = {}; }
    var options = defaultOptions;
    Object.keys(options || {}).forEach(function (opt) {
        options[opt] = providedOptions[opt] || options[opt];
    });
    var shouldInvert = options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst";
    var tryInvertedFirst = options.inversionAttempts === "onlyInvert" || options.inversionAttempts === "invertFirst";
    var _a = binarizer_1.binarize(data, width, height, shouldInvert), binarized = _a.binarized, inverted = _a.inverted;
    var result = scan(tryInvertedFirst ? inverted : binarized);
    if (!result && (options.inversionAttempts === "attemptBoth" || options.inversionAttempts === "invertFirst")) {
        result = scan(tryInvertedFirst ? binarized : inverted);
    }
    return result;
}
jsQR.default = jsQR;
exports.default = jsQR;


/***/ }),
/* 4 */
/***/ (function(module, exports, __nested_webpack_require_14168__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var BitMatrix_1 = __nested_webpack_require_14168__(0);
var REGION_SIZE = 8;
var MIN_DYNAMIC_RANGE = 24;
function numBetween(value, min, max) {
    return value < min ? min : value > max ? max : value;
}
// Like BitMatrix but accepts arbitry Uint8 values
var Matrix = /** @class */ (function () {
    function Matrix(width, height) {
        this.width = width;
        this.data = new Uint8ClampedArray(width * height);
    }
    Matrix.prototype.get = function (x, y) {
        return this.data[y * this.width + x];
    };
    Matrix.prototype.set = function (x, y, value) {
        this.data[y * this.width + x] = value;
    };
    return Matrix;
}());
function binarize(data, width, height, returnInverted) {
    if (data.length !== width * height * 4) {
        throw new Error("Malformed data passed to binarizer.");
    }
    // Convert image to greyscale
    var greyscalePixels = new Matrix(width, height);
    for (var x = 0; x < width; x++) {
        for (var y = 0; y < height; y++) {
            var r = data[((y * width + x) * 4) + 0];
            var g = data[((y * width + x) * 4) + 1];
            var b = data[((y * width + x) * 4) + 2];
            greyscalePixels.set(x, y, 0.2126 * r + 0.7152 * g + 0.0722 * b);
        }
    }
    var horizontalRegionCount = Math.ceil(width / REGION_SIZE);
    var verticalRegionCount = Math.ceil(height / REGION_SIZE);
    var blackPoints = new Matrix(horizontalRegionCount, verticalRegionCount);
    for (var verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) {
        for (var hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) {
            var sum = 0;
            var min = Infinity;
            var max = 0;
            for (var y = 0; y < REGION_SIZE; y++) {
                for (var x = 0; x < REGION_SIZE; x++) {
                    var pixelLumosity = greyscalePixels.get(hortizontalRegion * REGION_SIZE + x, verticalRegion * REGION_SIZE + y);
                    sum += pixelLumosity;
                    min = Math.min(min, pixelLumosity);
                    max = Math.max(max, pixelLumosity);
                }
            }
            var average = sum / (Math.pow(REGION_SIZE, 2));
            if (max - min <= MIN_DYNAMIC_RANGE) {
                // If variation within the block is low, assume this is a block with only light or only
                // dark pixels. In that case we do not want to use the average, as it would divide this
                // low contrast area into black and white pixels, essentially creating data out of noise.
                //
                // Default the blackpoint for these blocks to be half the min - effectively white them out
                average = min / 2;
                if (verticalRegion > 0 && hortizontalRegion > 0) {
                    // Correct the "white background" assumption for blocks that have neighbors by comparing
                    // the pixels in this block to the previously calculated black points. This is based on
                    // the fact that dark barcode symbology is always surrounded by some amount of light
                    // background for which reasonable black point estimates were made. The bp estimated at
                    // the boundaries is used for the interior.
                    // The (min < bp) is arbitrary but works better than other heuristics that were tried.
                    var averageNeighborBlackPoint = (blackPoints.get(hortizontalRegion, verticalRegion - 1) +
                        (2 * blackPoints.get(hortizontalRegion - 1, verticalRegion)) +
                        blackPoints.get(hortizontalRegion - 1, verticalRegion - 1)) / 4;
                    if (min < averageNeighborBlackPoint) {
                        average = averageNeighborBlackPoint;
                    }
                }
            }
            blackPoints.set(hortizontalRegion, verticalRegion, average);
        }
    }
    var binarized = BitMatrix_1.BitMatrix.createEmpty(width, height);
    var inverted = null;
    if (returnInverted) {
        inverted = BitMatrix_1.BitMatrix.createEmpty(width, height);
    }
    for (var verticalRegion = 0; verticalRegion < verticalRegionCount; verticalRegion++) {
        for (var hortizontalRegion = 0; hortizontalRegion < horizontalRegionCount; hortizontalRegion++) {
            var left = numBetween(hortizontalRegion, 2, horizontalRegionCount - 3);
            var top_1 = numBetween(verticalRegion, 2, verticalRegionCount - 3);
            var sum = 0;
            for (var xRegion = -2; xRegion <= 2; xRegion++) {
                for (var yRegion = -2; yRegion <= 2; yRegion++) {
                    sum += blackPoints.get(left + xRegion, top_1 + yRegion);
                }
            }
            var threshold = sum / 25;
            for (var xRegion = 0; xRegion < REGION_SIZE; xRegion++) {
                for (var yRegion = 0; yRegion < REGION_SIZE; yRegion++) {
                    var x = hortizontalRegion * REGION_SIZE + xRegion;
                    var y = verticalRegion * REGION_SIZE + yRegion;
                    var lum = greyscalePixels.get(x, y);
                    binarized.set(x, y, lum <= threshold);
                    if (returnInverted) {
                        inverted.set(x, y, !(lum <= threshold));
                    }
                }
            }
        }
    }
    if (returnInverted) {
        return { binarized: binarized, inverted: inverted };
    }
    return { binarized: binarized };
}
exports.binarize = binarize;


/***/ }),
/* 5 */
/***/ (function(module, exports, __nested_webpack_require_19864__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var BitMatrix_1 = __nested_webpack_require_19864__(0);
var decodeData_1 = __nested_webpack_require_19864__(6);
var reedsolomon_1 = __nested_webpack_require_19864__(9);
var version_1 = __nested_webpack_require_19864__(10);
// tslint:disable:no-bitwise
function numBitsDiffering(x, y) {
    var z = x ^ y;
    var bitCount = 0;
    while (z) {
        bitCount++;
        z &= z - 1;
    }
    return bitCount;
}
function pushBit(bit, byte) {
    return (byte << 1) | bit;
}
// tslint:enable:no-bitwise
var FORMAT_INFO_TABLE = [
    { bits: 0x5412, formatInfo: { errorCorrectionLevel: 1, dataMask: 0 } },
    { bits: 0x5125, formatInfo: { errorCorrectionLevel: 1, dataMask: 1 } },
    { bits: 0x5E7C, formatInfo: { errorCorrectionLevel: 1, dataMask: 2 } },
    { bits: 0x5B4B, formatInfo: { errorCorrectionLevel: 1, dataMask: 3 } },
    { bits: 0x45F9, formatInfo: { errorCorrectionLevel: 1, dataMask: 4 } },
    { bits: 0x40CE, formatInfo: { errorCorrectionLevel: 1, dataMask: 5 } },
    { bits: 0x4F97, formatInfo: { errorCorrectionLevel: 1, dataMask: 6 } },
    { bits: 0x4AA0, formatInfo: { errorCorrectionLevel: 1, dataMask: 7 } },
    { bits: 0x77C4, formatInfo: { errorCorrectionLevel: 0, dataMask: 0 } },
    { bits: 0x72F3, formatInfo: { errorCorrectionLevel: 0, dataMask: 1 } },
    { bits: 0x7DAA, formatInfo: { errorCorrectionLevel: 0, dataMask: 2 } },
    { bits: 0x789D, formatInfo: { errorCorrectionLevel: 0, dataMask: 3 } },
    { bits: 0x662F, formatInfo: { errorCorrectionLevel: 0, dataMask: 4 } },
    { bits: 0x6318, formatInfo: { errorCorrectionLevel: 0, dataMask: 5 } },
    { bits: 0x6C41, formatInfo: { errorCorrectionLevel: 0, dataMask: 6 } },
    { bits: 0x6976, formatInfo: { errorCorrectionLevel: 0, dataMask: 7 } },
    { bits: 0x1689, formatInfo: { errorCorrectionLevel: 3, dataMask: 0 } },
    { bits: 0x13BE, formatInfo: { errorCorrectionLevel: 3, dataMask: 1 } },
    { bits: 0x1CE7, formatInfo: { errorCorrectionLevel: 3, dataMask: 2 } },
    { bits: 0x19D0, formatInfo: { errorCorrectionLevel: 3, dataMask: 3 } },
    { bits: 0x0762, formatInfo: { errorCorrectionLevel: 3, dataMask: 4 } },
    { bits: 0x0255, formatInfo: { errorCorrectionLevel: 3, dataMask: 5 } },
    { bits: 0x0D0C, formatInfo: { errorCorrectionLevel: 3, dataMask: 6 } },
    { bits: 0x083B, formatInfo: { errorCorrectionLevel: 3, dataMask: 7 } },
    { bits: 0x355F, formatInfo: { errorCorrectionLevel: 2, dataMask: 0 } },
    { bits: 0x3068, formatInfo: { errorCorrectionLevel: 2, dataMask: 1 } },
    { bits: 0x3F31, formatInfo: { errorCorrectionLevel: 2, dataMask: 2 } },
    { bits: 0x3A06, formatInfo: { errorCorrectionLevel: 2, dataMask: 3 } },
    { bits: 0x24B4, formatInfo: { errorCorrectionLevel: 2, dataMask: 4 } },
    { bits: 0x2183, formatInfo: { errorCorrectionLevel: 2, dataMask: 5 } },
    { bits: 0x2EDA, formatInfo: { errorCorrectionLevel: 2, dataMask: 6 } },
    { bits: 0x2BED, formatInfo: { errorCorrectionLevel: 2, dataMask: 7 } },
];
var DATA_MASKS = [
    function (p) { return ((p.y + p.x) % 2) === 0; },
    function (p) { return (p.y % 2) === 0; },
    function (p) { return p.x % 3 === 0; },
    function (p) { return (p.y + p.x) % 3 === 0; },
    function (p) { return (Math.floor(p.y / 2) + Math.floor(p.x / 3)) % 2 === 0; },
    function (p) { return ((p.x * p.y) % 2) + ((p.x * p.y) % 3) === 0; },
    function (p) { return ((((p.y * p.x) % 2) + (p.y * p.x) % 3) % 2) === 0; },
    function (p) { return ((((p.y + p.x) % 2) + (p.y * p.x) % 3) % 2) === 0; },
];
function buildFunctionPatternMask(version) {
    var dimension = 17 + 4 * version.versionNumber;
    var matrix = BitMatrix_1.BitMatrix.createEmpty(dimension, dimension);
    matrix.setRegion(0, 0, 9, 9, true); // Top left finder pattern + separator + format
    matrix.setRegion(dimension - 8, 0, 8, 9, true); // Top right finder pattern + separator + format
    matrix.setRegion(0, dimension - 8, 9, 8, true); // Bottom left finder pattern + separator + format
    // Alignment patterns
    for (var _i = 0, _a = version.alignmentPatternCenters; _i < _a.length; _i++) {
        var x = _a[_i];
        for (var _b = 0, _c = version.alignmentPatternCenters; _b < _c.length; _b++) {
            var y = _c[_b];
            if (!(x === 6 && y === 6 || x === 6 && y === dimension - 7 || x === dimension - 7 && y === 6)) {
                matrix.setRegion(x - 2, y - 2, 5, 5, true);
            }
        }
    }
    matrix.setRegion(6, 9, 1, dimension - 17, true); // Vertical timing pattern
    matrix.setRegion(9, 6, dimension - 17, 1, true); // Horizontal timing pattern
    if (version.versionNumber > 6) {
        matrix.setRegion(dimension - 11, 0, 3, 6, true); // Version info, top right
        matrix.setRegion(0, dimension - 11, 6, 3, true); // Version info, bottom left
    }
    return matrix;
}
function readCodewords(matrix, version, formatInfo) {
    var dataMask = DATA_MASKS[formatInfo.dataMask];
    var dimension = matrix.height;
    var functionPatternMask = buildFunctionPatternMask(version);
    var codewords = [];
    var currentByte = 0;
    var bitsRead = 0;
    // Read columns in pairs, from right to left
    var readingUp = true;
    for (var columnIndex = dimension - 1; columnIndex > 0; columnIndex -= 2) {
        if (columnIndex === 6) { // Skip whole column with vertical alignment pattern;
            columnIndex--;
        }
        for (var i = 0; i < dimension; i++) {
            var y = readingUp ? dimension - 1 - i : i;
            for (var columnOffset = 0; columnOffset < 2; columnOffset++) {
                var x = columnIndex - columnOffset;
                if (!functionPatternMask.get(x, y)) {
                    bitsRead++;
                    var bit = matrix.get(x, y);
                    if (dataMask({ y: y, x: x })) {
                        bit = !bit;
                    }
                    currentByte = pushBit(bit, currentByte);
                    if (bitsRead === 8) { // Whole bytes
                        codewords.push(currentByte);
                        bitsRead = 0;
                        currentByte = 0;
                    }
                }
            }
        }
        readingUp = !readingUp;
    }
    return codewords;
}
function readVersion(matrix) {
    var dimension = matrix.height;
    var provisionalVersion = Math.floor((dimension - 17) / 4);
    if (provisionalVersion <= 6) { // 6 and under dont have version info in the QR code
        return version_1.VERSIONS[provisionalVersion - 1];
    }
    var topRightVersionBits = 0;
    for (var y = 5; y >= 0; y--) {
        for (var x = dimension - 9; x >= dimension - 11; x--) {
            topRightVersionBits = pushBit(matrix.get(x, y), topRightVersionBits);
        }
    }
    var bottomLeftVersionBits = 0;
    for (var x = 5; x >= 0; x--) {
        for (var y = dimension - 9; y >= dimension - 11; y--) {
            bottomLeftVersionBits = pushBit(matrix.get(x, y), bottomLeftVersionBits);
        }
    }
    var bestDifference = Infinity;
    var bestVersion;
    for (var _i = 0, VERSIONS_1 = version_1.VERSIONS; _i < VERSIONS_1.length; _i++) {
        var version = VERSIONS_1[_i];
        if (version.infoBits === topRightVersionBits || version.infoBits === bottomLeftVersionBits) {
            return version;
        }
        var difference = numBitsDiffering(topRightVersionBits, version.infoBits);
        if (difference < bestDifference) {
            bestVersion = version;
            bestDifference = difference;
        }
        difference = numBitsDiffering(bottomLeftVersionBits, version.infoBits);
        if (difference < bestDifference) {
            bestVersion = version;
            bestDifference = difference;
        }
    }
    // We can tolerate up to 3 bits of error since no two version info codewords will
    // differ in less than 8 bits.
    if (bestDifference <= 3) {
        return bestVersion;
    }
}
function readFormatInformation(matrix) {
    var topLeftFormatInfoBits = 0;
    for (var x = 0; x <= 8; x++) {
        if (x !== 6) { // Skip timing pattern bit
            topLeftFormatInfoBits = pushBit(matrix.get(x, 8), topLeftFormatInfoBits);
        }
    }
    for (var y = 7; y >= 0; y--) {
        if (y !== 6) { // Skip timing pattern bit
            topLeftFormatInfoBits = pushBit(matrix.get(8, y), topLeftFormatInfoBits);
        }
    }
    var dimension = matrix.height;
    var topRightBottomRightFormatInfoBits = 0;
    for (var y = dimension - 1; y >= dimension - 7; y--) { // bottom left
        topRightBottomRightFormatInfoBits = pushBit(matrix.get(8, y), topRightBottomRightFormatInfoBits);
    }
    for (var x = dimension - 8; x < dimension; x++) { // top right
        topRightBottomRightFormatInfoBits = pushBit(matrix.get(x, 8), topRightBottomRightFormatInfoBits);
    }
    var bestDifference = Infinity;
    var bestFormatInfo = null;
    for (var _i = 0, FORMAT_INFO_TABLE_1 = FORMAT_INFO_TABLE; _i < FORMAT_INFO_TABLE_1.length; _i++) {
        var _a = FORMAT_INFO_TABLE_1[_i], bits = _a.bits, formatInfo = _a.formatInfo;
        if (bits === topLeftFormatInfoBits || bits === topRightBottomRightFormatInfoBits) {
            return formatInfo;
        }
        var difference = numBitsDiffering(topLeftFormatInfoBits, bits);
        if (difference < bestDifference) {
            bestFormatInfo = formatInfo;
            bestDifference = difference;
        }
        if (topLeftFormatInfoBits !== topRightBottomRightFormatInfoBits) { // also try the other option
            difference = numBitsDiffering(topRightBottomRightFormatInfoBits, bits);
            if (difference < bestDifference) {
                bestFormatInfo = formatInfo;
                bestDifference = difference;
            }
        }
    }
    // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits differing means we found a match
    if (bestDifference <= 3) {
        return bestFormatInfo;
    }
    return null;
}
function getDataBlocks(codewords, version, ecLevel) {
    var ecInfo = version.errorCorrectionLevels[ecLevel];
    var dataBlocks = [];
    var totalCodewords = 0;
    ecInfo.ecBlocks.forEach(function (block) {
        for (var i = 0; i < block.numBlocks; i++) {
            dataBlocks.push({ numDataCodewords: block.dataCodewordsPerBlock, codewords: [] });
            totalCodewords += block.dataCodewordsPerBlock + ecInfo.ecCodewordsPerBlock;
        }
    });
    // In some cases the QR code will be malformed enough that we pull off more or less than we should.
    // If we pull off less there's nothing we can do.
    // If we pull off more we can safely truncate
    if (codewords.length < totalCodewords) {
        return null;
    }
    codewords = codewords.slice(0, totalCodewords);
    var shortBlockSize = ecInfo.ecBlocks[0].dataCodewordsPerBlock;
    // Pull codewords to fill the blocks up to the minimum size
    for (var i = 0; i < shortBlockSize; i++) {
        for (var _i = 0, dataBlocks_1 = dataBlocks; _i < dataBlocks_1.length; _i++) {
            var dataBlock = dataBlocks_1[_i];
            dataBlock.codewords.push(codewords.shift());
        }
    }
    // If there are any large blocks, pull codewords to fill the last element of those
    if (ecInfo.ecBlocks.length > 1) {
        var smallBlockCount = ecInfo.ecBlocks[0].numBlocks;
        var largeBlockCount = ecInfo.ecBlocks[1].numBlocks;
        for (var i = 0; i < largeBlockCount; i++) {
            dataBlocks[smallBlockCount + i].codewords.push(codewords.shift());
        }
    }
    // Add the rest of the codewords to the blocks. These are the error correction codewords.
    while (codewords.length > 0) {
        for (var _a = 0, dataBlocks_2 = dataBlocks; _a < dataBlocks_2.length; _a++) {
            var dataBlock = dataBlocks_2[_a];
            dataBlock.codewords.push(codewords.shift());
        }
    }
    return dataBlocks;
}
function decodeMatrix(matrix) {
    var version = readVersion(matrix);
    if (!version) {
        return null;
    }
    var formatInfo = readFormatInformation(matrix);
    if (!formatInfo) {
        return null;
    }
    var codewords = readCodewords(matrix, version, formatInfo);
    var dataBlocks = getDataBlocks(codewords, version, formatInfo.errorCorrectionLevel);
    if (!dataBlocks) {
        return null;
    }
    // Count total number of data bytes
    var totalBytes = dataBlocks.reduce(function (a, b) { return a + b.numDataCodewords; }, 0);
    var resultBytes = new Uint8ClampedArray(totalBytes);
    var resultIndex = 0;
    for (var _i = 0, dataBlocks_3 = dataBlocks; _i < dataBlocks_3.length; _i++) {
        var dataBlock = dataBlocks_3[_i];
        var correctedBytes = reedsolomon_1.decode(dataBlock.codewords, dataBlock.codewords.length - dataBlock.numDataCodewords);
        if (!correctedBytes) {
            return null;
        }
        for (var i = 0; i < dataBlock.numDataCodewords; i++) {
            resultBytes[resultIndex++] = correctedBytes[i];
        }
    }
    try {
        return decodeData_1.decode(resultBytes, version.versionNumber);
    }
    catch (_a) {
        return null;
    }
}
function decode(matrix) {
    if (matrix == null) {
        return null;
    }
    var result = decodeMatrix(matrix);
    if (result) {
        return result;
    }
    // Decoding didn't work, try mirroring the QR across the topLeft -> bottomRight line.
    for (var x = 0; x < matrix.width; x++) {
        for (var y = x + 1; y < matrix.height; y++) {
            if (matrix.get(x, y) !== matrix.get(y, x)) {
                matrix.set(x, y, !matrix.get(x, y));
                matrix.set(y, x, !matrix.get(y, x));
            }
        }
    }
    return decodeMatrix(matrix);
}
exports.decode = decode;


/***/ }),
/* 6 */
/***/ (function(module, exports, __nested_webpack_require_33675__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
// tslint:disable:no-bitwise
var BitStream_1 = __nested_webpack_require_33675__(7);
var shiftJISTable_1 = __nested_webpack_require_33675__(8);
var Mode;
(function (Mode) {
    Mode["Numeric"] = "numeric";
    Mode["Alphanumeric"] = "alphanumeric";
    Mode["Byte"] = "byte";
    Mode["Kanji"] = "kanji";
    Mode["ECI"] = "eci";
})(Mode = exports.Mode || (exports.Mode = {}));
var ModeByte;
(function (ModeByte) {
    ModeByte[ModeByte["Terminator"] = 0] = "Terminator";
    ModeByte[ModeByte["Numeric"] = 1] = "Numeric";
    ModeByte[ModeByte["Alphanumeric"] = 2] = "Alphanumeric";
    ModeByte[ModeByte["Byte"] = 4] = "Byte";
    ModeByte[ModeByte["Kanji"] = 8] = "Kanji";
    ModeByte[ModeByte["ECI"] = 7] = "ECI";
    // StructuredAppend = 0x3,
    // FNC1FirstPosition = 0x5,
    // FNC1SecondPosition = 0x9,
})(ModeByte || (ModeByte = {}));
function decodeNumeric(stream, size) {
    var bytes = [];
    var text = "";
    var characterCountSize = [10, 12, 14][size];
    var length = stream.readBits(characterCountSize);
    // Read digits in groups of 3
    while (length >= 3) {
        var num = stream.readBits(10);
        if (num >= 1000) {
            throw new Error("Invalid numeric value above 999");
        }
        var a = Math.floor(num / 100);
        var b = Math.floor(num / 10) % 10;
        var c = num % 10;
        bytes.push(48 + a, 48 + b, 48 + c);
        text += a.toString() + b.toString() + c.toString();
        length -= 3;
    }
    // If the number of digits aren't a multiple of 3, the remaining digits are special cased.
    if (length === 2) {
        var num = stream.readBits(7);
        if (num >= 100) {
            throw new Error("Invalid numeric value above 99");
        }
        var a = Math.floor(num / 10);
        var b = num % 10;
        bytes.push(48 + a, 48 + b);
        text += a.toString() + b.toString();
    }
    else if (length === 1) {
        var num = stream.readBits(4);
        if (num >= 10) {
            throw new Error("Invalid numeric value above 9");
        }
        bytes.push(48 + num);
        text += num.toString();
    }
    return { bytes: bytes, text: text };
}
var AlphanumericCharacterCodes = [
    "0", "1", "2", "3", "4", "5", "6", "7", "8",
    "9", "A", "B", "C", "D", "E", "F", "G", "H",
    "I", "J", "K", "L", "M", "N", "O", "P", "Q",
    "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
    " ", "$", "%", "*", "+", "-", ".", "/", ":",
];
function decodeAlphanumeric(stream, size) {
    var bytes = [];
    var text = "";
    var characterCountSize = [9, 11, 13][size];
    var length = stream.readBits(characterCountSize);
    while (length >= 2) {
        var v = stream.readBits(11);
        var a = Math.floor(v / 45);
        var b = v % 45;
        bytes.push(AlphanumericCharacterCodes[a].charCodeAt(0), AlphanumericCharacterCodes[b].charCodeAt(0));
        text += AlphanumericCharacterCodes[a] + AlphanumericCharacterCodes[b];
        length -= 2;
    }
    if (length === 1) {
        var a = stream.readBits(6);
        bytes.push(AlphanumericCharacterCodes[a].charCodeAt(0));
        text += AlphanumericCharacterCodes[a];
    }
    return { bytes: bytes, text: text };
}
function decodeByte(stream, size) {
    var bytes = [];
    var text = "";
    var characterCountSize = [8, 16, 16][size];
    var length = stream.readBits(characterCountSize);
    for (var i = 0; i < length; i++) {
        var b = stream.readBits(8);
        bytes.push(b);
    }
    try {
        text += decodeURIComponent(bytes.map(function (b) { return "%" + ("0" + b.toString(16)).substr(-2); }).join(""));
    }
    catch (_a) {
        // failed to decode
    }
    return { bytes: bytes, text: text };
}
function decodeKanji(stream, size) {
    var bytes = [];
    var text = "";
    var characterCountSize = [8, 10, 12][size];
    var length = stream.readBits(characterCountSize);
    for (var i = 0; i < length; i++) {
        var k = stream.readBits(13);
        var c = (Math.floor(k / 0xC0) << 8) | (k % 0xC0);
        if (c < 0x1F00) {
            c += 0x8140;
        }
        else {
            c += 0xC140;
        }
        bytes.push(c >> 8, c & 0xFF);
        text += String.fromCharCode(shiftJISTable_1.shiftJISTable[c]);
    }
    return { bytes: bytes, text: text };
}
function decode(data, version) {
    var _a, _b, _c, _d;
    var stream = new BitStream_1.BitStream(data);
    // There are 3 'sizes' based on the version. 1-9 is small (0), 10-26 is medium (1) and 27-40 is large (2).
    var size = version <= 9 ? 0 : version <= 26 ? 1 : 2;
    var result = {
        text: "",
        bytes: [],
        chunks: [],
        version: version,
    };
    while (stream.available() >= 4) {
        var mode = stream.readBits(4);
        if (mode === ModeByte.Terminator) {
            return result;
        }
        else if (mode === ModeByte.ECI) {
            if (stream.readBits(1) === 0) {
                result.chunks.push({
                    type: Mode.ECI,
                    assignmentNumber: stream.readBits(7),
                });
            }
            else if (stream.readBits(1) === 0) {
                result.chunks.push({
                    type: Mode.ECI,
                    assignmentNumber: stream.readBits(14),
                });
            }
            else if (stream.readBits(1) === 0) {
                result.chunks.push({
                    type: Mode.ECI,
                    assignmentNumber: stream.readBits(21),
                });
            }
            else {
                // ECI data seems corrupted
                result.chunks.push({
                    type: Mode.ECI,
                    assignmentNumber: -1,
                });
            }
        }
        else if (mode === ModeByte.Numeric) {
            var numericResult = decodeNumeric(stream, size);
            result.text += numericResult.text;
            (_a = result.bytes).push.apply(_a, numericResult.bytes);
            result.chunks.push({
                type: Mode.Numeric,
                text: numericResult.text,
            });
        }
        else if (mode === ModeByte.Alphanumeric) {
            var alphanumericResult = decodeAlphanumeric(stream, size);
            result.text += alphanumericResult.text;
            (_b = result.bytes).push.apply(_b, alphanumericResult.bytes);
            result.chunks.push({
                type: Mode.Alphanumeric,
                text: alphanumericResult.text,
            });
        }
        else if (mode === ModeByte.Byte) {
            var byteResult = decodeByte(stream, size);
            result.text += byteResult.text;
            (_c = result.bytes).push.apply(_c, byteResult.bytes);
            result.chunks.push({
                type: Mode.Byte,
                bytes: byteResult.bytes,
                text: byteResult.text,
            });
        }
        else if (mode === ModeByte.Kanji) {
            var kanjiResult = decodeKanji(stream, size);
            result.text += kanjiResult.text;
            (_d = result.bytes).push.apply(_d, kanjiResult.bytes);
            result.chunks.push({
                type: Mode.Kanji,
                bytes: kanjiResult.bytes,
                text: kanjiResult.text,
            });
        }
    }
    // If there is no data left, or the remaining bits are all 0, then that counts as a termination marker
    if (stream.available() === 0 || stream.readBits(stream.available()) === 0) {
        return result;
    }
}
exports.decode = decode;


/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

// tslint:disable:no-bitwise
Object.defineProperty(exports, "__esModule", { value: true });
var BitStream = /** @class */ (function () {
    function BitStream(bytes) {
        this.byteOffset = 0;
        this.bitOffset = 0;
        this.bytes = bytes;
    }
    BitStream.prototype.readBits = function (numBits) {
        if (numBits < 1 || numBits > 32 || numBits > this.available()) {
            throw new Error("Cannot read " + numBits.toString() + " bits");
        }
        var result = 0;
        // First, read remainder from current byte
        if (this.bitOffset > 0) {
            var bitsLeft = 8 - this.bitOffset;
            var toRead = numBits < bitsLeft ? numBits : bitsLeft;
            var bitsToNotRead = bitsLeft - toRead;
            var mask = (0xFF >> (8 - toRead)) << bitsToNotRead;
            result = (this.bytes[this.byteOffset] & mask) >> bitsToNotRead;
            numBits -= toRead;
            this.bitOffset += toRead;
            if (this.bitOffset === 8) {
                this.bitOffset = 0;
                this.byteOffset++;
            }
        }
        // Next read whole bytes
        if (numBits > 0) {
            while (numBits >= 8) {
                result = (result << 8) | (this.bytes[this.byteOffset] & 0xFF);
                this.byteOffset++;
                numBits -= 8;
            }
            // Finally read a partial byte
            if (numBits > 0) {
                var bitsToNotRead = 8 - numBits;
                var mask = (0xFF >> bitsToNotRead) << bitsToNotRead;
                result = (result << numBits) | ((this.bytes[this.byteOffset] & mask) >> bitsToNotRead);
                this.bitOffset += numBits;
            }
        }
        return result;
    };
    BitStream.prototype.available = function () {
        return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset;
    };
    return BitStream;
}());
exports.BitStream = BitStream;


/***/ }),
/* 8 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.shiftJISTable = {
    0x20: 0x0020,
    0x21: 0x0021,
    0x22: 0x0022,
    0x23: 0x0023,
    0x24: 0x0024,
    0x25: 0x0025,
    0x26: 0x0026,
    0x27: 0x0027,
    0x28: 0x0028,
    0x29: 0x0029,
    0x2A: 0x002A,
    0x2B: 0x002B,
    0x2C: 0x002C,
    0x2D: 0x002D,
    0x2E: 0x002E,
    0x2F: 0x002F,
    0x30: 0x0030,
    0x31: 0x0031,
    0x32: 0x0032,
    0x33: 0x0033,
    0x34: 0x0034,
    0x35: 0x0035,
    0x36: 0x0036,
    0x37: 0x0037,
    0x38: 0x0038,
    0x39: 0x0039,
    0x3A: 0x003A,
    0x3B: 0x003B,
    0x3C: 0x003C,
    0x3D: 0x003D,
    0x3E: 0x003E,
    0x3F: 0x003F,
    0x40: 0x0040,
    0x41: 0x0041,
    0x42: 0x0042,
    0x43: 0x0043,
    0x44: 0x0044,
    0x45: 0x0045,
    0x46: 0x0046,
    0x47: 0x0047,
    0x48: 0x0048,
    0x49: 0x0049,
    0x4A: 0x004A,
    0x4B: 0x004B,
    0x4C: 0x004C,
    0x4D: 0x004D,
    0x4E: 0x004E,
    0x4F: 0x004F,
    0x50: 0x0050,
    0x51: 0x0051,
    0x52: 0x0052,
    0x53: 0x0053,
    0x54: 0x0054,
    0x55: 0x0055,
    0x56: 0x0056,
    0x57: 0x0057,
    0x58: 0x0058,
    0x59: 0x0059,
    0x5A: 0x005A,
    0x5B: 0x005B,
    0x5C: 0x00A5,
    0x5D: 0x005D,
    0x5E: 0x005E,
    0x5F: 0x005F,
    0x60: 0x0060,
    0x61: 0x0061,
    0x62: 0x0062,
    0x63: 0x0063,
    0x64: 0x0064,
    0x65: 0x0065,
    0x66: 0x0066,
    0x67: 0x0067,
    0x68: 0x0068,
    0x69: 0x0069,
    0x6A: 0x006A,
    0x6B: 0x006B,
    0x6C: 0x006C,
    0x6D: 0x006D,
    0x6E: 0x006E,
    0x6F: 0x006F,
    0x70: 0x0070,
    0x71: 0x0071,
    0x72: 0x0072,
    0x73: 0x0073,
    0x74: 0x0074,
    0x75: 0x0075,
    0x76: 0x0076,
    0x77: 0x0077,
    0x78: 0x0078,
    0x79: 0x0079,
    0x7A: 0x007A,
    0x7B: 0x007B,
    0x7C: 0x007C,
    0x7D: 0x007D,
    0x7E: 0x203E,
    0x8140: 0x3000,
    0x8141: 0x3001,
    0x8142: 0x3002,
    0x8143: 0xFF0C,
    0x8144: 0xFF0E,
    0x8145: 0x30FB,
    0x8146: 0xFF1A,
    0x8147: 0xFF1B,
    0x8148: 0xFF1F,
    0x8149: 0xFF01,
    0x814A: 0x309B,
    0x814B: 0x309C,
    0x814C: 0x00B4,
    0x814D: 0xFF40,
    0x814E: 0x00A8,
    0x814F: 0xFF3E,
    0x8150: 0xFFE3,
    0x8151: 0xFF3F,
    0x8152: 0x30FD,
    0x8153: 0x30FE,
    0x8154: 0x309D,
    0x8155: 0x309E,
    0x8156: 0x3003,
    0x8157: 0x4EDD,
    0x8158: 0x3005,
    0x8159: 0x3006,
    0x815A: 0x3007,
    0x815B: 0x30FC,
    0x815C: 0x2015,
    0x815D: 0x2010,
    0x815E: 0xFF0F,
    0x815F: 0x005C,
    0x8160: 0x301C,
    0x8161: 0x2016,
    0x8162: 0xFF5C,
    0x8163: 0x2026,
    0x8164: 0x2025,
    0x8165: 0x2018,
    0x8166: 0x2019,
    0x8167: 0x201C,
    0x8168: 0x201D,
    0x8169: 0xFF08,
    0x816A: 0xFF09,
    0x816B: 0x3014,
    0x816C: 0x3015,
    0x816D: 0xFF3B,
    0x816E: 0xFF3D,
    0x816F: 0xFF5B,
    0x8170: 0xFF5D,
    0x8171: 0x3008,
    0x8172: 0x3009,
    0x8173: 0x300A,
    0x8174: 0x300B,
    0x8175: 0x300C,
    0x8176: 0x300D,
    0x8177: 0x300E,
    0x8178: 0x300F,
    0x8179: 0x3010,
    0x817A: 0x3011,
    0x817B: 0xFF0B,
    0x817C: 0x2212,
    0x817D: 0x00B1,
    0x817E: 0x00D7,
    0x8180: 0x00F7,
    0x8181: 0xFF1D,
    0x8182: 0x2260,
    0x8183: 0xFF1C,
    0x8184: 0xFF1E,
    0x8185: 0x2266,
    0x8186: 0x2267,
    0x8187: 0x221E,
    0x8188: 0x2234,
    0x8189: 0x2642,
    0x818A: 0x2640,
    0x818B: 0x00B0,
    0x818C: 0x2032,
    0x818D: 0x2033,
    0x818E: 0x2103,
    0x818F: 0xFFE5,
    0x8190: 0xFF04,
    0x8191: 0x00A2,
    0x8192: 0x00A3,
    0x8193: 0xFF05,
    0x8194: 0xFF03,
    0x8195: 0xFF06,
    0x8196: 0xFF0A,
    0x8197: 0xFF20,
    0x8198: 0x00A7,
    0x8199: 0x2606,
    0x819A: 0x2605,
    0x819B: 0x25CB,
    0x819C: 0x25CF,
    0x819D: 0x25CE,
    0x819E: 0x25C7,
    0x819F: 0x25C6,
    0x81A0: 0x25A1,
    0x81A1: 0x25A0,
    0x81A2: 0x25B3,
    0x81A3: 0x25B2,
    0x81A4: 0x25BD,
    0x81A5: 0x25BC,
    0x81A6: 0x203B,
    0x81A7: 0x3012,
    0x81A8: 0x2192,
    0x81A9: 0x2190,
    0x81AA: 0x2191,
    0x81AB: 0x2193,
    0x81AC: 0x3013,
    0x81B8: 0x2208,
    0x81B9: 0x220B,
    0x81BA: 0x2286,
    0x81BB: 0x2287,
    0x81BC: 0x2282,
    0x81BD: 0x2283,
    0x81BE: 0x222A,
    0x81BF: 0x2229,
    0x81C8: 0x2227,
    0x81C9: 0x2228,
    0x81CA: 0x00AC,
    0x81CB: 0x21D2,
    0x81CC: 0x21D4,
    0x81CD: 0x2200,
    0x81CE: 0x2203,
    0x81DA: 0x2220,
    0x81DB: 0x22A5,
    0x81DC: 0x2312,
    0x81DD: 0x2202,
    0x81DE: 0x2207,
    0x81DF: 0x2261,
    0x81E0: 0x2252,
    0x81E1: 0x226A,
    0x81E2: 0x226B,
    0x81E3: 0x221A,
    0x81E4: 0x223D,
    0x81E5: 0x221D,
    0x81E6: 0x2235,
    0x81E7: 0x222B,
    0x81E8: 0x222C,
    0x81F0: 0x212B,
    0x81F1: 0x2030,
    0x81F2: 0x266F,
    0x81F3: 0x266D,
    0x81F4: 0x266A,
    0x81F5: 0x2020,
    0x81F6: 0x2021,
    0x81F7: 0x00B6,
    0x81FC: 0x25EF,
    0x824F: 0xFF10,
    0x8250: 0xFF11,
    0x8251: 0xFF12,
    0x8252: 0xFF13,
    0x8253: 0xFF14,
    0x8254: 0xFF15,
    0x8255: 0xFF16,
    0x8256: 0xFF17,
    0x8257: 0xFF18,
    0x8258: 0xFF19,
    0x8260: 0xFF21,
    0x8261: 0xFF22,
    0x8262: 0xFF23,
    0x8263: 0xFF24,
    0x8264: 0xFF25,
    0x8265: 0xFF26,
    0x8266: 0xFF27,
    0x8267: 0xFF28,
    0x8268: 0xFF29,
    0x8269: 0xFF2A,
    0x826A: 0xFF2B,
    0x826B: 0xFF2C,
    0x826C: 0xFF2D,
    0x826D: 0xFF2E,
    0x826E: 0xFF2F,
    0x826F: 0xFF30,
    0x8270: 0xFF31,
    0x8271: 0xFF32,
    0x8272: 0xFF33,
    0x8273: 0xFF34,
    0x8274: 0xFF35,
    0x8275: 0xFF36,
    0x8276: 0xFF37,
    0x8277: 0xFF38,
    0x8278: 0xFF39,
    0x8279: 0xFF3A,
    0x8281: 0xFF41,
    0x8282: 0xFF42,
    0x8283: 0xFF43,
    0x8284: 0xFF44,
    0x8285: 0xFF45,
    0x8286: 0xFF46,
    0x8287: 0xFF47,
    0x8288: 0xFF48,
    0x8289: 0xFF49,
    0x828A: 0xFF4A,
    0x828B: 0xFF4B,
    0x828C: 0xFF4C,
    0x828D: 0xFF4D,
    0x828E: 0xFF4E,
    0x828F: 0xFF4F,
    0x8290: 0xFF50,
    0x8291: 0xFF51,
    0x8292: 0xFF52,
    0x8293: 0xFF53,
    0x8294: 0xFF54,
    0x8295: 0xFF55,
    0x8296: 0xFF56,
    0x8297: 0xFF57,
    0x8298: 0xFF58,
    0x8299: 0xFF59,
    0x829A: 0xFF5A,
    0x829F: 0x3041,
    0x82A0: 0x3042,
    0x82A1: 0x3043,
    0x82A2: 0x3044,
    0x82A3: 0x3045,
    0x82A4: 0x3046,
    0x82A5: 0x3047,
    0x82A6: 0x3048,
    0x82A7: 0x3049,
    0x82A8: 0x304A,
    0x82A9: 0x304B,
    0x82AA: 0x304C,
    0x82AB: 0x304D,
    0x82AC: 0x304E,
    0x82AD: 0x304F,
    0x82AE: 0x3050,
    0x82AF: 0x3051,
    0x82B0: 0x3052,
    0x82B1: 0x3053,
    0x82B2: 0x3054,
    0x82B3: 0x3055,
    0x82B4: 0x3056,
    0x82B5: 0x3057,
    0x82B6: 0x3058,
    0x82B7: 0x3059,
    0x82B8: 0x305A,
    0x82B9: 0x305B,
    0x82BA: 0x305C,
    0x82BB: 0x305D,
    0x82BC: 0x305E,
    0x82BD: 0x305F,
    0x82BE: 0x3060,
    0x82BF: 0x3061,
    0x82C0: 0x3062,
    0x82C1: 0x3063,
    0x82C2: 0x3064,
    0x82C3: 0x3065,
    0x82C4: 0x3066,
    0x82C5: 0x3067,
    0x82C6: 0x3068,
    0x82C7: 0x3069,
    0x82C8: 0x306A,
    0x82C9: 0x306B,
    0x82CA: 0x306C,
    0x82CB: 0x306D,
    0x82CC: 0x306E,
    0x82CD: 0x306F,
    0x82CE: 0x3070,
    0x82CF: 0x3071,
    0x82D0: 0x3072,
    0x82D1: 0x3073,
    0x82D2: 0x3074,
    0x82D3: 0x3075,
    0x82D4: 0x3076,
    0x82D5: 0x3077,
    0x82D6: 0x3078,
    0x82D7: 0x3079,
    0x82D8: 0x307A,
    0x82D9: 0x307B,
    0x82DA: 0x307C,
    0x82DB: 0x307D,
    0x82DC: 0x307E,
    0x82DD: 0x307F,
    0x82DE: 0x3080,
    0x82DF: 0x3081,
    0x82E0: 0x3082,
    0x82E1: 0x3083,
    0x82E2: 0x3084,
    0x82E3: 0x3085,
    0x82E4: 0x3086,
    0x82E5: 0x3087,
    0x82E6: 0x3088,
    0x82E7: 0x3089,
    0x82E8: 0x308A,
    0x82E9: 0x308B,
    0x82EA: 0x308C,
    0x82EB: 0x308D,
    0x82EC: 0x308E,
    0x82ED: 0x308F,
    0x82EE: 0x3090,
    0x82EF: 0x3091,
    0x82F0: 0x3092,
    0x82F1: 0x3093,
    0x8340: 0x30A1,
    0x8341: 0x30A2,
    0x8342: 0x30A3,
    0x8343: 0x30A4,
    0x8344: 0x30A5,
    0x8345: 0x30A6,
    0x8346: 0x30A7,
    0x8347: 0x30A8,
    0x8348: 0x30A9,
    0x8349: 0x30AA,
    0x834A: 0x30AB,
    0x834B: 0x30AC,
    0x834C: 0x30AD,
    0x834D: 0x30AE,
    0x834E: 0x30AF,
    0x834F: 0x30B0,
    0x8350: 0x30B1,
    0x8351: 0x30B2,
    0x8352: 0x30B3,
    0x8353: 0x30B4,
    0x8354: 0x30B5,
    0x8355: 0x30B6,
    0x8356: 0x30B7,
    0x8357: 0x30B8,
    0x8358: 0x30B9,
    0x8359: 0x30BA,
    0x835A: 0x30BB,
    0x835B: 0x30BC,
    0x835C: 0x30BD,
    0x835D: 0x30BE,
    0x835E: 0x30BF,
    0x835F: 0x30C0,
    0x8360: 0x30C1,
    0x8361: 0x30C2,
    0x8362: 0x30C3,
    0x8363: 0x30C4,
    0x8364: 0x30C5,
    0x8365: 0x30C6,
    0x8366: 0x30C7,
    0x8367: 0x30C8,
    0x8368: 0x30C9,
    0x8369: 0x30CA,
    0x836A: 0x30CB,
    0x836B: 0x30CC,
    0x836C: 0x30CD,
    0x836D: 0x30CE,
    0x836E: 0x30CF,
    0x836F: 0x30D0,
    0x8370: 0x30D1,
    0x8371: 0x30D2,
    0x8372: 0x30D3,
    0x8373: 0x30D4,
    0x8374: 0x30D5,
    0x8375: 0x30D6,
    0x8376: 0x30D7,
    0x8377: 0x30D8,
    0x8378: 0x30D9,
    0x8379: 0x30DA,
    0x837A: 0x30DB,
    0x837B: 0x30DC,
    0x837C: 0x30DD,
    0x837D: 0x30DE,
    0x837E: 0x30DF,
    0x8380: 0x30E0,
    0x8381: 0x30E1,
    0x8382: 0x30E2,
    0x8383: 0x30E3,
    0x8384: 0x30E4,
    0x8385: 0x30E5,
    0x8386: 0x30E6,
    0x8387: 0x30E7,
    0x8388: 0x30E8,
    0x8389: 0x30E9,
    0x838A: 0x30EA,
    0x838B: 0x30EB,
    0x838C: 0x30EC,
    0x838D: 0x30ED,
    0x838E: 0x30EE,
    0x838F: 0x30EF,
    0x8390: 0x30F0,
    0x8391: 0x30F1,
    0x8392: 0x30F2,
    0x8393: 0x30F3,
    0x8394: 0x30F4,
    0x8395: 0x30F5,
    0x8396: 0x30F6,
    0x839F: 0x0391,
    0x83A0: 0x0392,
    0x83A1: 0x0393,
    0x83A2: 0x0394,
    0x83A3: 0x0395,
    0x83A4: 0x0396,
    0x83A5: 0x0397,
    0x83A6: 0x0398,
    0x83A7: 0x0399,
    0x83A8: 0x039A,
    0x83A9: 0x039B,
    0x83AA: 0x039C,
    0x83AB: 0x039D,
    0x83AC: 0x039E,
    0x83AD: 0x039F,
    0x83AE: 0x03A0,
    0x83AF: 0x03A1,
    0x83B0: 0x03A3,
    0x83B1: 0x03A4,
    0x83B2: 0x03A5,
    0x83B3: 0x03A6,
    0x83B4: 0x03A7,
    0x83B5: 0x03A8,
    0x83B6: 0x03A9,
    0x83BF: 0x03B1,
    0x83C0: 0x03B2,
    0x83C1: 0x03B3,
    0x83C2: 0x03B4,
    0x83C3: 0x03B5,
    0x83C4: 0x03B6,
    0x83C5: 0x03B7,
    0x83C6: 0x03B8,
    0x83C7: 0x03B9,
    0x83C8: 0x03BA,
    0x83C9: 0x03BB,
    0x83CA: 0x03BC,
    0x83CB: 0x03BD,
    0x83CC: 0x03BE,
    0x83CD: 0x03BF,
    0x83CE: 0x03C0,
    0x83CF: 0x03C1,
    0x83D0: 0x03C3,
    0x83D1: 0x03C4,
    0x83D2: 0x03C5,
    0x83D3: 0x03C6,
    0x83D4: 0x03C7,
    0x83D5: 0x03C8,
    0x83D6: 0x03C9,
    0x8440: 0x0410,
    0x8441: 0x0411,
    0x8442: 0x0412,
    0x8443: 0x0413,
    0x8444: 0x0414,
    0x8445: 0x0415,
    0x8446: 0x0401,
    0x8447: 0x0416,
    0x8448: 0x0417,
    0x8449: 0x0418,
    0x844A: 0x0419,
    0x844B: 0x041A,
    0x844C: 0x041B,
    0x844D: 0x041C,
    0x844E: 0x041D,
    0x844F: 0x041E,
    0x8450: 0x041F,
    0x8451: 0x0420,
    0x8452: 0x0421,
    0x8453: 0x0422,
    0x8454: 0x0423,
    0x8455: 0x0424,
    0x8456: 0x0425,
    0x8457: 0x0426,
    0x8458: 0x0427,
    0x8459: 0x0428,
    0x845A: 0x0429,
    0x845B: 0x042A,
    0x845C: 0x042B,
    0x845D: 0x042C,
    0x845E: 0x042D,
    0x845F: 0x042E,
    0x8460: 0x042F,
    0x8470: 0x0430,
    0x8471: 0x0431,
    0x8472: 0x0432,
    0x8473: 0x0433,
    0x8474: 0x0434,
    0x8475: 0x0435,
    0x8476: 0x0451,
    0x8477: 0x0436,
    0x8478: 0x0437,
    0x8479: 0x0438,
    0x847A: 0x0439,
    0x847B: 0x043A,
    0x847C: 0x043B,
    0x847D: 0x043C,
    0x847E: 0x043D,
    0x8480: 0x043E,
    0x8481: 0x043F,
    0x8482: 0x0440,
    0x8483: 0x0441,
    0x8484: 0x0442,
    0x8485: 0x0443,
    0x8486: 0x0444,
    0x8487: 0x0445,
    0x8488: 0x0446,
    0x8489: 0x0447,
    0x848A: 0x0448,
    0x848B: 0x0449,
    0x848C: 0x044A,
    0x848D: 0x044B,
    0x848E: 0x044C,
    0x848F: 0x044D,
    0x8490: 0x044E,
    0x8491: 0x044F,
    0x849F: 0x2500,
    0x84A0: 0x2502,
    0x84A1: 0x250C,
    0x84A2: 0x2510,
    0x84A3: 0x2518,
    0x84A4: 0x2514,
    0x84A5: 0x251C,
    0x84A6: 0x252C,
    0x84A7: 0x2524,
    0x84A8: 0x2534,
    0x84A9: 0x253C,
    0x84AA: 0x2501,
    0x84AB: 0x2503,
    0x84AC: 0x250F,
    0x84AD: 0x2513,
    0x84AE: 0x251B,
    0x84AF: 0x2517,
    0x84B0: 0x2523,
    0x84B1: 0x2533,
    0x84B2: 0x252B,
    0x84B3: 0x253B,
    0x84B4: 0x254B,
    0x84B5: 0x2520,
    0x84B6: 0x252F,
    0x84B7: 0x2528,
    0x84B8: 0x2537,
    0x84B9: 0x253F,
    0x84BA: 0x251D,
    0x84BB: 0x2530,
    0x84BC: 0x2525,
    0x84BD: 0x2538,
    0x84BE: 0x2542,
    0x889F: 0x4E9C,
    0x88A0: 0x5516,
    0x88A1: 0x5A03,
    0x88A2: 0x963F,
    0x88A3: 0x54C0,
    0x88A4: 0x611B,
    0x88A5: 0x6328,
    0x88A6: 0x59F6,
    0x88A7: 0x9022,
    0x88A8: 0x8475,
    0x88A9: 0x831C,
    0x88AA: 0x7A50,
    0x88AB: 0x60AA,
    0x88AC: 0x63E1,
    0x88AD: 0x6E25,
    0x88AE: 0x65ED,
    0x88AF: 0x8466,
    0x88B0: 0x82A6,
    0x88B1: 0x9BF5,
    0x88B2: 0x6893,
    0x88B3: 0x5727,
    0x88B4: 0x65A1,
    0x88B5: 0x6271,
    0x88B6: 0x5B9B,
    0x88B7: 0x59D0,
    0x88B8: 0x867B,
    0x88B9: 0x98F4,
    0x88BA: 0x7D62,
    0x88BB: 0x7DBE,
    0x88BC: 0x9B8E,
    0x88BD: 0x6216,
    0x88BE: 0x7C9F,
    0x88BF: 0x88B7,
    0x88C0: 0x5B89,
    0x88C1: 0x5EB5,
    0x88C2: 0x6309,
    0x88C3: 0x6697,
    0x88C4: 0x6848,
    0x88C5: 0x95C7,
    0x88C6: 0x978D,
    0x88C7: 0x674F,
    0x88C8: 0x4EE5,
    0x88C9: 0x4F0A,
    0x88CA: 0x4F4D,
    0x88CB: 0x4F9D,
    0x88CC: 0x5049,
    0x88CD: 0x56F2,
    0x88CE: 0x5937,
    0x88CF: 0x59D4,
    0x88D0: 0x5A01,
    0x88D1: 0x5C09,
    0x88D2: 0x60DF,
    0x88D3: 0x610F,
    0x88D4: 0x6170,
    0x88D5: 0x6613,
    0x88D6: 0x6905,
    0x88D7: 0x70BA,
    0x88D8: 0x754F,
    0x88D9: 0x7570,
    0x88DA: 0x79FB,
    0x88DB: 0x7DAD,
    0x88DC: 0x7DEF,
    0x88DD: 0x80C3,
    0x88DE: 0x840E,
    0x88DF: 0x8863,
    0x88E0: 0x8B02,
    0x88E1: 0x9055,
    0x88E2: 0x907A,
    0x88E3: 0x533B,
    0x88E4: 0x4E95,
    0x88E5: 0x4EA5,
    0x88E6: 0x57DF,
    0x88E7: 0x80B2,
    0x88E8: 0x90C1,
    0x88E9: 0x78EF,
    0x88EA: 0x4E00,
    0x88EB: 0x58F1,
    0x88EC: 0x6EA2,
    0x88ED: 0x9038,
    0x88EE: 0x7A32,
    0x88EF: 0x8328,
    0x88F0: 0x828B,
    0x88F1: 0x9C2F,
    0x88F2: 0x5141,
    0x88F3: 0x5370,
    0x88F4: 0x54BD,
    0x88F5: 0x54E1,
    0x88F6: 0x56E0,
    0x88F7: 0x59FB,
    0x88F8: 0x5F15,
    0x88F9: 0x98F2,
    0x88FA: 0x6DEB,
    0x88FB: 0x80E4,
    0x88FC: 0x852D,
    0x8940: 0x9662,
    0x8941: 0x9670,
    0x8942: 0x96A0,
    0x8943: 0x97FB,
    0x8944: 0x540B,
    0x8945: 0x53F3,
    0x8946: 0x5B87,
    0x8947: 0x70CF,
    0x8948: 0x7FBD,
    0x8949: 0x8FC2,
    0x894A: 0x96E8,
    0x894B: 0x536F,
    0x894C: 0x9D5C,
    0x894D: 0x7ABA,
    0x894E: 0x4E11,
    0x894F: 0x7893,
    0x8950: 0x81FC,
    0x8951: 0x6E26,
    0x8952: 0x5618,
    0x8953: 0x5504,
    0x8954: 0x6B1D,
    0x8955: 0x851A,
    0x8956: 0x9C3B,
    0x8957: 0x59E5,
    0x8958: 0x53A9,
    0x8959: 0x6D66,
    0x895A: 0x74DC,
    0x895B: 0x958F,
    0x895C: 0x5642,
    0x895D: 0x4E91,
    0x895E: 0x904B,
    0x895F: 0x96F2,
    0x8960: 0x834F,
    0x8961: 0x990C,
    0x8962: 0x53E1,
    0x8963: 0x55B6,
    0x8964: 0x5B30,
    0x8965: 0x5F71,
    0x8966: 0x6620,
    0x8967: 0x66F3,
    0x8968: 0x6804,
    0x8969: 0x6C38,
    0x896A: 0x6CF3,
    0x896B: 0x6D29,
    0x896C: 0x745B,
    0x896D: 0x76C8,
    0x896E: 0x7A4E,
    0x896F: 0x9834,
    0x8970: 0x82F1,
    0x8971: 0x885B,
    0x8972: 0x8A60,
    0x8973: 0x92ED,
    0x8974: 0x6DB2,
    0x8975: 0x75AB,
    0x8976: 0x76CA,
    0x8977: 0x99C5,
    0x8978: 0x60A6,
    0x8979: 0x8B01,
    0x897A: 0x8D8A,
    0x897B: 0x95B2,
    0x897C: 0x698E,
    0x897D: 0x53AD,
    0x897E: 0x5186,
    0x8980: 0x5712,
    0x8981: 0x5830,
    0x8982: 0x5944,
    0x8983: 0x5BB4,
    0x8984: 0x5EF6,
    0x8985: 0x6028,
    0x8986: 0x63A9,
    0x8987: 0x63F4,
    0x8988: 0x6CBF,
    0x8989: 0x6F14,
    0x898A: 0x708E,
    0x898B: 0x7114,
    0x898C: 0x7159,
    0x898D: 0x71D5,
    0x898E: 0x733F,
    0x898F: 0x7E01,
    0x8990: 0x8276,
    0x8991: 0x82D1,
    0x8992: 0x8597,
    0x8993: 0x9060,
    0x8994: 0x925B,
    0x8995: 0x9D1B,
    0x8996: 0x5869,
    0x8997: 0x65BC,
    0x8998: 0x6C5A,
    0x8999: 0x7525,
    0x899A: 0x51F9,
    0x899B: 0x592E,
    0x899C: 0x5965,
    0x899D: 0x5F80,
    0x899E: 0x5FDC,
    0x899F: 0x62BC,
    0x89A0: 0x65FA,
    0x89A1: 0x6A2A,
    0x89A2: 0x6B27,
    0x89A3: 0x6BB4,
    0x89A4: 0x738B,
    0x89A5: 0x7FC1,
    0x89A6: 0x8956,
    0x89A7: 0x9D2C,
    0x89A8: 0x9D0E,
    0x89A9: 0x9EC4,
    0x89AA: 0x5CA1,
    0x89AB: 0x6C96,
    0x89AC: 0x837B,
    0x89AD: 0x5104,
    0x89AE: 0x5C4B,
    0x89AF: 0x61B6,
    0x89B0: 0x81C6,
    0x89B1: 0x6876,
    0x89B2: 0x7261,
    0x89B3: 0x4E59,
    0x89B4: 0x4FFA,
    0x89B5: 0x5378,
    0x89B6: 0x6069,
    0x89B7: 0x6E29,
    0x89B8: 0x7A4F,
    0x89B9: 0x97F3,
    0x89BA: 0x4E0B,
    0x89BB: 0x5316,
    0x89BC: 0x4EEE,
    0x89BD: 0x4F55,
    0x89BE: 0x4F3D,
    0x89BF: 0x4FA1,
    0x89C0: 0x4F73,
    0x89C1: 0x52A0,
    0x89C2: 0x53EF,
    0x89C3: 0x5609,
    0x89C4: 0x590F,
    0x89C5: 0x5AC1,
    0x89C6: 0x5BB6,
    0x89C7: 0x5BE1,
    0x89C8: 0x79D1,
    0x89C9: 0x6687,
    0x89CA: 0x679C,
    0x89CB: 0x67B6,
    0x89CC: 0x6B4C,
    0x89CD: 0x6CB3,
    0x89CE: 0x706B,
    0x89CF: 0x73C2,
    0x89D0: 0x798D,
    0x89D1: 0x79BE,
    0x89D2: 0x7A3C,
    0x89D3: 0x7B87,
    0x89D4: 0x82B1,
    0x89D5: 0x82DB,
    0x89D6: 0x8304,
    0x89D7: 0x8377,
    0x89D8: 0x83EF,
    0x89D9: 0x83D3,
    0x89DA: 0x8766,
    0x89DB: 0x8AB2,
    0x89DC: 0x5629,
    0x89DD: 0x8CA8,
    0x89DE: 0x8FE6,
    0x89DF: 0x904E,
    0x89E0: 0x971E,
    0x89E1: 0x868A,
    0x89E2: 0x4FC4,
    0x89E3: 0x5CE8,
    0x89E4: 0x6211,
    0x89E5: 0x7259,
    0x89E6: 0x753B,
    0x89E7: 0x81E5,
    0x89E8: 0x82BD,
    0x89E9: 0x86FE,
    0x89EA: 0x8CC0,
    0x89EB: 0x96C5,
    0x89EC: 0x9913,
    0x89ED: 0x99D5,
    0x89EE: 0x4ECB,
    0x89EF: 0x4F1A,
    0x89F0: 0x89E3,
    0x89F1: 0x56DE,
    0x89F2: 0x584A,
    0x89F3: 0x58CA,
    0x89F4: 0x5EFB,
    0x89F5: 0x5FEB,
    0x89F6: 0x602A,
    0x89F7: 0x6094,
    0x89F8: 0x6062,
    0x89F9: 0x61D0,
    0x89FA: 0x6212,
    0x89FB: 0x62D0,
    0x89FC: 0x6539,
    0x8A40: 0x9B41,
    0x8A41: 0x6666,
    0x8A42: 0x68B0,
    0x8A43: 0x6D77,
    0x8A44: 0x7070,
    0x8A45: 0x754C,
    0x8A46: 0x7686,
    0x8A47: 0x7D75,
    0x8A48: 0x82A5,
    0x8A49: 0x87F9,
    0x8A4A: 0x958B,
    0x8A4B: 0x968E,
    0x8A4C: 0x8C9D,
    0x8A4D: 0x51F1,
    0x8A4E: 0x52BE,
    0x8A4F: 0x5916,
    0x8A50: 0x54B3,
    0x8A51: 0x5BB3,
    0x8A52: 0x5D16,
    0x8A53: 0x6168,
    0x8A54: 0x6982,
    0x8A55: 0x6DAF,
    0x8A56: 0x788D,
    0x8A57: 0x84CB,
    0x8A58: 0x8857,
    0x8A59: 0x8A72,
    0x8A5A: 0x93A7,
    0x8A5B: 0x9AB8,
    0x8A5C: 0x6D6C,
    0x8A5D: 0x99A8,
    0x8A5E: 0x86D9,
    0x8A5F: 0x57A3,
    0x8A60: 0x67FF,
    0x8A61: 0x86CE,
    0x8A62: 0x920E,
    0x8A63: 0x5283,
    0x8A64: 0x5687,
    0x8A65: 0x5404,
    0x8A66: 0x5ED3,
    0x8A67: 0x62E1,
    0x8A68: 0x64B9,
    0x8A69: 0x683C,
    0x8A6A: 0x6838,
    0x8A6B: 0x6BBB,
    0x8A6C: 0x7372,
    0x8A6D: 0x78BA,
    0x8A6E: 0x7A6B,
    0x8A6F: 0x899A,
    0x8A70: 0x89D2,
    0x8A71: 0x8D6B,
    0x8A72: 0x8F03,
    0x8A73: 0x90ED,
    0x8A74: 0x95A3,
    0x8A75: 0x9694,
    0x8A76: 0x9769,
    0x8A77: 0x5B66,
    0x8A78: 0x5CB3,
    0x8A79: 0x697D,
    0x8A7A: 0x984D,
    0x8A7B: 0x984E,
    0x8A7C: 0x639B,
    0x8A7D: 0x7B20,
    0x8A7E: 0x6A2B,
    0x8A80: 0x6A7F,
    0x8A81: 0x68B6,
    0x8A82: 0x9C0D,
    0x8A83: 0x6F5F,
    0x8A84: 0x5272,
    0x8A85: 0x559D,
    0x8A86: 0x6070,
    0x8A87: 0x62EC,
    0x8A88: 0x6D3B,
    0x8A89: 0x6E07,
    0x8A8A: 0x6ED1,
    0x8A8B: 0x845B,
    0x8A8C: 0x8910,
    0x8A8D: 0x8F44,
    0x8A8E: 0x4E14,
    0x8A8F: 0x9C39,
    0x8A90: 0x53F6,
    0x8A91: 0x691B,
    0x8A92: 0x6A3A,
    0x8A93: 0x9784,
    0x8A94: 0x682A,
    0x8A95: 0x515C,
    0x8A96: 0x7AC3,
    0x8A97: 0x84B2,
    0x8A98: 0x91DC,
    0x8A99: 0x938C,
    0x8A9A: 0x565B,
    0x8A9B: 0x9D28,
    0x8A9C: 0x6822,
    0x8A9D: 0x8305,
    0x8A9E: 0x8431,
    0x8A9F: 0x7CA5,
    0x8AA0: 0x5208,
    0x8AA1: 0x82C5,
    0x8AA2: 0x74E6,
    0x8AA3: 0x4E7E,
    0x8AA4: 0x4F83,
    0x8AA5: 0x51A0,
    0x8AA6: 0x5BD2,
    0x8AA7: 0x520A,
    0x8AA8: 0x52D8,
    0x8AA9: 0x52E7,
    0x8AAA: 0x5DFB,
    0x8AAB: 0x559A,
    0x8AAC: 0x582A,
    0x8AAD: 0x59E6,
    0x8AAE: 0x5B8C,
    0x8AAF: 0x5B98,
    0x8AB0: 0x5BDB,
    0x8AB1: 0x5E72,
    0x8AB2: 0x5E79,
    0x8AB3: 0x60A3,
    0x8AB4: 0x611F,
    0x8AB5: 0x6163,
    0x8AB6: 0x61BE,
    0x8AB7: 0x63DB,
    0x8AB8: 0x6562,
    0x8AB9: 0x67D1,
    0x8ABA: 0x6853,
    0x8ABB: 0x68FA,
    0x8ABC: 0x6B3E,
    0x8ABD: 0x6B53,
    0x8ABE: 0x6C57,
    0x8ABF: 0x6F22,
    0x8AC0: 0x6F97,
    0x8AC1: 0x6F45,
    0x8AC2: 0x74B0,
    0x8AC3: 0x7518,
    0x8AC4: 0x76E3,
    0x8AC5: 0x770B,
    0x8AC6: 0x7AFF,
    0x8AC7: 0x7BA1,
    0x8AC8: 0x7C21,
    0x8AC9: 0x7DE9,
    0x8ACA: 0x7F36,
    0x8ACB: 0x7FF0,
    0x8ACC: 0x809D,
    0x8ACD: 0x8266,
    0x8ACE: 0x839E,
    0x8ACF: 0x89B3,
    0x8AD0: 0x8ACC,
    0x8AD1: 0x8CAB,
    0x8AD2: 0x9084,
    0x8AD3: 0x9451,
    0x8AD4: 0x9593,
    0x8AD5: 0x9591,
    0x8AD6: 0x95A2,
    0x8AD7: 0x9665,
    0x8AD8: 0x97D3,
    0x8AD9: 0x9928,
    0x8ADA: 0x8218,
    0x8ADB: 0x4E38,
    0x8ADC: 0x542B,
    0x8ADD: 0x5CB8,
    0x8ADE: 0x5DCC,
    0x8ADF: 0x73A9,
    0x8AE0: 0x764C,
    0x8AE1: 0x773C,
    0x8AE2: 0x5CA9,
    0x8AE3: 0x7FEB,
    0x8AE4: 0x8D0B,
    0x8AE5: 0x96C1,
    0x8AE6: 0x9811,
    0x8AE7: 0x9854,
    0x8AE8: 0x9858,
    0x8AE9: 0x4F01,
    0x8AEA: 0x4F0E,
    0x8AEB: 0x5371,
    0x8AEC: 0x559C,
    0x8AED: 0x5668,
    0x8AEE: 0x57FA,
    0x8AEF: 0x5947,
    0x8AF0: 0x5B09,
    0x8AF1: 0x5BC4,
    0x8AF2: 0x5C90,
    0x8AF3: 0x5E0C,
    0x8AF4: 0x5E7E,
    0x8AF5: 0x5FCC,
    0x8AF6: 0x63EE,
    0x8AF7: 0x673A,
    0x8AF8: 0x65D7,
    0x8AF9: 0x65E2,
    0x8AFA: 0x671F,
    0x8AFB: 0x68CB,
    0x8AFC: 0x68C4,
    0x8B40: 0x6A5F,
    0x8B41: 0x5E30,
    0x8B42: 0x6BC5,
    0x8B43: 0x6C17,
    0x8B44: 0x6C7D,
    0x8B45: 0x757F,
    0x8B46: 0x7948,
    0x8B47: 0x5B63,
    0x8B48: 0x7A00,
    0x8B49: 0x7D00,
    0x8B4A: 0x5FBD,
    0x8B4B: 0x898F,
    0x8B4C: 0x8A18,
    0x8B4D: 0x8CB4,
    0x8B4E: 0x8D77,
    0x8B4F: 0x8ECC,
    0x8B50: 0x8F1D,
    0x8B51: 0x98E2,
    0x8B52: 0x9A0E,
    0x8B53: 0x9B3C,
    0x8B54: 0x4E80,
    0x8B55: 0x507D,
    0x8B56: 0x5100,
    0x8B57: 0x5993,
    0x8B58: 0x5B9C,
    0x8B59: 0x622F,
    0x8B5A: 0x6280,
    0x8B5B: 0x64EC,
    0x8B5C: 0x6B3A,
    0x8B5D: 0x72A0,
    0x8B5E: 0x7591,
    0x8B5F: 0x7947,
    0x8B60: 0x7FA9,
    0x8B61: 0x87FB,
    0x8B62: 0x8ABC,
    0x8B63: 0x8B70,
    0x8B64: 0x63AC,
    0x8B65: 0x83CA,
    0x8B66: 0x97A0,
    0x8B67: 0x5409,
    0x8B68: 0x5403,
    0x8B69: 0x55AB,
    0x8B6A: 0x6854,
    0x8B6B: 0x6A58,
    0x8B6C: 0x8A70,
    0x8B6D: 0x7827,
    0x8B6E: 0x6775,
    0x8B6F: 0x9ECD,
    0x8B70: 0x5374,
    0x8B71: 0x5BA2,
    0x8B72: 0x811A,
    0x8B73: 0x8650,
    0x8B74: 0x9006,
    0x8B75: 0x4E18,
    0x8B76: 0x4E45,
    0x8B77: 0x4EC7,
    0x8B78: 0x4F11,
    0x8B79: 0x53CA,
    0x8B7A: 0x5438,
    0x8B7B: 0x5BAE,
    0x8B7C: 0x5F13,
    0x8B7D: 0x6025,
    0x8B7E: 0x6551,
    0x8B80: 0x673D,
    0x8B81: 0x6C42,
    0x8B82: 0x6C72,
    0x8B83: 0x6CE3,
    0x8B84: 0x7078,
    0x8B85: 0x7403,
    0x8B86: 0x7A76,
    0x8B87: 0x7AAE,
    0x8B88: 0x7B08,
    0x8B89: 0x7D1A,
    0x8B8A: 0x7CFE,
    0x8B8B: 0x7D66,
    0x8B8C: 0x65E7,
    0x8B8D: 0x725B,
    0x8B8E: 0x53BB,
    0x8B8F: 0x5C45,
    0x8B90: 0x5DE8,
    0x8B91: 0x62D2,
    0x8B92: 0x62E0,
    0x8B93: 0x6319,
    0x8B94: 0x6E20,
    0x8B95: 0x865A,
    0x8B96: 0x8A31,
    0x8B97: 0x8DDD,
    0x8B98: 0x92F8,
    0x8B99: 0x6F01,
    0x8B9A: 0x79A6,
    0x8B9B: 0x9B5A,
    0x8B9C: 0x4EA8,
    0x8B9D: 0x4EAB,
    0x8B9E: 0x4EAC,
    0x8B9F: 0x4F9B,
    0x8BA0: 0x4FA0,
    0x8BA1: 0x50D1,
    0x8BA2: 0x5147,
    0x8BA3: 0x7AF6,
    0x8BA4: 0x5171,
    0x8BA5: 0x51F6,
    0x8BA6: 0x5354,
    0x8BA7: 0x5321,
    0x8BA8: 0x537F,
    0x8BA9: 0x53EB,
    0x8BAA: 0x55AC,
    0x8BAB: 0x5883,
    0x8BAC: 0x5CE1,
    0x8BAD: 0x5F37,
    0x8BAE: 0x5F4A,
    0x8BAF: 0x602F,
    0x8BB0: 0x6050,
    0x8BB1: 0x606D,
    0x8BB2: 0x631F,
    0x8BB3: 0x6559,
    0x8BB4: 0x6A4B,
    0x8BB5: 0x6CC1,
    0x8BB6: 0x72C2,
    0x8BB7: 0x72ED,
    0x8BB8: 0x77EF,
    0x8BB9: 0x80F8,
    0x8BBA: 0x8105,
    0x8BBB: 0x8208,
    0x8BBC: 0x854E,
    0x8BBD: 0x90F7,
    0x8BBE: 0x93E1,
    0x8BBF: 0x97FF,
    0x8BC0: 0x9957,
    0x8BC1: 0x9A5A,
    0x8BC2: 0x4EF0,
    0x8BC3: 0x51DD,
    0x8BC4: 0x5C2D,
    0x8BC5: 0x6681,
    0x8BC6: 0x696D,
    0x8BC7: 0x5C40,
    0x8BC8: 0x66F2,
    0x8BC9: 0x6975,
    0x8BCA: 0x7389,
    0x8BCB: 0x6850,
    0x8BCC: 0x7C81,
    0x8BCD: 0x50C5,
    0x8BCE: 0x52E4,
    0x8BCF: 0x5747,
    0x8BD0: 0x5DFE,
    0x8BD1: 0x9326,
    0x8BD2: 0x65A4,
    0x8BD3: 0x6B23,
    0x8BD4: 0x6B3D,
    0x8BD5: 0x7434,
    0x8BD6: 0x7981,
    0x8BD7: 0x79BD,
    0x8BD8: 0x7B4B,
    0x8BD9: 0x7DCA,
    0x8BDA: 0x82B9,
    0x8BDB: 0x83CC,
    0x8BDC: 0x887F,
    0x8BDD: 0x895F,
    0x8BDE: 0x8B39,
    0x8BDF: 0x8FD1,
    0x8BE0: 0x91D1,
    0x8BE1: 0x541F,
    0x8BE2: 0x9280,
    0x8BE3: 0x4E5D,
    0x8BE4: 0x5036,
    0x8BE5: 0x53E5,
    0x8BE6: 0x533A,
    0x8BE7: 0x72D7,
    0x8BE8: 0x7396,
    0x8BE9: 0x77E9,
    0x8BEA: 0x82E6,
    0x8BEB: 0x8EAF,
    0x8BEC: 0x99C6,
    0x8BED: 0x99C8,
    0x8BEE: 0x99D2,
    0x8BEF: 0x5177,
    0x8BF0: 0x611A,
    0x8BF1: 0x865E,
    0x8BF2: 0x55B0,
    0x8BF3: 0x7A7A,
    0x8BF4: 0x5076,
    0x8BF5: 0x5BD3,
    0x8BF6: 0x9047,
    0x8BF7: 0x9685,
    0x8BF8: 0x4E32,
    0x8BF9: 0x6ADB,
    0x8BFA: 0x91E7,
    0x8BFB: 0x5C51,
    0x8BFC: 0x5C48,
    0x8C40: 0x6398,
    0x8C41: 0x7A9F,
    0x8C42: 0x6C93,
    0x8C43: 0x9774,
    0x8C44: 0x8F61,
    0x8C45: 0x7AAA,
    0x8C46: 0x718A,
    0x8C47: 0x9688,
    0x8C48: 0x7C82,
    0x8C49: 0x6817,
    0x8C4A: 0x7E70,
    0x8C4B: 0x6851,
    0x8C4C: 0x936C,
    0x8C4D: 0x52F2,
    0x8C4E: 0x541B,
    0x8C4F: 0x85AB,
    0x8C50: 0x8A13,
    0x8C51: 0x7FA4,
    0x8C52: 0x8ECD,
    0x8C53: 0x90E1,
    0x8C54: 0x5366,
    0x8C55: 0x8888,
    0x8C56: 0x7941,
    0x8C57: 0x4FC2,
    0x8C58: 0x50BE,
    0x8C59: 0x5211,
    0x8C5A: 0x5144,
    0x8C5B: 0x5553,
    0x8C5C: 0x572D,
    0x8C5D: 0x73EA,
    0x8C5E: 0x578B,
    0x8C5F: 0x5951,
    0x8C60: 0x5F62,
    0x8C61: 0x5F84,
    0x8C62: 0x6075,
    0x8C63: 0x6176,
    0x8C64: 0x6167,
    0x8C65: 0x61A9,
    0x8C66: 0x63B2,
    0x8C67: 0x643A,
    0x8C68: 0x656C,
    0x8C69: 0x666F,
    0x8C6A: 0x6842,
    0x8C6B: 0x6E13,
    0x8C6C: 0x7566,
    0x8C6D: 0x7A3D,
    0x8C6E: 0x7CFB,
    0x8C6F: 0x7D4C,
    0x8C70: 0x7D99,
    0x8C71: 0x7E4B,
    0x8C72: 0x7F6B,
    0x8C73: 0x830E,
    0x8C74: 0x834A,
    0x8C75: 0x86CD,
    0x8C76: 0x8A08,
    0x8C77: 0x8A63,
    0x8C78: 0x8B66,
    0x8C79: 0x8EFD,
    0x8C7A: 0x981A,
    0x8C7B: 0x9D8F,
    0x8C7C: 0x82B8,
    0x8C7D: 0x8FCE,
    0x8C7E: 0x9BE8,
    0x8C80: 0x5287,
    0x8C81: 0x621F,
    0x8C82: 0x6483,
    0x8C83: 0x6FC0,
    0x8C84: 0x9699,
    0x8C85: 0x6841,
    0x8C86: 0x5091,
    0x8C87: 0x6B20,
    0x8C88: 0x6C7A,
    0x8C89: 0x6F54,
    0x8C8A: 0x7A74,
    0x8C8B: 0x7D50,
    0x8C8C: 0x8840,
    0x8C8D: 0x8A23,
    0x8C8E: 0x6708,
    0x8C8F: 0x4EF6,
    0x8C90: 0x5039,
    0x8C91: 0x5026,
    0x8C92: 0x5065,
    0x8C93: 0x517C,
    0x8C94: 0x5238,
    0x8C95: 0x5263,
    0x8C96: 0x55A7,
    0x8C97: 0x570F,
    0x8C98: 0x5805,
    0x8C99: 0x5ACC,
    0x8C9A: 0x5EFA,
    0x8C9B: 0x61B2,
    0x8C9C: 0x61F8,
    0x8C9D: 0x62F3,
    0x8C9E: 0x6372,
    0x8C9F: 0x691C,
    0x8CA0: 0x6A29,
    0x8CA1: 0x727D,
    0x8CA2: 0x72AC,
    0x8CA3: 0x732E,
    0x8CA4: 0x7814,
    0x8CA5: 0x786F,
    0x8CA6: 0x7D79,
    0x8CA7: 0x770C,
    0x8CA8: 0x80A9,
    0x8CA9: 0x898B,
    0x8CAA: 0x8B19,
    0x8CAB: 0x8CE2,
    0x8CAC: 0x8ED2,
    0x8CAD: 0x9063,
    0x8CAE: 0x9375,
    0x8CAF: 0x967A,
    0x8CB0: 0x9855,
    0x8CB1: 0x9A13,
    0x8CB2: 0x9E78,
    0x8CB3: 0x5143,
    0x8CB4: 0x539F,
    0x8CB5: 0x53B3,
    0x8CB6: 0x5E7B,
    0x8CB7: 0x5F26,
    0x8CB8: 0x6E1B,
    0x8CB9: 0x6E90,
    0x8CBA: 0x7384,
    0x8CBB: 0x73FE,
    0x8CBC: 0x7D43,
    0x8CBD: 0x8237,
    0x8CBE: 0x8A00,
    0x8CBF: 0x8AFA,
    0x8CC0: 0x9650,
    0x8CC1: 0x4E4E,
    0x8CC2: 0x500B,
    0x8CC3: 0x53E4,
    0x8CC4: 0x547C,
    0x8CC5: 0x56FA,
    0x8CC6: 0x59D1,
    0x8CC7: 0x5B64,
    0x8CC8: 0x5DF1,
    0x8CC9: 0x5EAB,
    0x8CCA: 0x5F27,
    0x8CCB: 0x6238,
    0x8CCC: 0x6545,
    0x8CCD: 0x67AF,
    0x8CCE: 0x6E56,
    0x8CCF: 0x72D0,
    0x8CD0: 0x7CCA,
    0x8CD1: 0x88B4,
    0x8CD2: 0x80A1,
    0x8CD3: 0x80E1,
    0x8CD4: 0x83F0,
    0x8CD5: 0x864E,
    0x8CD6: 0x8A87,
    0x8CD7: 0x8DE8,
    0x8CD8: 0x9237,
    0x8CD9: 0x96C7,
    0x8CDA: 0x9867,
    0x8CDB: 0x9F13,
    0x8CDC: 0x4E94,
    0x8CDD: 0x4E92,
    0x8CDE: 0x4F0D,
    0x8CDF: 0x5348,
    0x8CE0: 0x5449,
    0x8CE1: 0x543E,
    0x8CE2: 0x5A2F,
    0x8CE3: 0x5F8C,
    0x8CE4: 0x5FA1,
    0x8CE5: 0x609F,
    0x8CE6: 0x68A7,
    0x8CE7: 0x6A8E,
    0x8CE8: 0x745A,
    0x8CE9: 0x7881,
    0x8CEA: 0x8A9E,
    0x8CEB: 0x8AA4,
    0x8CEC: 0x8B77,
    0x8CED: 0x9190,
    0x8CEE: 0x4E5E,
    0x8CEF: 0x9BC9,
    0x8CF0: 0x4EA4,
    0x8CF1: 0x4F7C,
    0x8CF2: 0x4FAF,
    0x8CF3: 0x5019,
    0x8CF4: 0x5016,
    0x8CF5: 0x5149,
    0x8CF6: 0x516C,
    0x8CF7: 0x529F,
    0x8CF8: 0x52B9,
    0x8CF9: 0x52FE,
    0x8CFA: 0x539A,
    0x8CFB: 0x53E3,
    0x8CFC: 0x5411,
    0x8D40: 0x540E,
    0x8D41: 0x5589,
    0x8D42: 0x5751,
    0x8D43: 0x57A2,
    0x8D44: 0x597D,
    0x8D45: 0x5B54,
    0x8D46: 0x5B5D,
    0x8D47: 0x5B8F,
    0x8D48: 0x5DE5,
    0x8D49: 0x5DE7,
    0x8D4A: 0x5DF7,
    0x8D4B: 0x5E78,
    0x8D4C: 0x5E83,
    0x8D4D: 0x5E9A,
    0x8D4E: 0x5EB7,
    0x8D4F: 0x5F18,
    0x8D50: 0x6052,
    0x8D51: 0x614C,
    0x8D52: 0x6297,
    0x8D53: 0x62D8,
    0x8D54: 0x63A7,
    0x8D55: 0x653B,
    0x8D56: 0x6602,
    0x8D57: 0x6643,
    0x8D58: 0x66F4,
    0x8D59: 0x676D,
    0x8D5A: 0x6821,
    0x8D5B: 0x6897,
    0x8D5C: 0x69CB,
    0x8D5D: 0x6C5F,
    0x8D5E: 0x6D2A,
    0x8D5F: 0x6D69,
    0x8D60: 0x6E2F,
    0x8D61: 0x6E9D,
    0x8D62: 0x7532,
    0x8D63: 0x7687,
    0x8D64: 0x786C,
    0x8D65: 0x7A3F,
    0x8D66: 0x7CE0,
    0x8D67: 0x7D05,
    0x8D68: 0x7D18,
    0x8D69: 0x7D5E,
    0x8D6A: 0x7DB1,
    0x8D6B: 0x8015,
    0x8D6C: 0x8003,
    0x8D6D: 0x80AF,
    0x8D6E: 0x80B1,
    0x8D6F: 0x8154,
    0x8D70: 0x818F,
    0x8D71: 0x822A,
    0x8D72: 0x8352,
    0x8D73: 0x884C,
    0x8D74: 0x8861,
    0x8D75: 0x8B1B,
    0x8D76: 0x8CA2,
    0x8D77: 0x8CFC,
    0x8D78: 0x90CA,
    0x8D79: 0x9175,
    0x8D7A: 0x9271,
    0x8D7B: 0x783F,
    0x8D7C: 0x92FC,
    0x8D7D: 0x95A4,
    0x8D7E: 0x964D,
    0x8D80: 0x9805,
    0x8D81: 0x9999,
    0x8D82: 0x9AD8,
    0x8D83: 0x9D3B,
    0x8D84: 0x525B,
    0x8D85: 0x52AB,
    0x8D86: 0x53F7,
    0x8D87: 0x5408,
    0x8D88: 0x58D5,
    0x8D89: 0x62F7,
    0x8D8A: 0x6FE0,
    0x8D8B: 0x8C6A,
    0x8D8C: 0x8F5F,
    0x8D8D: 0x9EB9,
    0x8D8E: 0x514B,
    0x8D8F: 0x523B,
    0x8D90: 0x544A,
    0x8D91: 0x56FD,
    0x8D92: 0x7A40,
    0x8D93: 0x9177,
    0x8D94: 0x9D60,
    0x8D95: 0x9ED2,
    0x8D96: 0x7344,
    0x8D97: 0x6F09,
    0x8D98: 0x8170,
    0x8D99: 0x7511,
    0x8D9A: 0x5FFD,
    0x8D9B: 0x60DA,
    0x8D9C: 0x9AA8,
    0x8D9D: 0x72DB,
    0x8D9E: 0x8FBC,
    0x8D9F: 0x6B64,
    0x8DA0: 0x9803,
    0x8DA1: 0x4ECA,
    0x8DA2: 0x56F0,
    0x8DA3: 0x5764,
    0x8DA4: 0x58BE,
    0x8DA5: 0x5A5A,
    0x8DA6: 0x6068,
    0x8DA7: 0x61C7,
    0x8DA8: 0x660F,
    0x8DA9: 0x6606,
    0x8DAA: 0x6839,
    0x8DAB: 0x68B1,
    0x8DAC: 0x6DF7,
    0x8DAD: 0x75D5,
    0x8DAE: 0x7D3A,
    0x8DAF: 0x826E,
    0x8DB0: 0x9B42,
    0x8DB1: 0x4E9B,
    0x8DB2: 0x4F50,
    0x8DB3: 0x53C9,
    0x8DB4: 0x5506,
    0x8DB5: 0x5D6F,
    0x8DB6: 0x5DE6,
    0x8DB7: 0x5DEE,
    0x8DB8: 0x67FB,
    0x8DB9: 0x6C99,
    0x8DBA: 0x7473,
    0x8DBB: 0x7802,
    0x8DBC: 0x8A50,
    0x8DBD: 0x9396,
    0x8DBE: 0x88DF,
    0x8DBF: 0x5750,
    0x8DC0: 0x5EA7,
    0x8DC1: 0x632B,
    0x8DC2: 0x50B5,
    0x8DC3: 0x50AC,
    0x8DC4: 0x518D,
    0x8DC5: 0x6700,
    0x8DC6: 0x54C9,
    0x8DC7: 0x585E,
    0x8DC8: 0x59BB,
    0x8DC9: 0x5BB0,
    0x8DCA: 0x5F69,
    0x8DCB: 0x624D,
    0x8DCC: 0x63A1,
    0x8DCD: 0x683D,
    0x8DCE: 0x6B73,
    0x8DCF: 0x6E08,
    0x8DD0: 0x707D,
    0x8DD1: 0x91C7,
    0x8DD2: 0x7280,
    0x8DD3: 0x7815,
    0x8DD4: 0x7826,
    0x8DD5: 0x796D,
    0x8DD6: 0x658E,
    0x8DD7: 0x7D30,
    0x8DD8: 0x83DC,
    0x8DD9: 0x88C1,
    0x8DDA: 0x8F09,
    0x8DDB: 0x969B,
    0x8DDC: 0x5264,
    0x8DDD: 0x5728,
    0x8DDE: 0x6750,
    0x8DDF: 0x7F6A,
    0x8DE0: 0x8CA1,
    0x8DE1: 0x51B4,
    0x8DE2: 0x5742,
    0x8DE3: 0x962A,
    0x8DE4: 0x583A,
    0x8DE5: 0x698A,
    0x8DE6: 0x80B4,
    0x8DE7: 0x54B2,
    0x8DE8: 0x5D0E,
    0x8DE9: 0x57FC,
    0x8DEA: 0x7895,
    0x8DEB: 0x9DFA,
    0x8DEC: 0x4F5C,
    0x8DED: 0x524A,
    0x8DEE: 0x548B,
    0x8DEF: 0x643E,
    0x8DF0: 0x6628,
    0x8DF1: 0x6714,
    0x8DF2: 0x67F5,
    0x8DF3: 0x7A84,
    0x8DF4: 0x7B56,
    0x8DF5: 0x7D22,
    0x8DF6: 0x932F,
    0x8DF7: 0x685C,
    0x8DF8: 0x9BAD,
    0x8DF9: 0x7B39,
    0x8DFA: 0x5319,
    0x8DFB: 0x518A,
    0x8DFC: 0x5237,
    0x8E40: 0x5BDF,
    0x8E41: 0x62F6,
    0x8E42: 0x64AE,
    0x8E43: 0x64E6,
    0x8E44: 0x672D,
    0x8E45: 0x6BBA,
    0x8E46: 0x85A9,
    0x8E47: 0x96D1,
    0x8E48: 0x7690,
    0x8E49: 0x9BD6,
    0x8E4A: 0x634C,
    0x8E4B: 0x9306,
    0x8E4C: 0x9BAB,
    0x8E4D: 0x76BF,
    0x8E4E: 0x6652,
    0x8E4F: 0x4E09,
    0x8E50: 0x5098,
    0x8E51: 0x53C2,
    0x8E52: 0x5C71,
    0x8E53: 0x60E8,
    0x8E54: 0x6492,
    0x8E55: 0x6563,
    0x8E56: 0x685F,
    0x8E57: 0x71E6,
    0x8E58: 0x73CA,
    0x8E59: 0x7523,
    0x8E5A: 0x7B97,
    0x8E5B: 0x7E82,
    0x8E5C: 0x8695,
    0x8E5D: 0x8B83,
    0x8E5E: 0x8CDB,
    0x8E5F: 0x9178,
    0x8E60: 0x9910,
    0x8E61: 0x65AC,
    0x8E62: 0x66AB,
    0x8E63: 0x6B8B,
    0x8E64: 0x4ED5,
    0x8E65: 0x4ED4,
    0x8E66: 0x4F3A,
    0x8E67: 0x4F7F,
    0x8E68: 0x523A,
    0x8E69: 0x53F8,
    0x8E6A: 0x53F2,
    0x8E6B: 0x55E3,
    0x8E6C: 0x56DB,
    0x8E6D: 0x58EB,
    0x8E6E: 0x59CB,
    0x8E6F: 0x59C9,
    0x8E70: 0x59FF,
    0x8E71: 0x5B50,
    0x8E72: 0x5C4D,
    0x8E73: 0x5E02,
    0x8E74: 0x5E2B,
    0x8E75: 0x5FD7,
    0x8E76: 0x601D,
    0x8E77: 0x6307,
    0x8E78: 0x652F,
    0x8E79: 0x5B5C,
    0x8E7A: 0x65AF,
    0x8E7B: 0x65BD,
    0x8E7C: 0x65E8,
    0x8E7D: 0x679D,
    0x8E7E: 0x6B62,
    0x8E80: 0x6B7B,
    0x8E81: 0x6C0F,
    0x8E82: 0x7345,
    0x8E83: 0x7949,
    0x8E84: 0x79C1,
    0x8E85: 0x7CF8,
    0x8E86: 0x7D19,
    0x8E87: 0x7D2B,
    0x8E88: 0x80A2,
    0x8E89: 0x8102,
    0x8E8A: 0x81F3,
    0x8E8B: 0x8996,
    0x8E8C: 0x8A5E,
    0x8E8D: 0x8A69,
    0x8E8E: 0x8A66,
    0x8E8F: 0x8A8C,
    0x8E90: 0x8AEE,
    0x8E91: 0x8CC7,
    0x8E92: 0x8CDC,
    0x8E93: 0x96CC,
    0x8E94: 0x98FC,
    0x8E95: 0x6B6F,
    0x8E96: 0x4E8B,
    0x8E97: 0x4F3C,
    0x8E98: 0x4F8D,
    0x8E99: 0x5150,
    0x8E9A: 0x5B57,
    0x8E9B: 0x5BFA,
    0x8E9C: 0x6148,
    0x8E9D: 0x6301,
    0x8E9E: 0x6642,
    0x8E9F: 0x6B21,
    0x8EA0: 0x6ECB,
    0x8EA1: 0x6CBB,
    0x8EA2: 0x723E,
    0x8EA3: 0x74BD,
    0x8EA4: 0x75D4,
    0x8EA5: 0x78C1,
    0x8EA6: 0x793A,
    0x8EA7: 0x800C,
    0x8EA8: 0x8033,
    0x8EA9: 0x81EA,
    0x8EAA: 0x8494,
    0x8EAB: 0x8F9E,
    0x8EAC: 0x6C50,
    0x8EAD: 0x9E7F,
    0x8EAE: 0x5F0F,
    0x8EAF: 0x8B58,
    0x8EB0: 0x9D2B,
    0x8EB1: 0x7AFA,
    0x8EB2: 0x8EF8,
    0x8EB3: 0x5B8D,
    0x8EB4: 0x96EB,
    0x8EB5: 0x4E03,
    0x8EB6: 0x53F1,
    0x8EB7: 0x57F7,
    0x8EB8: 0x5931,
    0x8EB9: 0x5AC9,
    0x8EBA: 0x5BA4,
    0x8EBB: 0x6089,
    0x8EBC: 0x6E7F,
    0x8EBD: 0x6F06,
    0x8EBE: 0x75BE,
    0x8EBF: 0x8CEA,
    0x8EC0: 0x5B9F,
    0x8EC1: 0x8500,
    0x8EC2: 0x7BE0,
    0x8EC3: 0x5072,
    0x8EC4: 0x67F4,
    0x8EC5: 0x829D,
    0x8EC6: 0x5C61,
    0x8EC7: 0x854A,
    0x8EC8: 0x7E1E,
    0x8EC9: 0x820E,
    0x8ECA: 0x5199,
    0x8ECB: 0x5C04,
    0x8ECC: 0x6368,
    0x8ECD: 0x8D66,
    0x8ECE: 0x659C,
    0x8ECF: 0x716E,
    0x8ED0: 0x793E,
    0x8ED1: 0x7D17,
    0x8ED2: 0x8005,
    0x8ED3: 0x8B1D,
    0x8ED4: 0x8ECA,
    0x8ED5: 0x906E,
    0x8ED6: 0x86C7,
    0x8ED7: 0x90AA,
    0x8ED8: 0x501F,
    0x8ED9: 0x52FA,
    0x8EDA: 0x5C3A,
    0x8EDB: 0x6753,
    0x8EDC: 0x707C,
    0x8EDD: 0x7235,
    0x8EDE: 0x914C,
    0x8EDF: 0x91C8,
    0x8EE0: 0x932B,
    0x8EE1: 0x82E5,
    0x8EE2: 0x5BC2,
    0x8EE3: 0x5F31,
    0x8EE4: 0x60F9,
    0x8EE5: 0x4E3B,
    0x8EE6: 0x53D6,
    0x8EE7: 0x5B88,
    0x8EE8: 0x624B,
    0x8EE9: 0x6731,
    0x8EEA: 0x6B8A,
    0x8EEB: 0x72E9,
    0x8EEC: 0x73E0,
    0x8EED: 0x7A2E,
    0x8EEE: 0x816B,
    0x8EEF: 0x8DA3,
    0x8EF0: 0x9152,
    0x8EF1: 0x9996,
    0x8EF2: 0x5112,
    0x8EF3: 0x53D7,
    0x8EF4: 0x546A,
    0x8EF5: 0x5BFF,
    0x8EF6: 0x6388,
    0x8EF7: 0x6A39,
    0x8EF8: 0x7DAC,
    0x8EF9: 0x9700,
    0x8EFA: 0x56DA,
    0x8EFB: 0x53CE,
    0x8EFC: 0x5468,
    0x8F40: 0x5B97,
    0x8F41: 0x5C31,
    0x8F42: 0x5DDE,
    0x8F43: 0x4FEE,
    0x8F44: 0x6101,
    0x8F45: 0x62FE,
    0x8F46: 0x6D32,
    0x8F47: 0x79C0,
    0x8F48: 0x79CB,
    0x8F49: 0x7D42,
    0x8F4A: 0x7E4D,
    0x8F4B: 0x7FD2,
    0x8F4C: 0x81ED,
    0x8F4D: 0x821F,
    0x8F4E: 0x8490,
    0x8F4F: 0x8846,
    0x8F50: 0x8972,
    0x8F51: 0x8B90,
    0x8F52: 0x8E74,
    0x8F53: 0x8F2F,
    0x8F54: 0x9031,
    0x8F55: 0x914B,
    0x8F56: 0x916C,
    0x8F57: 0x96C6,
    0x8F58: 0x919C,
    0x8F59: 0x4EC0,
    0x8F5A: 0x4F4F,
    0x8F5B: 0x5145,
    0x8F5C: 0x5341,
    0x8F5D: 0x5F93,
    0x8F5E: 0x620E,
    0x8F5F: 0x67D4,
    0x8F60: 0x6C41,
    0x8F61: 0x6E0B,
    0x8F62: 0x7363,
    0x8F63: 0x7E26,
    0x8F64: 0x91CD,
    0x8F65: 0x9283,
    0x8F66: 0x53D4,
    0x8F67: 0x5919,
    0x8F68: 0x5BBF,
    0x8F69: 0x6DD1,
    0x8F6A: 0x795D,
    0x8F6B: 0x7E2E,
    0x8F6C: 0x7C9B,
    0x8F6D: 0x587E,
    0x8F6E: 0x719F,
    0x8F6F: 0x51FA,
    0x8F70: 0x8853,
    0x8F71: 0x8FF0,
    0x8F72: 0x4FCA,
    0x8F73: 0x5CFB,
    0x8F74: 0x6625,
    0x8F75: 0x77AC,
    0x8F76: 0x7AE3,
    0x8F77: 0x821C,
    0x8F78: 0x99FF,
    0x8F79: 0x51C6,
    0x8F7A: 0x5FAA,
    0x8F7B: 0x65EC,
    0x8F7C: 0x696F,
    0x8F7D: 0x6B89,
    0x8F7E: 0x6DF3,
    0x8F80: 0x6E96,
    0x8F81: 0x6F64,
    0x8F82: 0x76FE,
    0x8F83: 0x7D14,
    0x8F84: 0x5DE1,
    0x8F85: 0x9075,
    0x8F86: 0x9187,
    0x8F87: 0x9806,
    0x8F88: 0x51E6,
    0x8F89: 0x521D,
    0x8F8A: 0x6240,
    0x8F8B: 0x6691,
    0x8F8C: 0x66D9,
    0x8F8D: 0x6E1A,
    0x8F8E: 0x5EB6,
    0x8F8F: 0x7DD2,
    0x8F90: 0x7F72,
    0x8F91: 0x66F8,
    0x8F92: 0x85AF,
    0x8F93: 0x85F7,
    0x8F94: 0x8AF8,
    0x8F95: 0x52A9,
    0x8F96: 0x53D9,
    0x8F97: 0x5973,
    0x8F98: 0x5E8F,
    0x8F99: 0x5F90,
    0x8F9A: 0x6055,
    0x8F9B: 0x92E4,
    0x8F9C: 0x9664,
    0x8F9D: 0x50B7,
    0x8F9E: 0x511F,
    0x8F9F: 0x52DD,
    0x8FA0: 0x5320,
    0x8FA1: 0x5347,
    0x8FA2: 0x53EC,
    0x8FA3: 0x54E8,
    0x8FA4: 0x5546,
    0x8FA5: 0x5531,
    0x8FA6: 0x5617,
    0x8FA7: 0x5968,
    0x8FA8: 0x59BE,
    0x8FA9: 0x5A3C,
    0x8FAA: 0x5BB5,
    0x8FAB: 0x5C06,
    0x8FAC: 0x5C0F,
    0x8FAD: 0x5C11,
    0x8FAE: 0x5C1A,
    0x8FAF: 0x5E84,
    0x8FB0: 0x5E8A,
    0x8FB1: 0x5EE0,
    0x8FB2: 0x5F70,
    0x8FB3: 0x627F,
    0x8FB4: 0x6284,
    0x8FB5: 0x62DB,
    0x8FB6: 0x638C,
    0x8FB7: 0x6377,
    0x8FB8: 0x6607,
    0x8FB9: 0x660C,
    0x8FBA: 0x662D,
    0x8FBB: 0x6676,
    0x8FBC: 0x677E,
    0x8FBD: 0x68A2,
    0x8FBE: 0x6A1F,
    0x8FBF: 0x6A35,
    0x8FC0: 0x6CBC,
    0x8FC1: 0x6D88,
    0x8FC2: 0x6E09,
    0x8FC3: 0x6E58,
    0x8FC4: 0x713C,
    0x8FC5: 0x7126,
    0x8FC6: 0x7167,
    0x8FC7: 0x75C7,
    0x8FC8: 0x7701,
    0x8FC9: 0x785D,
    0x8FCA: 0x7901,
    0x8FCB: 0x7965,
    0x8FCC: 0x79F0,
    0x8FCD: 0x7AE0,
    0x8FCE: 0x7B11,
    0x8FCF: 0x7CA7,
    0x8FD0: 0x7D39,
    0x8FD1: 0x8096,
    0x8FD2: 0x83D6,
    0x8FD3: 0x848B,
    0x8FD4: 0x8549,
    0x8FD5: 0x885D,
    0x8FD6: 0x88F3,
    0x8FD7: 0x8A1F,
    0x8FD8: 0x8A3C,
    0x8FD9: 0x8A54,
    0x8FDA: 0x8A73,
    0x8FDB: 0x8C61,
    0x8FDC: 0x8CDE,
    0x8FDD: 0x91A4,
    0x8FDE: 0x9266,
    0x8FDF: 0x937E,
    0x8FE0: 0x9418,
    0x8FE1: 0x969C,
    0x8FE2: 0x9798,
    0x8FE3: 0x4E0A,
    0x8FE4: 0x4E08,
    0x8FE5: 0x4E1E,
    0x8FE6: 0x4E57,
    0x8FE7: 0x5197,
    0x8FE8: 0x5270,
    0x8FE9: 0x57CE,
    0x8FEA: 0x5834,
    0x8FEB: 0x58CC,
    0x8FEC: 0x5B22,
    0x8FED: 0x5E38,
    0x8FEE: 0x60C5,
    0x8FEF: 0x64FE,
    0x8FF0: 0x6761,
    0x8FF1: 0x6756,
    0x8FF2: 0x6D44,
    0x8FF3: 0x72B6,
    0x8FF4: 0x7573,
    0x8FF5: 0x7A63,
    0x8FF6: 0x84B8,
    0x8FF7: 0x8B72,
    0x8FF8: 0x91B8,
    0x8FF9: 0x9320,
    0x8FFA: 0x5631,
    0x8FFB: 0x57F4,
    0x8FFC: 0x98FE,
    0x9040: 0x62ED,
    0x9041: 0x690D,
    0x9042: 0x6B96,
    0x9043: 0x71ED,
    0x9044: 0x7E54,
    0x9045: 0x8077,
    0x9046: 0x8272,
    0x9047: 0x89E6,
    0x9048: 0x98DF,
    0x9049: 0x8755,
    0x904A: 0x8FB1,
    0x904B: 0x5C3B,
    0x904C: 0x4F38,
    0x904D: 0x4FE1,
    0x904E: 0x4FB5,
    0x904F: 0x5507,
    0x9050: 0x5A20,
    0x9051: 0x5BDD,
    0x9052: 0x5BE9,
    0x9053: 0x5FC3,
    0x9054: 0x614E,
    0x9055: 0x632F,
    0x9056: 0x65B0,
    0x9057: 0x664B,
    0x9058: 0x68EE,
    0x9059: 0x699B,
    0x905A: 0x6D78,
    0x905B: 0x6DF1,
    0x905C: 0x7533,
    0x905D: 0x75B9,
    0x905E: 0x771F,
    0x905F: 0x795E,
    0x9060: 0x79E6,
    0x9061: 0x7D33,
    0x9062: 0x81E3,
    0x9063: 0x82AF,
    0x9064: 0x85AA,
    0x9065: 0x89AA,
    0x9066: 0x8A3A,
    0x9067: 0x8EAB,
    0x9068: 0x8F9B,
    0x9069: 0x9032,
    0x906A: 0x91DD,
    0x906B: 0x9707,
    0x906C: 0x4EBA,
    0x906D: 0x4EC1,
    0x906E: 0x5203,
    0x906F: 0x5875,
    0x9070: 0x58EC,
    0x9071: 0x5C0B,
    0x9072: 0x751A,
    0x9073: 0x5C3D,
    0x9074: 0x814E,
    0x9075: 0x8A0A,
    0x9076: 0x8FC5,
    0x9077: 0x9663,
    0x9078: 0x976D,
    0x9079: 0x7B25,
    0x907A: 0x8ACF,
    0x907B: 0x9808,
    0x907C: 0x9162,
    0x907D: 0x56F3,
    0x907E: 0x53A8,
    0x9080: 0x9017,
    0x9081: 0x5439,
    0x9082: 0x5782,
    0x9083: 0x5E25,
    0x9084: 0x63A8,
    0x9085: 0x6C34,
    0x9086: 0x708A,
    0x9087: 0x7761,
    0x9088: 0x7C8B,
    0x9089: 0x7FE0,
    0x908A: 0x8870,
    0x908B: 0x9042,
    0x908C: 0x9154,
    0x908D: 0x9310,
    0x908E: 0x9318,
    0x908F: 0x968F,
    0x9090: 0x745E,
    0x9091: 0x9AC4,
    0x9092: 0x5D07,
    0x9093: 0x5D69,
    0x9094: 0x6570,
    0x9095: 0x67A2,
    0x9096: 0x8DA8,
    0x9097: 0x96DB,
    0x9098: 0x636E,
    0x9099: 0x6749,
    0x909A: 0x6919,
    0x909B: 0x83C5,
    0x909C: 0x9817,
    0x909D: 0x96C0,
    0x909E: 0x88FE,
    0x909F: 0x6F84,
    0x90A0: 0x647A,
    0x90A1: 0x5BF8,
    0x90A2: 0x4E16,
    0x90A3: 0x702C,
    0x90A4: 0x755D,
    0x90A5: 0x662F,
    0x90A6: 0x51C4,
    0x90A7: 0x5236,
    0x90A8: 0x52E2,
    0x90A9: 0x59D3,
    0x90AA: 0x5F81,
    0x90AB: 0x6027,
    0x90AC: 0x6210,
    0x90AD: 0x653F,
    0x90AE: 0x6574,
    0x90AF: 0x661F,
    0x90B0: 0x6674,
    0x90B1: 0x68F2,
    0x90B2: 0x6816,
    0x90B3: 0x6B63,
    0x90B4: 0x6E05,
    0x90B5: 0x7272,
    0x90B6: 0x751F,
    0x90B7: 0x76DB,
    0x90B8: 0x7CBE,
    0x90B9: 0x8056,
    0x90BA: 0x58F0,
    0x90BB: 0x88FD,
    0x90BC: 0x897F,
    0x90BD: 0x8AA0,
    0x90BE: 0x8A93,
    0x90BF: 0x8ACB,
    0x90C0: 0x901D,
    0x90C1: 0x9192,
    0x90C2: 0x9752,
    0x90C3: 0x9759,
    0x90C4: 0x6589,
    0x90C5: 0x7A0E,
    0x90C6: 0x8106,
    0x90C7: 0x96BB,
    0x90C8: 0x5E2D,
    0x90C9: 0x60DC,
    0x90CA: 0x621A,
    0x90CB: 0x65A5,
    0x90CC: 0x6614,
    0x90CD: 0x6790,
    0x90CE: 0x77F3,
    0x90CF: 0x7A4D,
    0x90D0: 0x7C4D,
    0x90D1: 0x7E3E,
    0x90D2: 0x810A,
    0x90D3: 0x8CAC,
    0x90D4: 0x8D64,
    0x90D5: 0x8DE1,
    0x90D6: 0x8E5F,
    0x90D7: 0x78A9,
    0x90D8: 0x5207,
    0x90D9: 0x62D9,
    0x90DA: 0x63A5,
    0x90DB: 0x6442,
    0x90DC: 0x6298,
    0x90DD: 0x8A2D,
    0x90DE: 0x7A83,
    0x90DF: 0x7BC0,
    0x90E0: 0x8AAC,
    0x90E1: 0x96EA,
    0x90E2: 0x7D76,
    0x90E3: 0x820C,
    0x90E4: 0x8749,
    0x90E5: 0x4ED9,
    0x90E6: 0x5148,
    0x90E7: 0x5343,
    0x90E8: 0x5360,
    0x90E9: 0x5BA3,
    0x90EA: 0x5C02,
    0x90EB: 0x5C16,
    0x90EC: 0x5DDD,
    0x90ED: 0x6226,
    0x90EE: 0x6247,
    0x90EF: 0x64B0,
    0x90F0: 0x6813,
    0x90F1: 0x6834,
    0x90F2: 0x6CC9,
    0x90F3: 0x6D45,
    0x90F4: 0x6D17,
    0x90F5: 0x67D3,
    0x90F6: 0x6F5C,
    0x90F7: 0x714E,
    0x90F8: 0x717D,
    0x90F9: 0x65CB,
    0x90FA: 0x7A7F,
    0x90FB: 0x7BAD,
    0x90FC: 0x7DDA,
    0x9140: 0x7E4A,
    0x9141: 0x7FA8,
    0x9142: 0x817A,
    0x9143: 0x821B,
    0x9144: 0x8239,
    0x9145: 0x85A6,
    0x9146: 0x8A6E,
    0x9147: 0x8CCE,
    0x9148: 0x8DF5,
    0x9149: 0x9078,
    0x914A: 0x9077,
    0x914B: 0x92AD,
    0x914C: 0x9291,
    0x914D: 0x9583,
    0x914E: 0x9BAE,
    0x914F: 0x524D,
    0x9150: 0x5584,
    0x9151: 0x6F38,
    0x9152: 0x7136,
    0x9153: 0x5168,
    0x9154: 0x7985,
    0x9155: 0x7E55,
    0x9156: 0x81B3,
    0x9157: 0x7CCE,
    0x9158: 0x564C,
    0x9159: 0x5851,
    0x915A: 0x5CA8,
    0x915B: 0x63AA,
    0x915C: 0x66FE,
    0x915D: 0x66FD,
    0x915E: 0x695A,
    0x915F: 0x72D9,
    0x9160: 0x758F,
    0x9161: 0x758E,
    0x9162: 0x790E,
    0x9163: 0x7956,
    0x9164: 0x79DF,
    0x9165: 0x7C97,
    0x9166: 0x7D20,
    0x9167: 0x7D44,
    0x9168: 0x8607,
    0x9169: 0x8A34,
    0x916A: 0x963B,
    0x916B: 0x9061,
    0x916C: 0x9F20,
    0x916D: 0x50E7,
    0x916E: 0x5275,
    0x916F: 0x53CC,
    0x9170: 0x53E2,
    0x9171: 0x5009,
    0x9172: 0x55AA,
    0x9173: 0x58EE,
    0x9174: 0x594F,
    0x9175: 0x723D,
    0x9176: 0x5B8B,
    0x9177: 0x5C64,
    0x9178: 0x531D,
    0x9179: 0x60E3,
    0x917A: 0x60F3,
    0x917B: 0x635C,
    0x917C: 0x6383,
    0x917D: 0x633F,
    0x917E: 0x63BB,
    0x9180: 0x64CD,
    0x9181: 0x65E9,
    0x9182: 0x66F9,
    0x9183: 0x5DE3,
    0x9184: 0x69CD,
    0x9185: 0x69FD,
    0x9186: 0x6F15,
    0x9187: 0x71E5,
    0x9188: 0x4E89,
    0x9189: 0x75E9,
    0x918A: 0x76F8,
    0x918B: 0x7A93,
    0x918C: 0x7CDF,
    0x918D: 0x7DCF,
    0x918E: 0x7D9C,
    0x918F: 0x8061,
    0x9190: 0x8349,
    0x9191: 0x8358,
    0x9192: 0x846C,
    0x9193: 0x84BC,
    0x9194: 0x85FB,
    0x9195: 0x88C5,
    0x9196: 0x8D70,
    0x9197: 0x9001,
    0x9198: 0x906D,
    0x9199: 0x9397,
    0x919A: 0x971C,
    0x919B: 0x9A12,
    0x919C: 0x50CF,
    0x919D: 0x5897,
    0x919E: 0x618E,
    0x919F: 0x81D3,
    0x91A0: 0x8535,
    0x91A1: 0x8D08,
    0x91A2: 0x9020,
    0x91A3: 0x4FC3,
    0x91A4: 0x5074,
    0x91A5: 0x5247,
    0x91A6: 0x5373,
    0x91A7: 0x606F,
    0x91A8: 0x6349,
    0x91A9: 0x675F,
    0x91AA: 0x6E2C,
    0x91AB: 0x8DB3,
    0x91AC: 0x901F,
    0x91AD: 0x4FD7,
    0x91AE: 0x5C5E,
    0x91AF: 0x8CCA,
    0x91B0: 0x65CF,
    0x91B1: 0x7D9A,
    0x91B2: 0x5352,
    0x91B3: 0x8896,
    0x91B4: 0x5176,
    0x91B5: 0x63C3,
    0x91B6: 0x5B58,
    0x91B7: 0x5B6B,
    0x91B8: 0x5C0A,
    0x91B9: 0x640D,
    0x91BA: 0x6751,
    0x91BB: 0x905C,
    0x91BC: 0x4ED6,
    0x91BD: 0x591A,
    0x91BE: 0x592A,
    0x91BF: 0x6C70,
    0x91C0: 0x8A51,
    0x91C1: 0x553E,
    0x91C2: 0x5815,
    0x91C3: 0x59A5,
    0x91C4: 0x60F0,
    0x91C5: 0x6253,
    0x91C6: 0x67C1,
    0x91C7: 0x8235,
    0x91C8: 0x6955,
    0x91C9: 0x9640,
    0x91CA: 0x99C4,
    0x91CB: 0x9A28,
    0x91CC: 0x4F53,
    0x91CD: 0x5806,
    0x91CE: 0x5BFE,
    0x91CF: 0x8010,
    0x91D0: 0x5CB1,
    0x91D1: 0x5E2F,
    0x91D2: 0x5F85,
    0x91D3: 0x6020,
    0x91D4: 0x614B,
    0x91D5: 0x6234,
    0x91D6: 0x66FF,
    0x91D7: 0x6CF0,
    0x91D8: 0x6EDE,
    0x91D9: 0x80CE,
    0x91DA: 0x817F,
    0x91DB: 0x82D4,
    0x91DC: 0x888B,
    0x91DD: 0x8CB8,
    0x91DE: 0x9000,
    0x91DF: 0x902E,
    0x91E0: 0x968A,
    0x91E1: 0x9EDB,
    0x91E2: 0x9BDB,
    0x91E3: 0x4EE3,
    0x91E4: 0x53F0,
    0x91E5: 0x5927,
    0x91E6: 0x7B2C,
    0x91E7: 0x918D,
    0x91E8: 0x984C,
    0x91E9: 0x9DF9,
    0x91EA: 0x6EDD,
    0x91EB: 0x7027,
    0x91EC: 0x5353,
    0x91ED: 0x5544,
    0x91EE: 0x5B85,
    0x91EF: 0x6258,
    0x91F0: 0x629E,
    0x91F1: 0x62D3,
    0x91F2: 0x6CA2,
    0x91F3: 0x6FEF,
    0x91F4: 0x7422,
    0x91F5: 0x8A17,
    0x91F6: 0x9438,
    0x91F7: 0x6FC1,
    0x91F8: 0x8AFE,
    0x91F9: 0x8338,
    0x91FA: 0x51E7,
    0x91FB: 0x86F8,
    0x91FC: 0x53EA,
    0x9240: 0x53E9,
    0x9241: 0x4F46,
    0x9242: 0x9054,
    0x9243: 0x8FB0,
    0x9244: 0x596A,
    0x9245: 0x8131,
    0x9246: 0x5DFD,
    0x9247: 0x7AEA,
    0x9248: 0x8FBF,
    0x9249: 0x68DA,
    0x924A: 0x8C37,
    0x924B: 0x72F8,
    0x924C: 0x9C48,
    0x924D: 0x6A3D,
    0x924E: 0x8AB0,
    0x924F: 0x4E39,
    0x9250: 0x5358,
    0x9251: 0x5606,
    0x9252: 0x5766,
    0x9253: 0x62C5,
    0x9254: 0x63A2,
    0x9255: 0x65E6,
    0x9256: 0x6B4E,
    0x9257: 0x6DE1,
    0x9258: 0x6E5B,
    0x9259: 0x70AD,
    0x925A: 0x77ED,
    0x925B: 0x7AEF,
    0x925C: 0x7BAA,
    0x925D: 0x7DBB,
    0x925E: 0x803D,
    0x925F: 0x80C6,
    0x9260: 0x86CB,
    0x9261: 0x8A95,
    0x9262: 0x935B,
    0x9263: 0x56E3,
    0x9264: 0x58C7,
    0x9265: 0x5F3E,
    0x9266: 0x65AD,
    0x9267: 0x6696,
    0x9268: 0x6A80,
    0x9269: 0x6BB5,
    0x926A: 0x7537,
    0x926B: 0x8AC7,
    0x926C: 0x5024,
    0x926D: 0x77E5,
    0x926E: 0x5730,
    0x926F: 0x5F1B,
    0x9270: 0x6065,
    0x9271: 0x667A,
    0x9272: 0x6C60,
    0x9273: 0x75F4,
    0x9274: 0x7A1A,
    0x9275: 0x7F6E,
    0x9276: 0x81F4,
    0x9277: 0x8718,
    0x9278: 0x9045,
    0x9279: 0x99B3,
    0x927A: 0x7BC9,
    0x927B: 0x755C,
    0x927C: 0x7AF9,
    0x927D: 0x7B51,
    0x927E: 0x84C4,
    0x9280: 0x9010,
    0x9281: 0x79E9,
    0x9282: 0x7A92,
    0x9283: 0x8336,
    0x9284: 0x5AE1,
    0x9285: 0x7740,
    0x9286: 0x4E2D,
    0x9287: 0x4EF2,
    0x9288: 0x5B99,
    0x9289: 0x5FE0,
    0x928A: 0x62BD,
    0x928B: 0x663C,
    0x928C: 0x67F1,
    0x928D: 0x6CE8,
    0x928E: 0x866B,
    0x928F: 0x8877,
    0x9290: 0x8A3B,
    0x9291: 0x914E,
    0x9292: 0x92F3,
    0x9293: 0x99D0,
    0x9294: 0x6A17,
    0x9295: 0x7026,
    0x9296: 0x732A,
    0x9297: 0x82E7,
    0x9298: 0x8457,
    0x9299: 0x8CAF,
    0x929A: 0x4E01,
    0x929B: 0x5146,
    0x929C: 0x51CB,
    0x929D: 0x558B,
    0x929E: 0x5BF5,
    0x929F: 0x5E16,
    0x92A0: 0x5E33,
    0x92A1: 0x5E81,
    0x92A2: 0x5F14,
    0x92A3: 0x5F35,
    0x92A4: 0x5F6B,
    0x92A5: 0x5FB4,
    0x92A6: 0x61F2,
    0x92A7: 0x6311,
    0x92A8: 0x66A2,
    0x92A9: 0x671D,
    0x92AA: 0x6F6E,
    0x92AB: 0x7252,
    0x92AC: 0x753A,
    0x92AD: 0x773A,
    0x92AE: 0x8074,
    0x92AF: 0x8139,
    0x92B0: 0x8178,
    0x92B1: 0x8776,
    0x92B2: 0x8ABF,
    0x92B3: 0x8ADC,
    0x92B4: 0x8D85,
    0x92B5: 0x8DF3,
    0x92B6: 0x929A,
    0x92B7: 0x9577,
    0x92B8: 0x9802,
    0x92B9: 0x9CE5,
    0x92BA: 0x52C5,
    0x92BB: 0x6357,
    0x92BC: 0x76F4,
    0x92BD: 0x6715,
    0x92BE: 0x6C88,
    0x92BF: 0x73CD,
    0x92C0: 0x8CC3,
    0x92C1: 0x93AE,
    0x92C2: 0x9673,
    0x92C3: 0x6D25,
    0x92C4: 0x589C,
    0x92C5: 0x690E,
    0x92C6: 0x69CC,
    0x92C7: 0x8FFD,
    0x92C8: 0x939A,
    0x92C9: 0x75DB,
    0x92CA: 0x901A,
    0x92CB: 0x585A,
    0x92CC: 0x6802,
    0x92CD: 0x63B4,
    0x92CE: 0x69FB,
    0x92CF: 0x4F43,
    0x92D0: 0x6F2C,
    0x92D1: 0x67D8,
    0x92D2: 0x8FBB,
    0x92D3: 0x8526,
    0x92D4: 0x7DB4,
    0x92D5: 0x9354,
    0x92D6: 0x693F,
    0x92D7: 0x6F70,
    0x92D8: 0x576A,
    0x92D9: 0x58F7,
    0x92DA: 0x5B2C,
    0x92DB: 0x7D2C,
    0x92DC: 0x722A,
    0x92DD: 0x540A,
    0x92DE: 0x91E3,
    0x92DF: 0x9DB4,
    0x92E0: 0x4EAD,
    0x92E1: 0x4F4E,
    0x92E2: 0x505C,
    0x92E3: 0x5075,
    0x92E4: 0x5243,
    0x92E5: 0x8C9E,
    0x92E6: 0x5448,
    0x92E7: 0x5824,
    0x92E8: 0x5B9A,
    0x92E9: 0x5E1D,
    0x92EA: 0x5E95,
    0x92EB: 0x5EAD,
    0x92EC: 0x5EF7,
    0x92ED: 0x5F1F,
    0x92EE: 0x608C,
    0x92EF: 0x62B5,
    0x92F0: 0x633A,
    0x92F1: 0x63D0,
    0x92F2: 0x68AF,
    0x92F3: 0x6C40,
    0x92F4: 0x7887,
    0x92F5: 0x798E,
    0x92F6: 0x7A0B,
    0x92F7: 0x7DE0,
    0x92F8: 0x8247,
    0x92F9: 0x8A02,
    0x92FA: 0x8AE6,
    0x92FB: 0x8E44,
    0x92FC: 0x9013,
    0x9340: 0x90B8,
    0x9341: 0x912D,
    0x9342: 0x91D8,
    0x9343: 0x9F0E,
    0x9344: 0x6CE5,
    0x9345: 0x6458,
    0x9346: 0x64E2,
    0x9347: 0x6575,
    0x9348: 0x6EF4,
    0x9349: 0x7684,
    0x934A: 0x7B1B,
    0x934B: 0x9069,
    0x934C: 0x93D1,
    0x934D: 0x6EBA,
    0x934E: 0x54F2,
    0x934F: 0x5FB9,
    0x9350: 0x64A4,
    0x9351: 0x8F4D,
    0x9352: 0x8FED,
    0x9353: 0x9244,
    0x9354: 0x5178,
    0x9355: 0x586B,
    0x9356: 0x5929,
    0x9357: 0x5C55,
    0x9358: 0x5E97,
    0x9359: 0x6DFB,
    0x935A: 0x7E8F,
    0x935B: 0x751C,
    0x935C: 0x8CBC,
    0x935D: 0x8EE2,
    0x935E: 0x985B,
    0x935F: 0x70B9,
    0x9360: 0x4F1D,
    0x9361: 0x6BBF,
    0x9362: 0x6FB1,
    0x9363: 0x7530,
    0x9364: 0x96FB,
    0x9365: 0x514E,
    0x9366: 0x5410,
    0x9367: 0x5835,
    0x9368: 0x5857,
    0x9369: 0x59AC,
    0x936A: 0x5C60,
    0x936B: 0x5F92,
    0x936C: 0x6597,
    0x936D: 0x675C,
    0x936E: 0x6E21,
    0x936F: 0x767B,
    0x9370: 0x83DF,
    0x9371: 0x8CED,
    0x9372: 0x9014,
    0x9373: 0x90FD,
    0x9374: 0x934D,
    0x9375: 0x7825,
    0x9376: 0x783A,
    0x9377: 0x52AA,
    0x9378: 0x5EA6,
    0x9379: 0x571F,
    0x937A: 0x5974,
    0x937B: 0x6012,
    0x937C: 0x5012,
    0x937D: 0x515A,
    0x937E: 0x51AC,
    0x9380: 0x51CD,
    0x9381: 0x5200,
    0x9382: 0x5510,
    0x9383: 0x5854,
    0x9384: 0x5858,
    0x9385: 0x5957,
    0x9386: 0x5B95,
    0x9387: 0x5CF6,
    0x9388: 0x5D8B,
    0x9389: 0x60BC,
    0x938A: 0x6295,
    0x938B: 0x642D,
    0x938C: 0x6771,
    0x938D: 0x6843,
    0x938E: 0x68BC,
    0x938F: 0x68DF,
    0x9390: 0x76D7,
    0x9391: 0x6DD8,
    0x9392: 0x6E6F,
    0x9393: 0x6D9B,
    0x9394: 0x706F,
    0x9395: 0x71C8,
    0x9396: 0x5F53,
    0x9397: 0x75D8,
    0x9398: 0x7977,
    0x9399: 0x7B49,
    0x939A: 0x7B54,
    0x939B: 0x7B52,
    0x939C: 0x7CD6,
    0x939D: 0x7D71,
    0x939E: 0x5230,
    0x939F: 0x8463,
    0x93A0: 0x8569,
    0x93A1: 0x85E4,
    0x93A2: 0x8A0E,
    0x93A3: 0x8B04,
    0x93A4: 0x8C46,
    0x93A5: 0x8E0F,
    0x93A6: 0x9003,
    0x93A7: 0x900F,
    0x93A8: 0x9419,
    0x93A9: 0x9676,
    0x93AA: 0x982D,
    0x93AB: 0x9A30,
    0x93AC: 0x95D8,
    0x93AD: 0x50CD,
    0x93AE: 0x52D5,
    0x93AF: 0x540C,
    0x93B0: 0x5802,
    0x93B1: 0x5C0E,
    0x93B2: 0x61A7,
    0x93B3: 0x649E,
    0x93B4: 0x6D1E,
    0x93B5: 0x77B3,
    0x93B6: 0x7AE5,
    0x93B7: 0x80F4,
    0x93B8: 0x8404,
    0x93B9: 0x9053,
    0x93BA: 0x9285,
    0x93BB: 0x5CE0,
    0x93BC: 0x9D07,
    0x93BD: 0x533F,
    0x93BE: 0x5F97,
    0x93BF: 0x5FB3,
    0x93C0: 0x6D9C,
    0x93C1: 0x7279,
    0x93C2: 0x7763,
    0x93C3: 0x79BF,
    0x93C4: 0x7BE4,
    0x93C5: 0x6BD2,
    0x93C6: 0x72EC,
    0x93C7: 0x8AAD,
    0x93C8: 0x6803,
    0x93C9: 0x6A61,
    0x93CA: 0x51F8,
    0x93CB: 0x7A81,
    0x93CC: 0x6934,
    0x93CD: 0x5C4A,
    0x93CE: 0x9CF6,
    0x93CF: 0x82EB,
    0x93D0: 0x5BC5,
    0x93D1: 0x9149,
    0x93D2: 0x701E,
    0x93D3: 0x5678,
    0x93D4: 0x5C6F,
    0x93D5: 0x60C7,
    0x93D6: 0x6566,
    0x93D7: 0x6C8C,
    0x93D8: 0x8C5A,
    0x93D9: 0x9041,
    0x93DA: 0x9813,
    0x93DB: 0x5451,
    0x93DC: 0x66C7,
    0x93DD: 0x920D,
    0x93DE: 0x5948,
    0x93DF: 0x90A3,
    0x93E0: 0x5185,
    0x93E1: 0x4E4D,
    0x93E2: 0x51EA,
    0x93E3: 0x8599,
    0x93E4: 0x8B0E,
    0x93E5: 0x7058,
    0x93E6: 0x637A,
    0x93E7: 0x934B,
    0x93E8: 0x6962,
    0x93E9: 0x99B4,
    0x93EA: 0x7E04,
    0x93EB: 0x7577,
    0x93EC: 0x5357,
    0x93ED: 0x6960,
    0x93EE: 0x8EDF,
    0x93EF: 0x96E3,
    0x93F0: 0x6C5D,
    0x93F1: 0x4E8C,
    0x93F2: 0x5C3C,
    0x93F3: 0x5F10,
    0x93F4: 0x8FE9,
    0x93F5: 0x5302,
    0x93F6: 0x8CD1,
    0x93F7: 0x8089,
    0x93F8: 0x8679,
    0x93F9: 0x5EFF,
    0x93FA: 0x65E5,
    0x93FB: 0x4E73,
    0x93FC: 0x5165,
    0x9440: 0x5982,
    0x9441: 0x5C3F,
    0x9442: 0x97EE,
    0x9443: 0x4EFB,
    0x9444: 0x598A,
    0x9445: 0x5FCD,
    0x9446: 0x8A8D,
    0x9447: 0x6FE1,
    0x9448: 0x79B0,
    0x9449: 0x7962,
    0x944A: 0x5BE7,
    0x944B: 0x8471,
    0x944C: 0x732B,
    0x944D: 0x71B1,
    0x944E: 0x5E74,
    0x944F: 0x5FF5,
    0x9450: 0x637B,
    0x9451: 0x649A,
    0x9452: 0x71C3,
    0x9453: 0x7C98,
    0x9454: 0x4E43,
    0x9455: 0x5EFC,
    0x9456: 0x4E4B,
    0x9457: 0x57DC,
    0x9458: 0x56A2,
    0x9459: 0x60A9,
    0x945A: 0x6FC3,
    0x945B: 0x7D0D,
    0x945C: 0x80FD,
    0x945D: 0x8133,
    0x945E: 0x81BF,
    0x945F: 0x8FB2,
    0x9460: 0x8997,
    0x9461: 0x86A4,
    0x9462: 0x5DF4,
    0x9463: 0x628A,
    0x9464: 0x64AD,
    0x9465: 0x8987,
    0x9466: 0x6777,
    0x9467: 0x6CE2,
    0x9468: 0x6D3E,
    0x9469: 0x7436,
    0x946A: 0x7834,
    0x946B: 0x5A46,
    0x946C: 0x7F75,
    0x946D: 0x82AD,
    0x946E: 0x99AC,
    0x946F: 0x4FF3,
    0x9470: 0x5EC3,
    0x9471: 0x62DD,
    0x9472: 0x6392,
    0x9473: 0x6557,
    0x9474: 0x676F,
    0x9475: 0x76C3,
    0x9476: 0x724C,
    0x9477: 0x80CC,
    0x9478: 0x80BA,
    0x9479: 0x8F29,
    0x947A: 0x914D,
    0x947B: 0x500D,
    0x947C: 0x57F9,
    0x947D: 0x5A92,
    0x947E: 0x6885,
    0x9480: 0x6973,
    0x9481: 0x7164,
    0x9482: 0x72FD,
    0x9483: 0x8CB7,
    0x9484: 0x58F2,
    0x9485: 0x8CE0,
    0x9486: 0x966A,
    0x9487: 0x9019,
    0x9488: 0x877F,
    0x9489: 0x79E4,
    0x948A: 0x77E7,
    0x948B: 0x8429,
    0x948C: 0x4F2F,
    0x948D: 0x5265,
    0x948E: 0x535A,
    0x948F: 0x62CD,
    0x9490: 0x67CF,
    0x9491: 0x6CCA,
    0x9492: 0x767D,
    0x9493: 0x7B94,
    0x9494: 0x7C95,
    0x9495: 0x8236,
    0x9496: 0x8584,
    0x9497: 0x8FEB,
    0x9498: 0x66DD,
    0x9499: 0x6F20,
    0x949A: 0x7206,
    0x949B: 0x7E1B,
    0x949C: 0x83AB,
    0x949D: 0x99C1,
    0x949E: 0x9EA6,
    0x949F: 0x51FD,
    0x94A0: 0x7BB1,
    0x94A1: 0x7872,
    0x94A2: 0x7BB8,
    0x94A3: 0x8087,
    0x94A4: 0x7B48,
    0x94A5: 0x6AE8,
    0x94A6: 0x5E61,
    0x94A7: 0x808C,
    0x94A8: 0x7551,
    0x94A9: 0x7560,
    0x94AA: 0x516B,
    0x94AB: 0x9262,
    0x94AC: 0x6E8C,
    0x94AD: 0x767A,
    0x94AE: 0x9197,
    0x94AF: 0x9AEA,
    0x94B0: 0x4F10,
    0x94B1: 0x7F70,
    0x94B2: 0x629C,
    0x94B3: 0x7B4F,
    0x94B4: 0x95A5,
    0x94B5: 0x9CE9,
    0x94B6: 0x567A,
    0x94B7: 0x5859,
    0x94B8: 0x86E4,
    0x94B9: 0x96BC,
    0x94BA: 0x4F34,
    0x94BB: 0x5224,
    0x94BC: 0x534A,
    0x94BD: 0x53CD,
    0x94BE: 0x53DB,
    0x94BF: 0x5E06,
    0x94C0: 0x642C,
    0x94C1: 0x6591,
    0x94C2: 0x677F,
    0x94C3: 0x6C3E,
    0x94C4: 0x6C4E,
    0x94C5: 0x7248,
    0x94C6: 0x72AF,
    0x94C7: 0x73ED,
    0x94C8: 0x7554,
    0x94C9: 0x7E41,
    0x94CA: 0x822C,
    0x94CB: 0x85E9,
    0x94CC: 0x8CA9,
    0x94CD: 0x7BC4,
    0x94CE: 0x91C6,
    0x94CF: 0x7169,
    0x94D0: 0x9812,
    0x94D1: 0x98EF,
    0x94D2: 0x633D,
    0x94D3: 0x6669,
    0x94D4: 0x756A,
    0x94D5: 0x76E4,
    0x94D6: 0x78D0,
    0x94D7: 0x8543,
    0x94D8: 0x86EE,
    0x94D9: 0x532A,
    0x94DA: 0x5351,
    0x94DB: 0x5426,
    0x94DC: 0x5983,
    0x94DD: 0x5E87,
    0x94DE: 0x5F7C,
    0x94DF: 0x60B2,
    0x94E0: 0x6249,
    0x94E1: 0x6279,
    0x94E2: 0x62AB,
    0x94E3: 0x6590,
    0x94E4: 0x6BD4,
    0x94E5: 0x6CCC,
    0x94E6: 0x75B2,
    0x94E7: 0x76AE,
    0x94E8: 0x7891,
    0x94E9: 0x79D8,
    0x94EA: 0x7DCB,
    0x94EB: 0x7F77,
    0x94EC: 0x80A5,
    0x94ED: 0x88AB,
    0x94EE: 0x8AB9,
    0x94EF: 0x8CBB,
    0x94F0: 0x907F,
    0x94F1: 0x975E,
    0x94F2: 0x98DB,
    0x94F3: 0x6A0B,
    0x94F4: 0x7C38,
    0x94F5: 0x5099,
    0x94F6: 0x5C3E,
    0x94F7: 0x5FAE,
    0x94F8: 0x6787,
    0x94F9: 0x6BD8,
    0x94FA: 0x7435,
    0x94FB: 0x7709,
    0x94FC: 0x7F8E,
    0x9540: 0x9F3B,
    0x9541: 0x67CA,
    0x9542: 0x7A17,
    0x9543: 0x5339,
    0x9544: 0x758B,
    0x9545: 0x9AED,
    0x9546: 0x5F66,
    0x9547: 0x819D,
    0x9548: 0x83F1,
    0x9549: 0x8098,
    0x954A: 0x5F3C,
    0x954B: 0x5FC5,
    0x954C: 0x7562,
    0x954D: 0x7B46,
    0x954E: 0x903C,
    0x954F: 0x6867,
    0x9550: 0x59EB,
    0x9551: 0x5A9B,
    0x9552: 0x7D10,
    0x9553: 0x767E,
    0x9554: 0x8B2C,
    0x9555: 0x4FF5,
    0x9556: 0x5F6A,
    0x9557: 0x6A19,
    0x9558: 0x6C37,
    0x9559: 0x6F02,
    0x955A: 0x74E2,
    0x955B: 0x7968,
    0x955C: 0x8868,
    0x955D: 0x8A55,
    0x955E: 0x8C79,
    0x955F: 0x5EDF,
    0x9560: 0x63CF,
    0x9561: 0x75C5,
    0x9562: 0x79D2,
    0x9563: 0x82D7,
    0x9564: 0x9328,
    0x9565: 0x92F2,
    0x9566: 0x849C,
    0x9567: 0x86ED,
    0x9568: 0x9C2D,
    0x9569: 0x54C1,
    0x956A: 0x5F6C,
    0x956B: 0x658C,
    0x956C: 0x6D5C,
    0x956D: 0x7015,
    0x956E: 0x8CA7,
    0x956F: 0x8CD3,
    0x9570: 0x983B,
    0x9571: 0x654F,
    0x9572: 0x74F6,
    0x9573: 0x4E0D,
    0x9574: 0x4ED8,
    0x9575: 0x57E0,
    0x9576: 0x592B,
    0x9577: 0x5A66,
    0x9578: 0x5BCC,
    0x9579: 0x51A8,
    0x957A: 0x5E03,
    0x957B: 0x5E9C,
    0x957C: 0x6016,
    0x957D: 0x6276,
    0x957E: 0x6577,
    0x9580: 0x65A7,
    0x9581: 0x666E,
    0x9582: 0x6D6E,
    0x9583: 0x7236,
    0x9584: 0x7B26,
    0x9585: 0x8150,
    0x9586: 0x819A,
    0x9587: 0x8299,
    0x9588: 0x8B5C,
    0x9589: 0x8CA0,
    0x958A: 0x8CE6,
    0x958B: 0x8D74,
    0x958C: 0x961C,
    0x958D: 0x9644,
    0x958E: 0x4FAE,
    0x958F: 0x64AB,
    0x9590: 0x6B66,
    0x9591: 0x821E,
    0x9592: 0x8461,
    0x9593: 0x856A,
    0x9594: 0x90E8,
    0x9595: 0x5C01,
    0x9596: 0x6953,
    0x9597: 0x98A8,
    0x9598: 0x847A,
    0x9599: 0x8557,
    0x959A: 0x4F0F,
    0x959B: 0x526F,
    0x959C: 0x5FA9,
    0x959D: 0x5E45,
    0x959E: 0x670D,
    0x959F: 0x798F,
    0x95A0: 0x8179,
    0x95A1: 0x8907,
    0x95A2: 0x8986,
    0x95A3: 0x6DF5,
    0x95A4: 0x5F17,
    0x95A5: 0x6255,
    0x95A6: 0x6CB8,
    0x95A7: 0x4ECF,
    0x95A8: 0x7269,
    0x95A9: 0x9B92,
    0x95AA: 0x5206,
    0x95AB: 0x543B,
    0x95AC: 0x5674,
    0x95AD: 0x58B3,
    0x95AE: 0x61A4,
    0x95AF: 0x626E,
    0x95B0: 0x711A,
    0x95B1: 0x596E,
    0x95B2: 0x7C89,
    0x95B3: 0x7CDE,
    0x95B4: 0x7D1B,
    0x95B5: 0x96F0,
    0x95B6: 0x6587,
    0x95B7: 0x805E,
    0x95B8: 0x4E19,
    0x95B9: 0x4F75,
    0x95BA: 0x5175,
    0x95BB: 0x5840,
    0x95BC: 0x5E63,
    0x95BD: 0x5E73,
    0x95BE: 0x5F0A,
    0x95BF: 0x67C4,
    0x95C0: 0x4E26,
    0x95C1: 0x853D,
    0x95C2: 0x9589,
    0x95C3: 0x965B,
    0x95C4: 0x7C73,
    0x95C5: 0x9801,
    0x95C6: 0x50FB,
    0x95C7: 0x58C1,
    0x95C8: 0x7656,
    0x95C9: 0x78A7,
    0x95CA: 0x5225,
    0x95CB: 0x77A5,
    0x95CC: 0x8511,
    0x95CD: 0x7B86,
    0x95CE: 0x504F,
    0x95CF: 0x5909,
    0x95D0: 0x7247,
    0x95D1: 0x7BC7,
    0x95D2: 0x7DE8,
    0x95D3: 0x8FBA,
    0x95D4: 0x8FD4,
    0x95D5: 0x904D,
    0x95D6: 0x4FBF,
    0x95D7: 0x52C9,
    0x95D8: 0x5A29,
    0x95D9: 0x5F01,
    0x95DA: 0x97AD,
    0x95DB: 0x4FDD,
    0x95DC: 0x8217,
    0x95DD: 0x92EA,
    0x95DE: 0x5703,
    0x95DF: 0x6355,
    0x95E0: 0x6B69,
    0x95E1: 0x752B,
    0x95E2: 0x88DC,
    0x95E3: 0x8F14,
    0x95E4: 0x7A42,
    0x95E5: 0x52DF,
    0x95E6: 0x5893,
    0x95E7: 0x6155,
    0x95E8: 0x620A,
    0x95E9: 0x66AE,
    0x95EA: 0x6BCD,
    0x95EB: 0x7C3F,
    0x95EC: 0x83E9,
    0x95ED: 0x5023,
    0x95EE: 0x4FF8,
    0x95EF: 0x5305,
    0x95F0: 0x5446,
    0x95F1: 0x5831,
    0x95F2: 0x5949,
    0x95F3: 0x5B9D,
    0x95F4: 0x5CF0,
    0x95F5: 0x5CEF,
    0x95F6: 0x5D29,
    0x95F7: 0x5E96,
    0x95F8: 0x62B1,
    0x95F9: 0x6367,
    0x95FA: 0x653E,
    0x95FB: 0x65B9,
    0x95FC: 0x670B,
    0x9640: 0x6CD5,
    0x9641: 0x6CE1,
    0x9642: 0x70F9,
    0x9643: 0x7832,
    0x9644: 0x7E2B,
    0x9645: 0x80DE,
    0x9646: 0x82B3,
    0x9647: 0x840C,
    0x9648: 0x84EC,
    0x9649: 0x8702,
    0x964A: 0x8912,
    0x964B: 0x8A2A,
    0x964C: 0x8C4A,
    0x964D: 0x90A6,
    0x964E: 0x92D2,
    0x964F: 0x98FD,
    0x9650: 0x9CF3,
    0x9651: 0x9D6C,
    0x9652: 0x4E4F,
    0x9653: 0x4EA1,
    0x9654: 0x508D,
    0x9655: 0x5256,
    0x9656: 0x574A,
    0x9657: 0x59A8,
    0x9658: 0x5E3D,
    0x9659: 0x5FD8,
    0x965A: 0x5FD9,
    0x965B: 0x623F,
    0x965C: 0x66B4,
    0x965D: 0x671B,
    0x965E: 0x67D0,
    0x965F: 0x68D2,
    0x9660: 0x5192,
    0x9661: 0x7D21,
    0x9662: 0x80AA,
    0x9663: 0x81A8,
    0x9664: 0x8B00,
    0x9665: 0x8C8C,
    0x9666: 0x8CBF,
    0x9667: 0x927E,
    0x9668: 0x9632,
    0x9669: 0x5420,
    0x966A: 0x982C,
    0x966B: 0x5317,
    0x966C: 0x50D5,
    0x966D: 0x535C,
    0x966E: 0x58A8,
    0x966F: 0x64B2,
    0x9670: 0x6734,
    0x9671: 0x7267,
    0x9672: 0x7766,
    0x9673: 0x7A46,
    0x9674: 0x91E6,
    0x9675: 0x52C3,
    0x9676: 0x6CA1,
    0x9677: 0x6B86,
    0x9678: 0x5800,
    0x9679: 0x5E4C,
    0x967A: 0x5954,
    0x967B: 0x672C,
    0x967C: 0x7FFB,
    0x967D: 0x51E1,
    0x967E: 0x76C6,
    0x9680: 0x6469,
    0x9681: 0x78E8,
    0x9682: 0x9B54,
    0x9683: 0x9EBB,
    0x9684: 0x57CB,
    0x9685: 0x59B9,
    0x9686: 0x6627,
    0x9687: 0x679A,
    0x9688: 0x6BCE,
    0x9689: 0x54E9,
    0x968A: 0x69D9,
    0x968B: 0x5E55,
    0x968C: 0x819C,
    0x968D: 0x6795,
    0x968E: 0x9BAA,
    0x968F: 0x67FE,
    0x9690: 0x9C52,
    0x9691: 0x685D,
    0x9692: 0x4EA6,
    0x9693: 0x4FE3,
    0x9694: 0x53C8,
    0x9695: 0x62B9,
    0x9696: 0x672B,
    0x9697: 0x6CAB,
    0x9698: 0x8FC4,
    0x9699: 0x4FAD,
    0x969A: 0x7E6D,
    0x969B: 0x9EBF,
    0x969C: 0x4E07,
    0x969D: 0x6162,
    0x969E: 0x6E80,
    0x969F: 0x6F2B,
    0x96A0: 0x8513,
    0x96A1: 0x5473,
    0x96A2: 0x672A,
    0x96A3: 0x9B45,
    0x96A4: 0x5DF3,
    0x96A5: 0x7B95,
    0x96A6: 0x5CAC,
    0x96A7: 0x5BC6,
    0x96A8: 0x871C,
    0x96A9: 0x6E4A,
    0x96AA: 0x84D1,
    0x96AB: 0x7A14,
    0x96AC: 0x8108,
    0x96AD: 0x5999,
    0x96AE: 0x7C8D,
    0x96AF: 0x6C11,
    0x96B0: 0x7720,
    0x96B1: 0x52D9,
    0x96B2: 0x5922,
    0x96B3: 0x7121,
    0x96B4: 0x725F,
    0x96B5: 0x77DB,
    0x96B6: 0x9727,
    0x96B7: 0x9D61,
    0x96B8: 0x690B,
    0x96B9: 0x5A7F,
    0x96BA: 0x5A18,
    0x96BB: 0x51A5,
    0x96BC: 0x540D,
    0x96BD: 0x547D,
    0x96BE: 0x660E,
    0x96BF: 0x76DF,
    0x96C0: 0x8FF7,
    0x96C1: 0x9298,
    0x96C2: 0x9CF4,
    0x96C3: 0x59EA,
    0x96C4: 0x725D,
    0x96C5: 0x6EC5,
    0x96C6: 0x514D,
    0x96C7: 0x68C9,
    0x96C8: 0x7DBF,
    0x96C9: 0x7DEC,
    0x96CA: 0x9762,
    0x96CB: 0x9EBA,
    0x96CC: 0x6478,
    0x96CD: 0x6A21,
    0x96CE: 0x8302,
    0x96CF: 0x5984,
    0x96D0: 0x5B5F,
    0x96D1: 0x6BDB,
    0x96D2: 0x731B,
    0x96D3: 0x76F2,
    0x96D4: 0x7DB2,
    0x96D5: 0x8017,
    0x96D6: 0x8499,
    0x96D7: 0x5132,
    0x96D8: 0x6728,
    0x96D9: 0x9ED9,
    0x96DA: 0x76EE,
    0x96DB: 0x6762,
    0x96DC: 0x52FF,
    0x96DD: 0x9905,
    0x96DE: 0x5C24,
    0x96DF: 0x623B,
    0x96E0: 0x7C7E,
    0x96E1: 0x8CB0,
    0x96E2: 0x554F,
    0x96E3: 0x60B6,
    0x96E4: 0x7D0B,
    0x96E5: 0x9580,
    0x96E6: 0x5301,
    0x96E7: 0x4E5F,
    0x96E8: 0x51B6,
    0x96E9: 0x591C,
    0x96EA: 0x723A,
    0x96EB: 0x8036,
    0x96EC: 0x91CE,
    0x96ED: 0x5F25,
    0x96EE: 0x77E2,
    0x96EF: 0x5384,
    0x96F0: 0x5F79,
    0x96F1: 0x7D04,
    0x96F2: 0x85AC,
    0x96F3: 0x8A33,
    0x96F4: 0x8E8D,
    0x96F5: 0x9756,
    0x96F6: 0x67F3,
    0x96F7: 0x85AE,
    0x96F8: 0x9453,
    0x96F9: 0x6109,
    0x96FA: 0x6108,
    0x96FB: 0x6CB9,
    0x96FC: 0x7652,
    0x9740: 0x8AED,
    0x9741: 0x8F38,
    0x9742: 0x552F,
    0x9743: 0x4F51,
    0x9744: 0x512A,
    0x9745: 0x52C7,
    0x9746: 0x53CB,
    0x9747: 0x5BA5,
    0x9748: 0x5E7D,
    0x9749: 0x60A0,
    0x974A: 0x6182,
    0x974B: 0x63D6,
    0x974C: 0x6709,
    0x974D: 0x67DA,
    0x974E: 0x6E67,
    0x974F: 0x6D8C,
    0x9750: 0x7336,
    0x9751: 0x7337,
    0x9752: 0x7531,
    0x9753: 0x7950,
    0x9754: 0x88D5,
    0x9755: 0x8A98,
    0x9756: 0x904A,
    0x9757: 0x9091,
    0x9758: 0x90F5,
    0x9759: 0x96C4,
    0x975A: 0x878D,
    0x975B: 0x5915,
    0x975C: 0x4E88,
    0x975D: 0x4F59,
    0x975E: 0x4E0E,
    0x975F: 0x8A89,
    0x9760: 0x8F3F,
    0x9761: 0x9810,
    0x9762: 0x50AD,
    0x9763: 0x5E7C,
    0x9764: 0x5996,
    0x9765: 0x5BB9,
    0x9766: 0x5EB8,
    0x9767: 0x63DA,
    0x9768: 0x63FA,
    0x9769: 0x64C1,
    0x976A: 0x66DC,
    0x976B: 0x694A,
    0x976C: 0x69D8,
    0x976D: 0x6D0B,
    0x976E: 0x6EB6,
    0x976F: 0x7194,
    0x9770: 0x7528,
    0x9771: 0x7AAF,
    0x9772: 0x7F8A,
    0x9773: 0x8000,
    0x9774: 0x8449,
    0x9775: 0x84C9,
    0x9776: 0x8981,
    0x9777: 0x8B21,
    0x9778: 0x8E0A,
    0x9779: 0x9065,
    0x977A: 0x967D,
    0x977B: 0x990A,
    0x977C: 0x617E,
    0x977D: 0x6291,
    0x977E: 0x6B32,
    0x9780: 0x6C83,
    0x9781: 0x6D74,
    0x9782: 0x7FCC,
    0x9783: 0x7FFC,
    0x9784: 0x6DC0,
    0x9785: 0x7F85,
    0x9786: 0x87BA,
    0x9787: 0x88F8,
    0x9788: 0x6765,
    0x9789: 0x83B1,
    0x978A: 0x983C,
    0x978B: 0x96F7,
    0x978C: 0x6D1B,
    0x978D: 0x7D61,
    0x978E: 0x843D,
    0x978F: 0x916A,
    0x9790: 0x4E71,
    0x9791: 0x5375,
    0x9792: 0x5D50,
    0x9793: 0x6B04,
    0x9794: 0x6FEB,
    0x9795: 0x85CD,
    0x9796: 0x862D,
    0x9797: 0x89A7,
    0x9798: 0x5229,
    0x9799: 0x540F,
    0x979A: 0x5C65,
    0x979B: 0x674E,
    0x979C: 0x68A8,
    0x979D: 0x7406,
    0x979E: 0x7483,
    0x979F: 0x75E2,
    0x97A0: 0x88CF,
    0x97A1: 0x88E1,
    0x97A2: 0x91CC,
    0x97A3: 0x96E2,
    0x97A4: 0x9678,
    0x97A5: 0x5F8B,
    0x97A6: 0x7387,
    0x97A7: 0x7ACB,
    0x97A8: 0x844E,
    0x97A9: 0x63A0,
    0x97AA: 0x7565,
    0x97AB: 0x5289,
    0x97AC: 0x6D41,
    0x97AD: 0x6E9C,
    0x97AE: 0x7409,
    0x97AF: 0x7559,
    0x97B0: 0x786B,
    0x97B1: 0x7C92,
    0x97B2: 0x9686,
    0x97B3: 0x7ADC,
    0x97B4: 0x9F8D,
    0x97B5: 0x4FB6,
    0x97B6: 0x616E,
    0x97B7: 0x65C5,
    0x97B8: 0x865C,
    0x97B9: 0x4E86,
    0x97BA: 0x4EAE,
    0x97BB: 0x50DA,
    0x97BC: 0x4E21,
    0x97BD: 0x51CC,
    0x97BE: 0x5BEE,
    0x97BF: 0x6599,
    0x97C0: 0x6881,
    0x97C1: 0x6DBC,
    0x97C2: 0x731F,
    0x97C3: 0x7642,
    0x97C4: 0x77AD,
    0x97C5: 0x7A1C,
    0x97C6: 0x7CE7,
    0x97C7: 0x826F,
    0x97C8: 0x8AD2,
    0x97C9: 0x907C,
    0x97CA: 0x91CF,
    0x97CB: 0x9675,
    0x97CC: 0x9818,
    0x97CD: 0x529B,
    0x97CE: 0x7DD1,
    0x97CF: 0x502B,
    0x97D0: 0x5398,
    0x97D1: 0x6797,
    0x97D2: 0x6DCB,
    0x97D3: 0x71D0,
    0x97D4: 0x7433,
    0x97D5: 0x81E8,
    0x97D6: 0x8F2A,
    0x97D7: 0x96A3,
    0x97D8: 0x9C57,
    0x97D9: 0x9E9F,
    0x97DA: 0x7460,
    0x97DB: 0x5841,
    0x97DC: 0x6D99,
    0x97DD: 0x7D2F,
    0x97DE: 0x985E,
    0x97DF: 0x4EE4,
    0x97E0: 0x4F36,
    0x97E1: 0x4F8B,
    0x97E2: 0x51B7,
    0x97E3: 0x52B1,
    0x97E4: 0x5DBA,
    0x97E5: 0x601C,
    0x97E6: 0x73B2,
    0x97E7: 0x793C,
    0x97E8: 0x82D3,
    0x97E9: 0x9234,
    0x97EA: 0x96B7,
    0x97EB: 0x96F6,
    0x97EC: 0x970A,
    0x97ED: 0x9E97,
    0x97EE: 0x9F62,
    0x97EF: 0x66A6,
    0x97F0: 0x6B74,
    0x97F1: 0x5217,
    0x97F2: 0x52A3,
    0x97F3: 0x70C8,
    0x97F4: 0x88C2,
    0x97F5: 0x5EC9,
    0x97F6: 0x604B,
    0x97F7: 0x6190,
    0x97F8: 0x6F23,
    0x97F9: 0x7149,
    0x97FA: 0x7C3E,
    0x97FB: 0x7DF4,
    0x97FC: 0x806F,
    0x9840: 0x84EE,
    0x9841: 0x9023,
    0x9842: 0x932C,
    0x9843: 0x5442,
    0x9844: 0x9B6F,
    0x9845: 0x6AD3,
    0x9846: 0x7089,
    0x9847: 0x8CC2,
    0x9848: 0x8DEF,
    0x9849: 0x9732,
    0x984A: 0x52B4,
    0x984B: 0x5A41,
    0x984C: 0x5ECA,
    0x984D: 0x5F04,
    0x984E: 0x6717,
    0x984F: 0x697C,
    0x9850: 0x6994,
    0x9851: 0x6D6A,
    0x9852: 0x6F0F,
    0x9853: 0x7262,
    0x9854: 0x72FC,
    0x9855: 0x7BED,
    0x9856: 0x8001,
    0x9857: 0x807E,
    0x9858: 0x874B,
    0x9859: 0x90CE,
    0x985A: 0x516D,
    0x985B: 0x9E93,
    0x985C: 0x7984,
    0x985D: 0x808B,
    0x985E: 0x9332,
    0x985F: 0x8AD6,
    0x9860: 0x502D,
    0x9861: 0x548C,
    0x9862: 0x8A71,
    0x9863: 0x6B6A,
    0x9864: 0x8CC4,
    0x9865: 0x8107,
    0x9866: 0x60D1,
    0x9867: 0x67A0,
    0x9868: 0x9DF2,
    0x9869: 0x4E99,
    0x986A: 0x4E98,
    0x986B: 0x9C10,
    0x986C: 0x8A6B,
    0x986D: 0x85C1,
    0x986E: 0x8568,
    0x986F: 0x6900,
    0x9870: 0x6E7E,
    0x9871: 0x7897,
    0x9872: 0x8155,
    0x989F: 0x5F0C,
    0x98A0: 0x4E10,
    0x98A1: 0x4E15,
    0x98A2: 0x4E2A,
    0x98A3: 0x4E31,
    0x98A4: 0x4E36,
    0x98A5: 0x4E3C,
    0x98A6: 0x4E3F,
    0x98A7: 0x4E42,
    0x98A8: 0x4E56,
    0x98A9: 0x4E58,
    0x98AA: 0x4E82,
    0x98AB: 0x4E85,
    0x98AC: 0x8C6B,
    0x98AD: 0x4E8A,
    0x98AE: 0x8212,
    0x98AF: 0x5F0D,
    0x98B0: 0x4E8E,
    0x98B1: 0x4E9E,
    0x98B2: 0x4E9F,
    0x98B3: 0x4EA0,
    0x98B4: 0x4EA2,
    0x98B5: 0x4EB0,
    0x98B6: 0x4EB3,
    0x98B7: 0x4EB6,
    0x98B8: 0x4ECE,
    0x98B9: 0x4ECD,
    0x98BA: 0x4EC4,
    0x98BB: 0x4EC6,
    0x98BC: 0x4EC2,
    0x98BD: 0x4ED7,
    0x98BE: 0x4EDE,
    0x98BF: 0x4EED,
    0x98C0: 0x4EDF,
    0x98C1: 0x4EF7,
    0x98C2: 0x4F09,
    0x98C3: 0x4F5A,
    0x98C4: 0x4F30,
    0x98C5: 0x4F5B,
    0x98C6: 0x4F5D,
    0x98C7: 0x4F57,
    0x98C8: 0x4F47,
    0x98C9: 0x4F76,
    0x98CA: 0x4F88,
    0x98CB: 0x4F8F,
    0x98CC: 0x4F98,
    0x98CD: 0x4F7B,
    0x98CE: 0x4F69,
    0x98CF: 0x4F70,
    0x98D0: 0x4F91,
    0x98D1: 0x4F6F,
    0x98D2: 0x4F86,
    0x98D3: 0x4F96,
    0x98D4: 0x5118,
    0x98D5: 0x4FD4,
    0x98D6: 0x4FDF,
    0x98D7: 0x4FCE,
    0x98D8: 0x4FD8,
    0x98D9: 0x4FDB,
    0x98DA: 0x4FD1,
    0x98DB: 0x4FDA,
    0x98DC: 0x4FD0,
    0x98DD: 0x4FE4,
    0x98DE: 0x4FE5,
    0x98DF: 0x501A,
    0x98E0: 0x5028,
    0x98E1: 0x5014,
    0x98E2: 0x502A,
    0x98E3: 0x5025,
    0x98E4: 0x5005,
    0x98E5: 0x4F1C,
    0x98E6: 0x4FF6,
    0x98E7: 0x5021,
    0x98E8: 0x5029,
    0x98E9: 0x502C,
    0x98EA: 0x4FFE,
    0x98EB: 0x4FEF,
    0x98EC: 0x5011,
    0x98ED: 0x5006,
    0x98EE: 0x5043,
    0x98EF: 0x5047,
    0x98F0: 0x6703,
    0x98F1: 0x5055,
    0x98F2: 0x5050,
    0x98F3: 0x5048,
    0x98F4: 0x505A,
    0x98F5: 0x5056,
    0x98F6: 0x506C,
    0x98F7: 0x5078,
    0x98F8: 0x5080,
    0x98F9: 0x509A,
    0x98FA: 0x5085,
    0x98FB: 0x50B4,
    0x98FC: 0x50B2,
    0x9940: 0x50C9,
    0x9941: 0x50CA,
    0x9942: 0x50B3,
    0x9943: 0x50C2,
    0x9944: 0x50D6,
    0x9945: 0x50DE,
    0x9946: 0x50E5,
    0x9947: 0x50ED,
    0x9948: 0x50E3,
    0x9949: 0x50EE,
    0x994A: 0x50F9,
    0x994B: 0x50F5,
    0x994C: 0x5109,
    0x994D: 0x5101,
    0x994E: 0x5102,
    0x994F: 0x5116,
    0x9950: 0x5115,
    0x9951: 0x5114,
    0x9952: 0x511A,
    0x9953: 0x5121,
    0x9954: 0x513A,
    0x9955: 0x5137,
    0x9956: 0x513C,
    0x9957: 0x513B,
    0x9958: 0x513F,
    0x9959: 0x5140,
    0x995A: 0x5152,
    0x995B: 0x514C,
    0x995C: 0x5154,
    0x995D: 0x5162,
    0x995E: 0x7AF8,
    0x995F: 0x5169,
    0x9960: 0x516A,
    0x9961: 0x516E,
    0x9962: 0x5180,
    0x9963: 0x5182,
    0x9964: 0x56D8,
    0x9965: 0x518C,
    0x9966: 0x5189,
    0x9967: 0x518F,
    0x9968: 0x5191,
    0x9969: 0x5193,
    0x996A: 0x5195,
    0x996B: 0x5196,
    0x996C: 0x51A4,
    0x996D: 0x51A6,
    0x996E: 0x51A2,
    0x996F: 0x51A9,
    0x9970: 0x51AA,
    0x9971: 0x51AB,
    0x9972: 0x51B3,
    0x9973: 0x51B1,
    0x9974: 0x51B2,
    0x9975: 0x51B0,
    0x9976: 0x51B5,
    0x9977: 0x51BD,
    0x9978: 0x51C5,
    0x9979: 0x51C9,
    0x997A: 0x51DB,
    0x997B: 0x51E0,
    0x997C: 0x8655,
    0x997D: 0x51E9,
    0x997E: 0x51ED,
    0x9980: 0x51F0,
    0x9981: 0x51F5,
    0x9982: 0x51FE,
    0x9983: 0x5204,
    0x9984: 0x520B,
    0x9985: 0x5214,
    0x9986: 0x520E,
    0x9987: 0x5227,
    0x9988: 0x522A,
    0x9989: 0x522E,
    0x998A: 0x5233,
    0x998B: 0x5239,
    0x998C: 0x524F,
    0x998D: 0x5244,
    0x998E: 0x524B,
    0x998F: 0x524C,
    0x9990: 0x525E,
    0x9991: 0x5254,
    0x9992: 0x526A,
    0x9993: 0x5274,
    0x9994: 0x5269,
    0x9995: 0x5273,
    0x9996: 0x527F,
    0x9997: 0x527D,
    0x9998: 0x528D,
    0x9999: 0x5294,
    0x999A: 0x5292,
    0x999B: 0x5271,
    0x999C: 0x5288,
    0x999D: 0x5291,
    0x999E: 0x8FA8,
    0x999F: 0x8FA7,
    0x99A0: 0x52AC,
    0x99A1: 0x52AD,
    0x99A2: 0x52BC,
    0x99A3: 0x52B5,
    0x99A4: 0x52C1,
    0x99A5: 0x52CD,
    0x99A6: 0x52D7,
    0x99A7: 0x52DE,
    0x99A8: 0x52E3,
    0x99A9: 0x52E6,
    0x99AA: 0x98ED,
    0x99AB: 0x52E0,
    0x99AC: 0x52F3,
    0x99AD: 0x52F5,
    0x99AE: 0x52F8,
    0x99AF: 0x52F9,
    0x99B0: 0x5306,
    0x99B1: 0x5308,
    0x99B2: 0x7538,
    0x99B3: 0x530D,
    0x99B4: 0x5310,
    0x99B5: 0x530F,
    0x99B6: 0x5315,
    0x99B7: 0x531A,
    0x99B8: 0x5323,
    0x99B9: 0x532F,
    0x99BA: 0x5331,
    0x99BB: 0x5333,
    0x99BC: 0x5338,
    0x99BD: 0x5340,
    0x99BE: 0x5346,
    0x99BF: 0x5345,
    0x99C0: 0x4E17,
    0x99C1: 0x5349,
    0x99C2: 0x534D,
    0x99C3: 0x51D6,
    0x99C4: 0x535E,
    0x99C5: 0x5369,
    0x99C6: 0x536E,
    0x99C7: 0x5918,
    0x99C8: 0x537B,
    0x99C9: 0x5377,
    0x99CA: 0x5382,
    0x99CB: 0x5396,
    0x99CC: 0x53A0,
    0x99CD: 0x53A6,
    0x99CE: 0x53A5,
    0x99CF: 0x53AE,
    0x99D0: 0x53B0,
    0x99D1: 0x53B6,
    0x99D2: 0x53C3,
    0x99D3: 0x7C12,
    0x99D4: 0x96D9,
    0x99D5: 0x53DF,
    0x99D6: 0x66FC,
    0x99D7: 0x71EE,
    0x99D8: 0x53EE,
    0x99D9: 0x53E8,
    0x99DA: 0x53ED,
    0x99DB: 0x53FA,
    0x99DC: 0x5401,
    0x99DD: 0x543D,
    0x99DE: 0x5440,
    0x99DF: 0x542C,
    0x99E0: 0x542D,
    0x99E1: 0x543C,
    0x99E2: 0x542E,
    0x99E3: 0x5436,
    0x99E4: 0x5429,
    0x99E5: 0x541D,
    0x99E6: 0x544E,
    0x99E7: 0x548F,
    0x99E8: 0x5475,
    0x99E9: 0x548E,
    0x99EA: 0x545F,
    0x99EB: 0x5471,
    0x99EC: 0x5477,
    0x99ED: 0x5470,
    0x99EE: 0x5492,
    0x99EF: 0x547B,
    0x99F0: 0x5480,
    0x99F1: 0x5476,
    0x99F2: 0x5484,
    0x99F3: 0x5490,
    0x99F4: 0x5486,
    0x99F5: 0x54C7,
    0x99F6: 0x54A2,
    0x99F7: 0x54B8,
    0x99F8: 0x54A5,
    0x99F9: 0x54AC,
    0x99FA: 0x54C4,
    0x99FB: 0x54C8,
    0x99FC: 0x54A8,
    0x9A40: 0x54AB,
    0x9A41: 0x54C2,
    0x9A42: 0x54A4,
    0x9A43: 0x54BE,
    0x9A44: 0x54BC,
    0x9A45: 0x54D8,
    0x9A46: 0x54E5,
    0x9A47: 0x54E6,
    0x9A48: 0x550F,
    0x9A49: 0x5514,
    0x9A4A: 0x54FD,
    0x9A4B: 0x54EE,
    0x9A4C: 0x54ED,
    0x9A4D: 0x54FA,
    0x9A4E: 0x54E2,
    0x9A4F: 0x5539,
    0x9A50: 0x5540,
    0x9A51: 0x5563,
    0x9A52: 0x554C,
    0x9A53: 0x552E,
    0x9A54: 0x555C,
    0x9A55: 0x5545,
    0x9A56: 0x5556,
    0x9A57: 0x5557,
    0x9A58: 0x5538,
    0x9A59: 0x5533,
    0x9A5A: 0x555D,
    0x9A5B: 0x5599,
    0x9A5C: 0x5580,
    0x9A5D: 0x54AF,
    0x9A5E: 0x558A,
    0x9A5F: 0x559F,
    0x9A60: 0x557B,
    0x9A61: 0x557E,
    0x9A62: 0x5598,
    0x9A63: 0x559E,
    0x9A64: 0x55AE,
    0x9A65: 0x557C,
    0x9A66: 0x5583,
    0x9A67: 0x55A9,
    0x9A68: 0x5587,
    0x9A69: 0x55A8,
    0x9A6A: 0x55DA,
    0x9A6B: 0x55C5,
    0x9A6C: 0x55DF,
    0x9A6D: 0x55C4,
    0x9A6E: 0x55DC,
    0x9A6F: 0x55E4,
    0x9A70: 0x55D4,
    0x9A71: 0x5614,
    0x9A72: 0x55F7,
    0x9A73: 0x5616,
    0x9A74: 0x55FE,
    0x9A75: 0x55FD,
    0x9A76: 0x561B,
    0x9A77: 0x55F9,
    0x9A78: 0x564E,
    0x9A79: 0x5650,
    0x9A7A: 0x71DF,
    0x9A7B: 0x5634,
    0x9A7C: 0x5636,
    0x9A7D: 0x5632,
    0x9A7E: 0x5638,
    0x9A80: 0x566B,
    0x9A81: 0x5664,
    0x9A82: 0x562F,
    0x9A83: 0x566C,
    0x9A84: 0x566A,
    0x9A85: 0x5686,
    0x9A86: 0x5680,
    0x9A87: 0x568A,
    0x9A88: 0x56A0,
    0x9A89: 0x5694,
    0x9A8A: 0x568F,
    0x9A8B: 0x56A5,
    0x9A8C: 0x56AE,
    0x9A8D: 0x56B6,
    0x9A8E: 0x56B4,
    0x9A8F: 0x56C2,
    0x9A90: 0x56BC,
    0x9A91: 0x56C1,
    0x9A92: 0x56C3,
    0x9A93: 0x56C0,
    0x9A94: 0x56C8,
    0x9A95: 0x56CE,
    0x9A96: 0x56D1,
    0x9A97: 0x56D3,
    0x9A98: 0x56D7,
    0x9A99: 0x56EE,
    0x9A9A: 0x56F9,
    0x9A9B: 0x5700,
    0x9A9C: 0x56FF,
    0x9A9D: 0x5704,
    0x9A9E: 0x5709,
    0x9A9F: 0x5708,
    0x9AA0: 0x570B,
    0x9AA1: 0x570D,
    0x9AA2: 0x5713,
    0x9AA3: 0x5718,
    0x9AA4: 0x5716,
    0x9AA5: 0x55C7,
    0x9AA6: 0x571C,
    0x9AA7: 0x5726,
    0x9AA8: 0x5737,
    0x9AA9: 0x5738,
    0x9AAA: 0x574E,
    0x9AAB: 0x573B,
    0x9AAC: 0x5740,
    0x9AAD: 0x574F,
    0x9AAE: 0x5769,
    0x9AAF: 0x57C0,
    0x9AB0: 0x5788,
    0x9AB1: 0x5761,
    0x9AB2: 0x577F,
    0x9AB3: 0x5789,
    0x9AB4: 0x5793,
    0x9AB5: 0x57A0,
    0x9AB6: 0x57B3,
    0x9AB7: 0x57A4,
    0x9AB8: 0x57AA,
    0x9AB9: 0x57B0,
    0x9ABA: 0x57C3,
    0x9ABB: 0x57C6,
    0x9ABC: 0x57D4,
    0x9ABD: 0x57D2,
    0x9ABE: 0x57D3,
    0x9ABF: 0x580A,
    0x9AC0: 0x57D6,
    0x9AC1: 0x57E3,
    0x9AC2: 0x580B,
    0x9AC3: 0x5819,
    0x9AC4: 0x581D,
    0x9AC5: 0x5872,
    0x9AC6: 0x5821,
    0x9AC7: 0x5862,
    0x9AC8: 0x584B,
    0x9AC9: 0x5870,
    0x9ACA: 0x6BC0,
    0x9ACB: 0x5852,
    0x9ACC: 0x583D,
    0x9ACD: 0x5879,
    0x9ACE: 0x5885,
    0x9ACF: 0x58B9,
    0x9AD0: 0x589F,
    0x9AD1: 0x58AB,
    0x9AD2: 0x58BA,
    0x9AD3: 0x58DE,
    0x9AD4: 0x58BB,
    0x9AD5: 0x58B8,
    0x9AD6: 0x58AE,
    0x9AD7: 0x58C5,
    0x9AD8: 0x58D3,
    0x9AD9: 0x58D1,
    0x9ADA: 0x58D7,
    0x9ADB: 0x58D9,
    0x9ADC: 0x58D8,
    0x9ADD: 0x58E5,
    0x9ADE: 0x58DC,
    0x9ADF: 0x58E4,
    0x9AE0: 0x58DF,
    0x9AE1: 0x58EF,
    0x9AE2: 0x58FA,
    0x9AE3: 0x58F9,
    0x9AE4: 0x58FB,
    0x9AE5: 0x58FC,
    0x9AE6: 0x58FD,
    0x9AE7: 0x5902,
    0x9AE8: 0x590A,
    0x9AE9: 0x5910,
    0x9AEA: 0x591B,
    0x9AEB: 0x68A6,
    0x9AEC: 0x5925,
    0x9AED: 0x592C,
    0x9AEE: 0x592D,
    0x9AEF: 0x5932,
    0x9AF0: 0x5938,
    0x9AF1: 0x593E,
    0x9AF2: 0x7AD2,
    0x9AF3: 0x5955,
    0x9AF4: 0x5950,
    0x9AF5: 0x594E,
    0x9AF6: 0x595A,
    0x9AF7: 0x5958,
    0x9AF8: 0x5962,
    0x9AF9: 0x5960,
    0x9AFA: 0x5967,
    0x9AFB: 0x596C,
    0x9AFC: 0x5969,
    0x9B40: 0x5978,
    0x9B41: 0x5981,
    0x9B42: 0x599D,
    0x9B43: 0x4F5E,
    0x9B44: 0x4FAB,
    0x9B45: 0x59A3,
    0x9B46: 0x59B2,
    0x9B47: 0x59C6,
    0x9B48: 0x59E8,
    0x9B49: 0x59DC,
    0x9B4A: 0x598D,
    0x9B4B: 0x59D9,
    0x9B4C: 0x59DA,
    0x9B4D: 0x5A25,
    0x9B4E: 0x5A1F,
    0x9B4F: 0x5A11,
    0x9B50: 0x5A1C,
    0x9B51: 0x5A09,
    0x9B52: 0x5A1A,
    0x9B53: 0x5A40,
    0x9B54: 0x5A6C,
    0x9B55: 0x5A49,
    0x9B56: 0x5A35,
    0x9B57: 0x5A36,
    0x9B58: 0x5A62,
    0x9B59: 0x5A6A,
    0x9B5A: 0x5A9A,
    0x9B5B: 0x5ABC,
    0x9B5C: 0x5ABE,
    0x9B5D: 0x5ACB,
    0x9B5E: 0x5AC2,
    0x9B5F: 0x5ABD,
    0x9B60: 0x5AE3,
    0x9B61: 0x5AD7,
    0x9B62: 0x5AE6,
    0x9B63: 0x5AE9,
    0x9B64: 0x5AD6,
    0x9B65: 0x5AFA,
    0x9B66: 0x5AFB,
    0x9B67: 0x5B0C,
    0x9B68: 0x5B0B,
    0x9B69: 0x5B16,
    0x9B6A: 0x5B32,
    0x9B6B: 0x5AD0,
    0x9B6C: 0x5B2A,
    0x9B6D: 0x5B36,
    0x9B6E: 0x5B3E,
    0x9B6F: 0x5B43,
    0x9B70: 0x5B45,
    0x9B71: 0x5B40,
    0x9B72: 0x5B51,
    0x9B73: 0x5B55,
    0x9B74: 0x5B5A,
    0x9B75: 0x5B5B,
    0x9B76: 0x5B65,
    0x9B77: 0x5B69,
    0x9B78: 0x5B70,
    0x9B79: 0x5B73,
    0x9B7A: 0x5B75,
    0x9B7B: 0x5B78,
    0x9B7C: 0x6588,
    0x9B7D: 0x5B7A,
    0x9B7E: 0x5B80,
    0x9B80: 0x5B83,
    0x9B81: 0x5BA6,
    0x9B82: 0x5BB8,
    0x9B83: 0x5BC3,
    0x9B84: 0x5BC7,
    0x9B85: 0x5BC9,
    0x9B86: 0x5BD4,
    0x9B87: 0x5BD0,
    0x9B88: 0x5BE4,
    0x9B89: 0x5BE6,
    0x9B8A: 0x5BE2,
    0x9B8B: 0x5BDE,
    0x9B8C: 0x5BE5,
    0x9B8D: 0x5BEB,
    0x9B8E: 0x5BF0,
    0x9B8F: 0x5BF6,
    0x9B90: 0x5BF3,
    0x9B91: 0x5C05,
    0x9B92: 0x5C07,
    0x9B93: 0x5C08,
    0x9B94: 0x5C0D,
    0x9B95: 0x5C13,
    0x9B96: 0x5C20,
    0x9B97: 0x5C22,
    0x9B98: 0x5C28,
    0x9B99: 0x5C38,
    0x9B9A: 0x5C39,
    0x9B9B: 0x5C41,
    0x9B9C: 0x5C46,
    0x9B9D: 0x5C4E,
    0x9B9E: 0x5C53,
    0x9B9F: 0x5C50,
    0x9BA0: 0x5C4F,
    0x9BA1: 0x5B71,
    0x9BA2: 0x5C6C,
    0x9BA3: 0x5C6E,
    0x9BA4: 0x4E62,
    0x9BA5: 0x5C76,
    0x9BA6: 0x5C79,
    0x9BA7: 0x5C8C,
    0x9BA8: 0x5C91,
    0x9BA9: 0x5C94,
    0x9BAA: 0x599B,
    0x9BAB: 0x5CAB,
    0x9BAC: 0x5CBB,
    0x9BAD: 0x5CB6,
    0x9BAE: 0x5CBC,
    0x9BAF: 0x5CB7,
    0x9BB0: 0x5CC5,
    0x9BB1: 0x5CBE,
    0x9BB2: 0x5CC7,
    0x9BB3: 0x5CD9,
    0x9BB4: 0x5CE9,
    0x9BB5: 0x5CFD,
    0x9BB6: 0x5CFA,
    0x9BB7: 0x5CED,
    0x9BB8: 0x5D8C,
    0x9BB9: 0x5CEA,
    0x9BBA: 0x5D0B,
    0x9BBB: 0x5D15,
    0x9BBC: 0x5D17,
    0x9BBD: 0x5D5C,
    0x9BBE: 0x5D1F,
    0x9BBF: 0x5D1B,
    0x9BC0: 0x5D11,
    0x9BC1: 0x5D14,
    0x9BC2: 0x5D22,
    0x9BC3: 0x5D1A,
    0x9BC4: 0x5D19,
    0x9BC5: 0x5D18,
    0x9BC6: 0x5D4C,
    0x9BC7: 0x5D52,
    0x9BC8: 0x5D4E,
    0x9BC9: 0x5D4B,
    0x9BCA: 0x5D6C,
    0x9BCB: 0x5D73,
    0x9BCC: 0x5D76,
    0x9BCD: 0x5D87,
    0x9BCE: 0x5D84,
    0x9BCF: 0x5D82,
    0x9BD0: 0x5DA2,
    0x9BD1: 0x5D9D,
    0x9BD2: 0x5DAC,
    0x9BD3: 0x5DAE,
    0x9BD4: 0x5DBD,
    0x9BD5: 0x5D90,
    0x9BD6: 0x5DB7,
    0x9BD7: 0x5DBC,
    0x9BD8: 0x5DC9,
    0x9BD9: 0x5DCD,
    0x9BDA: 0x5DD3,
    0x9BDB: 0x5DD2,
    0x9BDC: 0x5DD6,
    0x9BDD: 0x5DDB,
    0x9BDE: 0x5DEB,
    0x9BDF: 0x5DF2,
    0x9BE0: 0x5DF5,
    0x9BE1: 0x5E0B,
    0x9BE2: 0x5E1A,
    0x9BE3: 0x5E19,
    0x9BE4: 0x5E11,
    0x9BE5: 0x5E1B,
    0x9BE6: 0x5E36,
    0x9BE7: 0x5E37,
    0x9BE8: 0x5E44,
    0x9BE9: 0x5E43,
    0x9BEA: 0x5E40,
    0x9BEB: 0x5E4E,
    0x9BEC: 0x5E57,
    0x9BED: 0x5E54,
    0x9BEE: 0x5E5F,
    0x9BEF: 0x5E62,
    0x9BF0: 0x5E64,
    0x9BF1: 0x5E47,
    0x9BF2: 0x5E75,
    0x9BF3: 0x5E76,
    0x9BF4: 0x5E7A,
    0x9BF5: 0x9EBC,
    0x9BF6: 0x5E7F,
    0x9BF7: 0x5EA0,
    0x9BF8: 0x5EC1,
    0x9BF9: 0x5EC2,
    0x9BFA: 0x5EC8,
    0x9BFB: 0x5ED0,
    0x9BFC: 0x5ECF,
    0x9C40: 0x5ED6,
    0x9C41: 0x5EE3,
    0x9C42: 0x5EDD,
    0x9C43: 0x5EDA,
    0x9C44: 0x5EDB,
    0x9C45: 0x5EE2,
    0x9C46: 0x5EE1,
    0x9C47: 0x5EE8,
    0x9C48: 0x5EE9,
    0x9C49: 0x5EEC,
    0x9C4A: 0x5EF1,
    0x9C4B: 0x5EF3,
    0x9C4C: 0x5EF0,
    0x9C4D: 0x5EF4,
    0x9C4E: 0x5EF8,
    0x9C4F: 0x5EFE,
    0x9C50: 0x5F03,
    0x9C51: 0x5F09,
    0x9C52: 0x5F5D,
    0x9C53: 0x5F5C,
    0x9C54: 0x5F0B,
    0x9C55: 0x5F11,
    0x9C56: 0x5F16,
    0x9C57: 0x5F29,
    0x9C58: 0x5F2D,
    0x9C59: 0x5F38,
    0x9C5A: 0x5F41,
    0x9C5B: 0x5F48,
    0x9C5C: 0x5F4C,
    0x9C5D: 0x5F4E,
    0x9C5E: 0x5F2F,
    0x9C5F: 0x5F51,
    0x9C60: 0x5F56,
    0x9C61: 0x5F57,
    0x9C62: 0x5F59,
    0x9C63: 0x5F61,
    0x9C64: 0x5F6D,
    0x9C65: 0x5F73,
    0x9C66: 0x5F77,
    0x9C67: 0x5F83,
    0x9C68: 0x5F82,
    0x9C69: 0x5F7F,
    0x9C6A: 0x5F8A,
    0x9C6B: 0x5F88,
    0x9C6C: 0x5F91,
    0x9C6D: 0x5F87,
    0x9C6E: 0x5F9E,
    0x9C6F: 0x5F99,
    0x9C70: 0x5F98,
    0x9C71: 0x5FA0,
    0x9C72: 0x5FA8,
    0x9C73: 0x5FAD,
    0x9C74: 0x5FBC,
    0x9C75: 0x5FD6,
    0x9C76: 0x5FFB,
    0x9C77: 0x5FE4,
    0x9C78: 0x5FF8,
    0x9C79: 0x5FF1,
    0x9C7A: 0x5FDD,
    0x9C7B: 0x60B3,
    0x9C7C: 0x5FFF,
    0x9C7D: 0x6021,
    0x9C7E: 0x6060,
    0x9C80: 0x6019,
    0x9C81: 0x6010,
    0x9C82: 0x6029,
    0x9C83: 0x600E,
    0x9C84: 0x6031,
    0x9C85: 0x601B,
    0x9C86: 0x6015,
    0x9C87: 0x602B,
    0x9C88: 0x6026,
    0x9C89: 0x600F,
    0x9C8A: 0x603A,
    0x9C8B: 0x605A,
    0x9C8C: 0x6041,
    0x9C8D: 0x606A,
    0x9C8E: 0x6077,
    0x9C8F: 0x605F,
    0x9C90: 0x604A,
    0x9C91: 0x6046,
    0x9C92: 0x604D,
    0x9C93: 0x6063,
    0x9C94: 0x6043,
    0x9C95: 0x6064,
    0x9C96: 0x6042,
    0x9C97: 0x606C,
    0x9C98: 0x606B,
    0x9C99: 0x6059,
    0x9C9A: 0x6081,
    0x9C9B: 0x608D,
    0x9C9C: 0x60E7,
    0x9C9D: 0x6083,
    0x9C9E: 0x609A,
    0x9C9F: 0x6084,
    0x9CA0: 0x609B,
    0x9CA1: 0x6096,
    0x9CA2: 0x6097,
    0x9CA3: 0x6092,
    0x9CA4: 0x60A7,
    0x9CA5: 0x608B,
    0x9CA6: 0x60E1,
    0x9CA7: 0x60B8,
    0x9CA8: 0x60E0,
    0x9CA9: 0x60D3,
    0x9CAA: 0x60B4,
    0x9CAB: 0x5FF0,
    0x9CAC: 0x60BD,
    0x9CAD: 0x60C6,
    0x9CAE: 0x60B5,
    0x9CAF: 0x60D8,
    0x9CB0: 0x614D,
    0x9CB1: 0x6115,
    0x9CB2: 0x6106,
    0x9CB3: 0x60F6,
    0x9CB4: 0x60F7,
    0x9CB5: 0x6100,
    0x9CB6: 0x60F4,
    0x9CB7: 0x60FA,
    0x9CB8: 0x6103,
    0x9CB9: 0x6121,
    0x9CBA: 0x60FB,
    0x9CBB: 0x60F1,
    0x9CBC: 0x610D,
    0x9CBD: 0x610E,
    0x9CBE: 0x6147,
    0x9CBF: 0x613E,
    0x9CC0: 0x6128,
    0x9CC1: 0x6127,
    0x9CC2: 0x614A,
    0x9CC3: 0x613F,
    0x9CC4: 0x613C,
    0x9CC5: 0x612C,
    0x9CC6: 0x6134,
    0x9CC7: 0x613D,
    0x9CC8: 0x6142,
    0x9CC9: 0x6144,
    0x9CCA: 0x6173,
    0x9CCB: 0x6177,
    0x9CCC: 0x6158,
    0x9CCD: 0x6159,
    0x9CCE: 0x615A,
    0x9CCF: 0x616B,
    0x9CD0: 0x6174,
    0x9CD1: 0x616F,
    0x9CD2: 0x6165,
    0x9CD3: 0x6171,
    0x9CD4: 0x615F,
    0x9CD5: 0x615D,
    0x9CD6: 0x6153,
    0x9CD7: 0x6175,
    0x9CD8: 0x6199,
    0x9CD9: 0x6196,
    0x9CDA: 0x6187,
    0x9CDB: 0x61AC,
    0x9CDC: 0x6194,
    0x9CDD: 0x619A,
    0x9CDE: 0x618A,
    0x9CDF: 0x6191,
    0x9CE0: 0x61AB,
    0x9CE1: 0x61AE,
    0x9CE2: 0x61CC,
    0x9CE3: 0x61CA,
    0x9CE4: 0x61C9,
    0x9CE5: 0x61F7,
    0x9CE6: 0x61C8,
    0x9CE7: 0x61C3,
    0x9CE8: 0x61C6,
    0x9CE9: 0x61BA,
    0x9CEA: 0x61CB,
    0x9CEB: 0x7F79,
    0x9CEC: 0x61CD,
    0x9CED: 0x61E6,
    0x9CEE: 0x61E3,
    0x9CEF: 0x61F6,
    0x9CF0: 0x61FA,
    0x9CF1: 0x61F4,
    0x9CF2: 0x61FF,
    0x9CF3: 0x61FD,
    0x9CF4: 0x61FC,
    0x9CF5: 0x61FE,
    0x9CF6: 0x6200,
    0x9CF7: 0x6208,
    0x9CF8: 0x6209,
    0x9CF9: 0x620D,
    0x9CFA: 0x620C,
    0x9CFB: 0x6214,
    0x9CFC: 0x621B,
    0x9D40: 0x621E,
    0x9D41: 0x6221,
    0x9D42: 0x622A,
    0x9D43: 0x622E,
    0x9D44: 0x6230,
    0x9D45: 0x6232,
    0x9D46: 0x6233,
    0x9D47: 0x6241,
    0x9D48: 0x624E,
    0x9D49: 0x625E,
    0x9D4A: 0x6263,
    0x9D4B: 0x625B,
    0x9D4C: 0x6260,
    0x9D4D: 0x6268,
    0x9D4E: 0x627C,
    0x9D4F: 0x6282,
    0x9D50: 0x6289,
    0x9D51: 0x627E,
    0x9D52: 0x6292,
    0x9D53: 0x6293,
    0x9D54: 0x6296,
    0x9D55: 0x62D4,
    0x9D56: 0x6283,
    0x9D57: 0x6294,
    0x9D58: 0x62D7,
    0x9D59: 0x62D1,
    0x9D5A: 0x62BB,
    0x9D5B: 0x62CF,
    0x9D5C: 0x62FF,
    0x9D5D: 0x62C6,
    0x9D5E: 0x64D4,
    0x9D5F: 0x62C8,
    0x9D60: 0x62DC,
    0x9D61: 0x62CC,
    0x9D62: 0x62CA,
    0x9D63: 0x62C2,
    0x9D64: 0x62C7,
    0x9D65: 0x629B,
    0x9D66: 0x62C9,
    0x9D67: 0x630C,
    0x9D68: 0x62EE,
    0x9D69: 0x62F1,
    0x9D6A: 0x6327,
    0x9D6B: 0x6302,
    0x9D6C: 0x6308,
    0x9D6D: 0x62EF,
    0x9D6E: 0x62F5,
    0x9D6F: 0x6350,
    0x9D70: 0x633E,
    0x9D71: 0x634D,
    0x9D72: 0x641C,
    0x9D73: 0x634F,
    0x9D74: 0x6396,
    0x9D75: 0x638E,
    0x9D76: 0x6380,
    0x9D77: 0x63AB,
    0x9D78: 0x6376,
    0x9D79: 0x63A3,
    0x9D7A: 0x638F,
    0x9D7B: 0x6389,
    0x9D7C: 0x639F,
    0x9D7D: 0x63B5,
    0x9D7E: 0x636B,
    0x9D80: 0x6369,
    0x9D81: 0x63BE,
    0x9D82: 0x63E9,
    0x9D83: 0x63C0,
    0x9D84: 0x63C6,
    0x9D85: 0x63E3,
    0x9D86: 0x63C9,
    0x9D87: 0x63D2,
    0x9D88: 0x63F6,
    0x9D89: 0x63C4,
    0x9D8A: 0x6416,
    0x9D8B: 0x6434,
    0x9D8C: 0x6406,
    0x9D8D: 0x6413,
    0x9D8E: 0x6426,
    0x9D8F: 0x6436,
    0x9D90: 0x651D,
    0x9D91: 0x6417,
    0x9D92: 0x6428,
    0x9D93: 0x640F,
    0x9D94: 0x6467,
    0x9D95: 0x646F,
    0x9D96: 0x6476,
    0x9D97: 0x644E,
    0x9D98: 0x652A,
    0x9D99: 0x6495,
    0x9D9A: 0x6493,
    0x9D9B: 0x64A5,
    0x9D9C: 0x64A9,
    0x9D9D: 0x6488,
    0x9D9E: 0x64BC,
    0x9D9F: 0x64DA,
    0x9DA0: 0x64D2,
    0x9DA1: 0x64C5,
    0x9DA2: 0x64C7,
    0x9DA3: 0x64BB,
    0x9DA4: 0x64D8,
    0x9DA5: 0x64C2,
    0x9DA6: 0x64F1,
    0x9DA7: 0x64E7,
    0x9DA8: 0x8209,
    0x9DA9: 0x64E0,
    0x9DAA: 0x64E1,
    0x9DAB: 0x62AC,
    0x9DAC: 0x64E3,
    0x9DAD: 0x64EF,
    0x9DAE: 0x652C,
    0x9DAF: 0x64F6,
    0x9DB0: 0x64F4,
    0x9DB1: 0x64F2,
    0x9DB2: 0x64FA,
    0x9DB3: 0x6500,
    0x9DB4: 0x64FD,
    0x9DB5: 0x6518,
    0x9DB6: 0x651C,
    0x9DB7: 0x6505,
    0x9DB8: 0x6524,
    0x9DB9: 0x6523,
    0x9DBA: 0x652B,
    0x9DBB: 0x6534,
    0x9DBC: 0x6535,
    0x9DBD: 0x6537,
    0x9DBE: 0x6536,
    0x9DBF: 0x6538,
    0x9DC0: 0x754B,
    0x9DC1: 0x6548,
    0x9DC2: 0x6556,
    0x9DC3: 0x6555,
    0x9DC4: 0x654D,
    0x9DC5: 0x6558,
    0x9DC6: 0x655E,
    0x9DC7: 0x655D,
    0x9DC8: 0x6572,
    0x9DC9: 0x6578,
    0x9DCA: 0x6582,
    0x9DCB: 0x6583,
    0x9DCC: 0x8B8A,
    0x9DCD: 0x659B,
    0x9DCE: 0x659F,
    0x9DCF: 0x65AB,
    0x9DD0: 0x65B7,
    0x9DD1: 0x65C3,
    0x9DD2: 0x65C6,
    0x9DD3: 0x65C1,
    0x9DD4: 0x65C4,
    0x9DD5: 0x65CC,
    0x9DD6: 0x65D2,
    0x9DD7: 0x65DB,
    0x9DD8: 0x65D9,
    0x9DD9: 0x65E0,
    0x9DDA: 0x65E1,
    0x9DDB: 0x65F1,
    0x9DDC: 0x6772,
    0x9DDD: 0x660A,
    0x9DDE: 0x6603,
    0x9DDF: 0x65FB,
    0x9DE0: 0x6773,
    0x9DE1: 0x6635,
    0x9DE2: 0x6636,
    0x9DE3: 0x6634,
    0x9DE4: 0x661C,
    0x9DE5: 0x664F,
    0x9DE6: 0x6644,
    0x9DE7: 0x6649,
    0x9DE8: 0x6641,
    0x9DE9: 0x665E,
    0x9DEA: 0x665D,
    0x9DEB: 0x6664,
    0x9DEC: 0x6667,
    0x9DED: 0x6668,
    0x9DEE: 0x665F,
    0x9DEF: 0x6662,
    0x9DF0: 0x6670,
    0x9DF1: 0x6683,
    0x9DF2: 0x6688,
    0x9DF3: 0x668E,
    0x9DF4: 0x6689,
    0x9DF5: 0x6684,
    0x9DF6: 0x6698,
    0x9DF7: 0x669D,
    0x9DF8: 0x66C1,
    0x9DF9: 0x66B9,
    0x9DFA: 0x66C9,
    0x9DFB: 0x66BE,
    0x9DFC: 0x66BC,
    0x9E40: 0x66C4,
    0x9E41: 0x66B8,
    0x9E42: 0x66D6,
    0x9E43: 0x66DA,
    0x9E44: 0x66E0,
    0x9E45: 0x663F,
    0x9E46: 0x66E6,
    0x9E47: 0x66E9,
    0x9E48: 0x66F0,
    0x9E49: 0x66F5,
    0x9E4A: 0x66F7,
    0x9E4B: 0x670F,
    0x9E4C: 0x6716,
    0x9E4D: 0x671E,
    0x9E4E: 0x6726,
    0x9E4F: 0x6727,
    0x9E50: 0x9738,
    0x9E51: 0x672E,
    0x9E52: 0x673F,
    0x9E53: 0x6736,
    0x9E54: 0x6741,
    0x9E55: 0x6738,
    0x9E56: 0x6737,
    0x9E57: 0x6746,
    0x9E58: 0x675E,
    0x9E59: 0x6760,
    0x9E5A: 0x6759,
    0x9E5B: 0x6763,
    0x9E5C: 0x6764,
    0x9E5D: 0x6789,
    0x9E5E: 0x6770,
    0x9E5F: 0x67A9,
    0x9E60: 0x677C,
    0x9E61: 0x676A,
    0x9E62: 0x678C,
    0x9E63: 0x678B,
    0x9E64: 0x67A6,
    0x9E65: 0x67A1,
    0x9E66: 0x6785,
    0x9E67: 0x67B7,
    0x9E68: 0x67EF,
    0x9E69: 0x67B4,
    0x9E6A: 0x67EC,
    0x9E6B: 0x67B3,
    0x9E6C: 0x67E9,
    0x9E6D: 0x67B8,
    0x9E6E: 0x67E4,
    0x9E6F: 0x67DE,
    0x9E70: 0x67DD,
    0x9E71: 0x67E2,
    0x9E72: 0x67EE,
    0x9E73: 0x67B9,
    0x9E74: 0x67CE,
    0x9E75: 0x67C6,
    0x9E76: 0x67E7,
    0x9E77: 0x6A9C,
    0x9E78: 0x681E,
    0x9E79: 0x6846,
    0x9E7A: 0x6829,
    0x9E7B: 0x6840,
    0x9E7C: 0x684D,
    0x9E7D: 0x6832,
    0x9E7E: 0x684E,
    0x9E80: 0x68B3,
    0x9E81: 0x682B,
    0x9E82: 0x6859,
    0x9E83: 0x6863,
    0x9E84: 0x6877,
    0x9E85: 0x687F,
    0x9E86: 0x689F,
    0x9E87: 0x688F,
    0x9E88: 0x68AD,
    0x9E89: 0x6894,
    0x9E8A: 0x689D,
    0x9E8B: 0x689B,
    0x9E8C: 0x6883,
    0x9E8D: 0x6AAE,
    0x9E8E: 0x68B9,
    0x9E8F: 0x6874,
    0x9E90: 0x68B5,
    0x9E91: 0x68A0,
    0x9E92: 0x68BA,
    0x9E93: 0x690F,
    0x9E94: 0x688D,
    0x9E95: 0x687E,
    0x9E96: 0x6901,
    0x9E97: 0x68CA,
    0x9E98: 0x6908,
    0x9E99: 0x68D8,
    0x9E9A: 0x6922,
    0x9E9B: 0x6926,
    0x9E9C: 0x68E1,
    0x9E9D: 0x690C,
    0x9E9E: 0x68CD,
    0x9E9F: 0x68D4,
    0x9EA0: 0x68E7,
    0x9EA1: 0x68D5,
    0x9EA2: 0x6936,
    0x9EA3: 0x6912,
    0x9EA4: 0x6904,
    0x9EA5: 0x68D7,
    0x9EA6: 0x68E3,
    0x9EA7: 0x6925,
    0x9EA8: 0x68F9,
    0x9EA9: 0x68E0,
    0x9EAA: 0x68EF,
    0x9EAB: 0x6928,
    0x9EAC: 0x692A,
    0x9EAD: 0x691A,
    0x9EAE: 0x6923,
    0x9EAF: 0x6921,
    0x9EB0: 0x68C6,
    0x9EB1: 0x6979,
    0x9EB2: 0x6977,
    0x9EB3: 0x695C,
    0x9EB4: 0x6978,
    0x9EB5: 0x696B,
    0x9EB6: 0x6954,
    0x9EB7: 0x697E,
    0x9EB8: 0x696E,
    0x9EB9: 0x6939,
    0x9EBA: 0x6974,
    0x9EBB: 0x693D,
    0x9EBC: 0x6959,
    0x9EBD: 0x6930,
    0x9EBE: 0x6961,
    0x9EBF: 0x695E,
    0x9EC0: 0x695D,
    0x9EC1: 0x6981,
    0x9EC2: 0x696A,
    0x9EC3: 0x69B2,
    0x9EC4: 0x69AE,
    0x9EC5: 0x69D0,
    0x9EC6: 0x69BF,
    0x9EC7: 0x69C1,
    0x9EC8: 0x69D3,
    0x9EC9: 0x69BE,
    0x9ECA: 0x69CE,
    0x9ECB: 0x5BE8,
    0x9ECC: 0x69CA,
    0x9ECD: 0x69DD,
    0x9ECE: 0x69BB,
    0x9ECF: 0x69C3,
    0x9ED0: 0x69A7,
    0x9ED1: 0x6A2E,
    0x9ED2: 0x6991,
    0x9ED3: 0x69A0,
    0x9ED4: 0x699C,
    0x9ED5: 0x6995,
    0x9ED6: 0x69B4,
    0x9ED7: 0x69DE,
    0x9ED8: 0x69E8,
    0x9ED9: 0x6A02,
    0x9EDA: 0x6A1B,
    0x9EDB: 0x69FF,
    0x9EDC: 0x6B0A,
    0x9EDD: 0x69F9,
    0x9EDE: 0x69F2,
    0x9EDF: 0x69E7,
    0x9EE0: 0x6A05,
    0x9EE1: 0x69B1,
    0x9EE2: 0x6A1E,
    0x9EE3: 0x69ED,
    0x9EE4: 0x6A14,
    0x9EE5: 0x69EB,
    0x9EE6: 0x6A0A,
    0x9EE7: 0x6A12,
    0x9EE8: 0x6AC1,
    0x9EE9: 0x6A23,
    0x9EEA: 0x6A13,
    0x9EEB: 0x6A44,
    0x9EEC: 0x6A0C,
    0x9EED: 0x6A72,
    0x9EEE: 0x6A36,
    0x9EEF: 0x6A78,
    0x9EF0: 0x6A47,
    0x9EF1: 0x6A62,
    0x9EF2: 0x6A59,
    0x9EF3: 0x6A66,
    0x9EF4: 0x6A48,
    0x9EF5: 0x6A38,
    0x9EF6: 0x6A22,
    0x9EF7: 0x6A90,
    0x9EF8: 0x6A8D,
    0x9EF9: 0x6AA0,
    0x9EFA: 0x6A84,
    0x9EFB: 0x6AA2,
    0x9EFC: 0x6AA3,
    0x9F40: 0x6A97,
    0x9F41: 0x8617,
    0x9F42: 0x6ABB,
    0x9F43: 0x6AC3,
    0x9F44: 0x6AC2,
    0x9F45: 0x6AB8,
    0x9F46: 0x6AB3,
    0x9F47: 0x6AAC,
    0x9F48: 0x6ADE,
    0x9F49: 0x6AD1,
    0x9F4A: 0x6ADF,
    0x9F4B: 0x6AAA,
    0x9F4C: 0x6ADA,
    0x9F4D: 0x6AEA,
    0x9F4E: 0x6AFB,
    0x9F4F: 0x6B05,
    0x9F50: 0x8616,
    0x9F51: 0x6AFA,
    0x9F52: 0x6B12,
    0x9F53: 0x6B16,
    0x9F54: 0x9B31,
    0x9F55: 0x6B1F,
    0x9F56: 0x6B38,
    0x9F57: 0x6B37,
    0x9F58: 0x76DC,
    0x9F59: 0x6B39,
    0x9F5A: 0x98EE,
    0x9F5B: 0x6B47,
    0x9F5C: 0x6B43,
    0x9F5D: 0x6B49,
    0x9F5E: 0x6B50,
    0x9F5F: 0x6B59,
    0x9F60: 0x6B54,
    0x9F61: 0x6B5B,
    0x9F62: 0x6B5F,
    0x9F63: 0x6B61,
    0x9F64: 0x6B78,
    0x9F65: 0x6B79,
    0x9F66: 0x6B7F,
    0x9F67: 0x6B80,
    0x9F68: 0x6B84,
    0x9F69: 0x6B83,
    0x9F6A: 0x6B8D,
    0x9F6B: 0x6B98,
    0x9F6C: 0x6B95,
    0x9F6D: 0x6B9E,
    0x9F6E: 0x6BA4,
    0x9F6F: 0x6BAA,
    0x9F70: 0x6BAB,
    0x9F71: 0x6BAF,
    0x9F72: 0x6BB2,
    0x9F73: 0x6BB1,
    0x9F74: 0x6BB3,
    0x9F75: 0x6BB7,
    0x9F76: 0x6BBC,
    0x9F77: 0x6BC6,
    0x9F78: 0x6BCB,
    0x9F79: 0x6BD3,
    0x9F7A: 0x6BDF,
    0x9F7B: 0x6BEC,
    0x9F7C: 0x6BEB,
    0x9F7D: 0x6BF3,
    0x9F7E: 0x6BEF,
    0x9F80: 0x9EBE,
    0x9F81: 0x6C08,
    0x9F82: 0x6C13,
    0x9F83: 0x6C14,
    0x9F84: 0x6C1B,
    0x9F85: 0x6C24,
    0x9F86: 0x6C23,
    0x9F87: 0x6C5E,
    0x9F88: 0x6C55,
    0x9F89: 0x6C62,
    0x9F8A: 0x6C6A,
    0x9F8B: 0x6C82,
    0x9F8C: 0x6C8D,
    0x9F8D: 0x6C9A,
    0x9F8E: 0x6C81,
    0x9F8F: 0x6C9B,
    0x9F90: 0x6C7E,
    0x9F91: 0x6C68,
    0x9F92: 0x6C73,
    0x9F93: 0x6C92,
    0x9F94: 0x6C90,
    0x9F95: 0x6CC4,
    0x9F96: 0x6CF1,
    0x9F97: 0x6CD3,
    0x9F98: 0x6CBD,
    0x9F99: 0x6CD7,
    0x9F9A: 0x6CC5,
    0x9F9B: 0x6CDD,
    0x9F9C: 0x6CAE,
    0x9F9D: 0x6CB1,
    0x9F9E: 0x6CBE,
    0x9F9F: 0x6CBA,
    0x9FA0: 0x6CDB,
    0x9FA1: 0x6CEF,
    0x9FA2: 0x6CD9,
    0x9FA3: 0x6CEA,
    0x9FA4: 0x6D1F,
    0x9FA5: 0x884D,
    0x9FA6: 0x6D36,
    0x9FA7: 0x6D2B,
    0x9FA8: 0x6D3D,
    0x9FA9: 0x6D38,
    0x9FAA: 0x6D19,
    0x9FAB: 0x6D35,
    0x9FAC: 0x6D33,
    0x9FAD: 0x6D12,
    0x9FAE: 0x6D0C,
    0x9FAF: 0x6D63,
    0x9FB0: 0x6D93,
    0x9FB1: 0x6D64,
    0x9FB2: 0x6D5A,
    0x9FB3: 0x6D79,
    0x9FB4: 0x6D59,
    0x9FB5: 0x6D8E,
    0x9FB6: 0x6D95,
    0x9FB7: 0x6FE4,
    0x9FB8: 0x6D85,
    0x9FB9: 0x6DF9,
    0x9FBA: 0x6E15,
    0x9FBB: 0x6E0A,
    0x9FBC: 0x6DB5,
    0x9FBD: 0x6DC7,
    0x9FBE: 0x6DE6,
    0x9FBF: 0x6DB8,
    0x9FC0: 0x6DC6,
    0x9FC1: 0x6DEC,
    0x9FC2: 0x6DDE,
    0x9FC3: 0x6DCC,
    0x9FC4: 0x6DE8,
    0x9FC5: 0x6DD2,
    0x9FC6: 0x6DC5,
    0x9FC7: 0x6DFA,
    0x9FC8: 0x6DD9,
    0x9FC9: 0x6DE4,
    0x9FCA: 0x6DD5,
    0x9FCB: 0x6DEA,
    0x9FCC: 0x6DEE,
    0x9FCD: 0x6E2D,
    0x9FCE: 0x6E6E,
    0x9FCF: 0x6E2E,
    0x9FD0: 0x6E19,
    0x9FD1: 0x6E72,
    0x9FD2: 0x6E5F,
    0x9FD3: 0x6E3E,
    0x9FD4: 0x6E23,
    0x9FD5: 0x6E6B,
    0x9FD6: 0x6E2B,
    0x9FD7: 0x6E76,
    0x9FD8: 0x6E4D,
    0x9FD9: 0x6E1F,
    0x9FDA: 0x6E43,
    0x9FDB: 0x6E3A,
    0x9FDC: 0x6E4E,
    0x9FDD: 0x6E24,
    0x9FDE: 0x6EFF,
    0x9FDF: 0x6E1D,
    0x9FE0: 0x6E38,
    0x9FE1: 0x6E82,
    0x9FE2: 0x6EAA,
    0x9FE3: 0x6E98,
    0x9FE4: 0x6EC9,
    0x9FE5: 0x6EB7,
    0x9FE6: 0x6ED3,
    0x9FE7: 0x6EBD,
    0x9FE8: 0x6EAF,
    0x9FE9: 0x6EC4,
    0x9FEA: 0x6EB2,
    0x9FEB: 0x6ED4,
    0x9FEC: 0x6ED5,
    0x9FED: 0x6E8F,
    0x9FEE: 0x6EA5,
    0x9FEF: 0x6EC2,
    0x9FF0: 0x6E9F,
    0x9FF1: 0x6F41,
    0x9FF2: 0x6F11,
    0x9FF3: 0x704C,
    0x9FF4: 0x6EEC,
    0x9FF5: 0x6EF8,
    0x9FF6: 0x6EFE,
    0x9FF7: 0x6F3F,
    0x9FF8: 0x6EF2,
    0x9FF9: 0x6F31,
    0x9FFA: 0x6EEF,
    0x9FFB: 0x6F32,
    0x9FFC: 0x6ECC,
    0xA1: 0xFF61,
    0xA2: 0xFF62,
    0xA3: 0xFF63,
    0xA4: 0xFF64,
    0xA5: 0xFF65,
    0xA6: 0xFF66,
    0xA7: 0xFF67,
    0xA8: 0xFF68,
    0xA9: 0xFF69,
    0xAA: 0xFF6A,
    0xAB: 0xFF6B,
    0xAC: 0xFF6C,
    0xAD: 0xFF6D,
    0xAE: 0xFF6E,
    0xAF: 0xFF6F,
    0xB0: 0xFF70,
    0xB1: 0xFF71,
    0xB2: 0xFF72,
    0xB3: 0xFF73,
    0xB4: 0xFF74,
    0xB5: 0xFF75,
    0xB6: 0xFF76,
    0xB7: 0xFF77,
    0xB8: 0xFF78,
    0xB9: 0xFF79,
    0xBA: 0xFF7A,
    0xBB: 0xFF7B,
    0xBC: 0xFF7C,
    0xBD: 0xFF7D,
    0xBE: 0xFF7E,
    0xBF: 0xFF7F,
    0xC0: 0xFF80,
    0xC1: 0xFF81,
    0xC2: 0xFF82,
    0xC3: 0xFF83,
    0xC4: 0xFF84,
    0xC5: 0xFF85,
    0xC6: 0xFF86,
    0xC7: 0xFF87,
    0xC8: 0xFF88,
    0xC9: 0xFF89,
    0xCA: 0xFF8A,
    0xCB: 0xFF8B,
    0xCC: 0xFF8C,
    0xCD: 0xFF8D,
    0xCE: 0xFF8E,
    0xCF: 0xFF8F,
    0xD0: 0xFF90,
    0xD1: 0xFF91,
    0xD2: 0xFF92,
    0xD3: 0xFF93,
    0xD4: 0xFF94,
    0xD5: 0xFF95,
    0xD6: 0xFF96,
    0xD7: 0xFF97,
    0xD8: 0xFF98,
    0xD9: 0xFF99,
    0xDA: 0xFF9A,
    0xDB: 0xFF9B,
    0xDC: 0xFF9C,
    0xDD: 0xFF9D,
    0xDE: 0xFF9E,
    0xDF: 0xFF9F,
    0xE040: 0x6F3E,
    0xE041: 0x6F13,
    0xE042: 0x6EF7,
    0xE043: 0x6F86,
    0xE044: 0x6F7A,
    0xE045: 0x6F78,
    0xE046: 0x6F81,
    0xE047: 0x6F80,
    0xE048: 0x6F6F,
    0xE049: 0x6F5B,
    0xE04A: 0x6FF3,
    0xE04B: 0x6F6D,
    0xE04C: 0x6F82,
    0xE04D: 0x6F7C,
    0xE04E: 0x6F58,
    0xE04F: 0x6F8E,
    0xE050: 0x6F91,
    0xE051: 0x6FC2,
    0xE052: 0x6F66,
    0xE053: 0x6FB3,
    0xE054: 0x6FA3,
    0xE055: 0x6FA1,
    0xE056: 0x6FA4,
    0xE057: 0x6FB9,
    0xE058: 0x6FC6,
    0xE059: 0x6FAA,
    0xE05A: 0x6FDF,
    0xE05B: 0x6FD5,
    0xE05C: 0x6FEC,
    0xE05D: 0x6FD4,
    0xE05E: 0x6FD8,
    0xE05F: 0x6FF1,
    0xE060: 0x6FEE,
    0xE061: 0x6FDB,
    0xE062: 0x7009,
    0xE063: 0x700B,
    0xE064: 0x6FFA,
    0xE065: 0x7011,
    0xE066: 0x7001,
    0xE067: 0x700F,
    0xE068: 0x6FFE,
    0xE069: 0x701B,
    0xE06A: 0x701A,
    0xE06B: 0x6F74,
    0xE06C: 0x701D,
    0xE06D: 0x7018,
    0xE06E: 0x701F,
    0xE06F: 0x7030,
    0xE070: 0x703E,
    0xE071: 0x7032,
    0xE072: 0x7051,
    0xE073: 0x7063,
    0xE074: 0x7099,
    0xE075: 0x7092,
    0xE076: 0x70AF,
    0xE077: 0x70F1,
    0xE078: 0x70AC,
    0xE079: 0x70B8,
    0xE07A: 0x70B3,
    0xE07B: 0x70AE,
    0xE07C: 0x70DF,
    0xE07D: 0x70CB,
    0xE07E: 0x70DD,
    0xE080: 0x70D9,
    0xE081: 0x7109,
    0xE082: 0x70FD,
    0xE083: 0x711C,
    0xE084: 0x7119,
    0xE085: 0x7165,
    0xE086: 0x7155,
    0xE087: 0x7188,
    0xE088: 0x7166,
    0xE089: 0x7162,
    0xE08A: 0x714C,
    0xE08B: 0x7156,
    0xE08C: 0x716C,
    0xE08D: 0x718F,
    0xE08E: 0x71FB,
    0xE08F: 0x7184,
    0xE090: 0x7195,
    0xE091: 0x71A8,
    0xE092: 0x71AC,
    0xE093: 0x71D7,
    0xE094: 0x71B9,
    0xE095: 0x71BE,
    0xE096: 0x71D2,
    0xE097: 0x71C9,
    0xE098: 0x71D4,
    0xE099: 0x71CE,
    0xE09A: 0x71E0,
    0xE09B: 0x71EC,
    0xE09C: 0x71E7,
    0xE09D: 0x71F5,
    0xE09E: 0x71FC,
    0xE09F: 0x71F9,
    0xE0A0: 0x71FF,
    0xE0A1: 0x720D,
    0xE0A2: 0x7210,
    0xE0A3: 0x721B,
    0xE0A4: 0x7228,
    0xE0A5: 0x722D,
    0xE0A6: 0x722C,
    0xE0A7: 0x7230,
    0xE0A8: 0x7232,
    0xE0A9: 0x723B,
    0xE0AA: 0x723C,
    0xE0AB: 0x723F,
    0xE0AC: 0x7240,
    0xE0AD: 0x7246,
    0xE0AE: 0x724B,
    0xE0AF: 0x7258,
    0xE0B0: 0x7274,
    0xE0B1: 0x727E,
    0xE0B2: 0x7282,
    0xE0B3: 0x7281,
    0xE0B4: 0x7287,
    0xE0B5: 0x7292,
    0xE0B6: 0x7296,
    0xE0B7: 0x72A2,
    0xE0B8: 0x72A7,
    0xE0B9: 0x72B9,
    0xE0BA: 0x72B2,
    0xE0BB: 0x72C3,
    0xE0BC: 0x72C6,
    0xE0BD: 0x72C4,
    0xE0BE: 0x72CE,
    0xE0BF: 0x72D2,
    0xE0C0: 0x72E2,
    0xE0C1: 0x72E0,
    0xE0C2: 0x72E1,
    0xE0C3: 0x72F9,
    0xE0C4: 0x72F7,
    0xE0C5: 0x500F,
    0xE0C6: 0x7317,
    0xE0C7: 0x730A,
    0xE0C8: 0x731C,
    0xE0C9: 0x7316,
    0xE0CA: 0x731D,
    0xE0CB: 0x7334,
    0xE0CC: 0x732F,
    0xE0CD: 0x7329,
    0xE0CE: 0x7325,
    0xE0CF: 0x733E,
    0xE0D0: 0x734E,
    0xE0D1: 0x734F,
    0xE0D2: 0x9ED8,
    0xE0D3: 0x7357,
    0xE0D4: 0x736A,
    0xE0D5: 0x7368,
    0xE0D6: 0x7370,
    0xE0D7: 0x7378,
    0xE0D8: 0x7375,
    0xE0D9: 0x737B,
    0xE0DA: 0x737A,
    0xE0DB: 0x73C8,
    0xE0DC: 0x73B3,
    0xE0DD: 0x73CE,
    0xE0DE: 0x73BB,
    0xE0DF: 0x73C0,
    0xE0E0: 0x73E5,
    0xE0E1: 0x73EE,
    0xE0E2: 0x73DE,
    0xE0E3: 0x74A2,
    0xE0E4: 0x7405,
    0xE0E5: 0x746F,
    0xE0E6: 0x7425,
    0xE0E7: 0x73F8,
    0xE0E8: 0x7432,
    0xE0E9: 0x743A,
    0xE0EA: 0x7455,
    0xE0EB: 0x743F,
    0xE0EC: 0x745F,
    0xE0ED: 0x7459,
    0xE0EE: 0x7441,
    0xE0EF: 0x745C,
    0xE0F0: 0x7469,
    0xE0F1: 0x7470,
    0xE0F2: 0x7463,
    0xE0F3: 0x746A,
    0xE0F4: 0x7476,
    0xE0F5: 0x747E,
    0xE0F6: 0x748B,
    0xE0F7: 0x749E,
    0xE0F8: 0x74A7,
    0xE0F9: 0x74CA,
    0xE0FA: 0x74CF,
    0xE0FB: 0x74D4,
    0xE0FC: 0x73F1,
    0xE140: 0x74E0,
    0xE141: 0x74E3,
    0xE142: 0x74E7,
    0xE143: 0x74E9,
    0xE144: 0x74EE,
    0xE145: 0x74F2,
    0xE146: 0x74F0,
    0xE147: 0x74F1,
    0xE148: 0x74F8,
    0xE149: 0x74F7,
    0xE14A: 0x7504,
    0xE14B: 0x7503,
    0xE14C: 0x7505,
    0xE14D: 0x750C,
    0xE14E: 0x750E,
    0xE14F: 0x750D,
    0xE150: 0x7515,
    0xE151: 0x7513,
    0xE152: 0x751E,
    0xE153: 0x7526,
    0xE154: 0x752C,
    0xE155: 0x753C,
    0xE156: 0x7544,
    0xE157: 0x754D,
    0xE158: 0x754A,
    0xE159: 0x7549,
    0xE15A: 0x755B,
    0xE15B: 0x7546,
    0xE15C: 0x755A,
    0xE15D: 0x7569,
    0xE15E: 0x7564,
    0xE15F: 0x7567,
    0xE160: 0x756B,
    0xE161: 0x756D,
    0xE162: 0x7578,
    0xE163: 0x7576,
    0xE164: 0x7586,
    0xE165: 0x7587,
    0xE166: 0x7574,
    0xE167: 0x758A,
    0xE168: 0x7589,
    0xE169: 0x7582,
    0xE16A: 0x7594,
    0xE16B: 0x759A,
    0xE16C: 0x759D,
    0xE16D: 0x75A5,
    0xE16E: 0x75A3,
    0xE16F: 0x75C2,
    0xE170: 0x75B3,
    0xE171: 0x75C3,
    0xE172: 0x75B5,
    0xE173: 0x75BD,
    0xE174: 0x75B8,
    0xE175: 0x75BC,
    0xE176: 0x75B1,
    0xE177: 0x75CD,
    0xE178: 0x75CA,
    0xE179: 0x75D2,
    0xE17A: 0x75D9,
    0xE17B: 0x75E3,
    0xE17C: 0x75DE,
    0xE17D: 0x75FE,
    0xE17E: 0x75FF,
    0xE180: 0x75FC,
    0xE181: 0x7601,
    0xE182: 0x75F0,
    0xE183: 0x75FA,
    0xE184: 0x75F2,
    0xE185: 0x75F3,
    0xE186: 0x760B,
    0xE187: 0x760D,
    0xE188: 0x7609,
    0xE189: 0x761F,
    0xE18A: 0x7627,
    0xE18B: 0x7620,
    0xE18C: 0x7621,
    0xE18D: 0x7622,
    0xE18E: 0x7624,
    0xE18F: 0x7634,
    0xE190: 0x7630,
    0xE191: 0x763B,
    0xE192: 0x7647,
    0xE193: 0x7648,
    0xE194: 0x7646,
    0xE195: 0x765C,
    0xE196: 0x7658,
    0xE197: 0x7661,
    0xE198: 0x7662,
    0xE199: 0x7668,
    0xE19A: 0x7669,
    0xE19B: 0x766A,
    0xE19C: 0x7667,
    0xE19D: 0x766C,
    0xE19E: 0x7670,
    0xE19F: 0x7672,
    0xE1A0: 0x7676,
    0xE1A1: 0x7678,
    0xE1A2: 0x767C,
    0xE1A3: 0x7680,
    0xE1A4: 0x7683,
    0xE1A5: 0x7688,
    0xE1A6: 0x768B,
    0xE1A7: 0x768E,
    0xE1A8: 0x7696,
    0xE1A9: 0x7693,
    0xE1AA: 0x7699,
    0xE1AB: 0x769A,
    0xE1AC: 0x76B0,
    0xE1AD: 0x76B4,
    0xE1AE: 0x76B8,
    0xE1AF: 0x76B9,
    0xE1B0: 0x76BA,
    0xE1B1: 0x76C2,
    0xE1B2: 0x76CD,
    0xE1B3: 0x76D6,
    0xE1B4: 0x76D2,
    0xE1B5: 0x76DE,
    0xE1B6: 0x76E1,
    0xE1B7: 0x76E5,
    0xE1B8: 0x76E7,
    0xE1B9: 0x76EA,
    0xE1BA: 0x862F,
    0xE1BB: 0x76FB,
    0xE1BC: 0x7708,
    0xE1BD: 0x7707,
    0xE1BE: 0x7704,
    0xE1BF: 0x7729,
    0xE1C0: 0x7724,
    0xE1C1: 0x771E,
    0xE1C2: 0x7725,
    0xE1C3: 0x7726,
    0xE1C4: 0x771B,
    0xE1C5: 0x7737,
    0xE1C6: 0x7738,
    0xE1C7: 0x7747,
    0xE1C8: 0x775A,
    0xE1C9: 0x7768,
    0xE1CA: 0x776B,
    0xE1CB: 0x775B,
    0xE1CC: 0x7765,
    0xE1CD: 0x777F,
    0xE1CE: 0x777E,
    0xE1CF: 0x7779,
    0xE1D0: 0x778E,
    0xE1D1: 0x778B,
    0xE1D2: 0x7791,
    0xE1D3: 0x77A0,
    0xE1D4: 0x779E,
    0xE1D5: 0x77B0,
    0xE1D6: 0x77B6,
    0xE1D7: 0x77B9,
    0xE1D8: 0x77BF,
    0xE1D9: 0x77BC,
    0xE1DA: 0x77BD,
    0xE1DB: 0x77BB,
    0xE1DC: 0x77C7,
    0xE1DD: 0x77CD,
    0xE1DE: 0x77D7,
    0xE1DF: 0x77DA,
    0xE1E0: 0x77DC,
    0xE1E1: 0x77E3,
    0xE1E2: 0x77EE,
    0xE1E3: 0x77FC,
    0xE1E4: 0x780C,
    0xE1E5: 0x7812,
    0xE1E6: 0x7926,
    0xE1E7: 0x7820,
    0xE1E8: 0x792A,
    0xE1E9: 0x7845,
    0xE1EA: 0x788E,
    0xE1EB: 0x7874,
    0xE1EC: 0x7886,
    0xE1ED: 0x787C,
    0xE1EE: 0x789A,
    0xE1EF: 0x788C,
    0xE1F0: 0x78A3,
    0xE1F1: 0x78B5,
    0xE1F2: 0x78AA,
    0xE1F3: 0x78AF,
    0xE1F4: 0x78D1,
    0xE1F5: 0x78C6,
    0xE1F6: 0x78CB,
    0xE1F7: 0x78D4,
    0xE1F8: 0x78BE,
    0xE1F9: 0x78BC,
    0xE1FA: 0x78C5,
    0xE1FB: 0x78CA,
    0xE1FC: 0x78EC,
    0xE240: 0x78E7,
    0xE241: 0x78DA,
    0xE242: 0x78FD,
    0xE243: 0x78F4,
    0xE244: 0x7907,
    0xE245: 0x7912,
    0xE246: 0x7911,
    0xE247: 0x7919,
    0xE248: 0x792C,
    0xE249: 0x792B,
    0xE24A: 0x7940,
    0xE24B: 0x7960,
    0xE24C: 0x7957,
    0xE24D: 0x795F,
    0xE24E: 0x795A,
    0xE24F: 0x7955,
    0xE250: 0x7953,
    0xE251: 0x797A,
    0xE252: 0x797F,
    0xE253: 0x798A,
    0xE254: 0x799D,
    0xE255: 0x79A7,
    0xE256: 0x9F4B,
    0xE257: 0x79AA,
    0xE258: 0x79AE,
    0xE259: 0x79B3,
    0xE25A: 0x79B9,
    0xE25B: 0x79BA,
    0xE25C: 0x79C9,
    0xE25D: 0x79D5,
    0xE25E: 0x79E7,
    0xE25F: 0x79EC,
    0xE260: 0x79E1,
    0xE261: 0x79E3,
    0xE262: 0x7A08,
    0xE263: 0x7A0D,
    0xE264: 0x7A18,
    0xE265: 0x7A19,
    0xE266: 0x7A20,
    0xE267: 0x7A1F,
    0xE268: 0x7980,
    0xE269: 0x7A31,
    0xE26A: 0x7A3B,
    0xE26B: 0x7A3E,
    0xE26C: 0x7A37,
    0xE26D: 0x7A43,
    0xE26E: 0x7A57,
    0xE26F: 0x7A49,
    0xE270: 0x7A61,
    0xE271: 0x7A62,
    0xE272: 0x7A69,
    0xE273: 0x9F9D,
    0xE274: 0x7A70,
    0xE275: 0x7A79,
    0xE276: 0x7A7D,
    0xE277: 0x7A88,
    0xE278: 0x7A97,
    0xE279: 0x7A95,
    0xE27A: 0x7A98,
    0xE27B: 0x7A96,
    0xE27C: 0x7AA9,
    0xE27D: 0x7AC8,
    0xE27E: 0x7AB0,
    0xE280: 0x7AB6,
    0xE281: 0x7AC5,
    0xE282: 0x7AC4,
    0xE283: 0x7ABF,
    0xE284: 0x9083,
    0xE285: 0x7AC7,
    0xE286: 0x7ACA,
    0xE287: 0x7ACD,
    0xE288: 0x7ACF,
    0xE289: 0x7AD5,
    0xE28A: 0x7AD3,
    0xE28B: 0x7AD9,
    0xE28C: 0x7ADA,
    0xE28D: 0x7ADD,
    0xE28E: 0x7AE1,
    0xE28F: 0x7AE2,
    0xE290: 0x7AE6,
    0xE291: 0x7AED,
    0xE292: 0x7AF0,
    0xE293: 0x7B02,
    0xE294: 0x7B0F,
    0xE295: 0x7B0A,
    0xE296: 0x7B06,
    0xE297: 0x7B33,
    0xE298: 0x7B18,
    0xE299: 0x7B19,
    0xE29A: 0x7B1E,
    0xE29B: 0x7B35,
    0xE29C: 0x7B28,
    0xE29D: 0x7B36,
    0xE29E: 0x7B50,
    0xE29F: 0x7B7A,
    0xE2A0: 0x7B04,
    0xE2A1: 0x7B4D,
    0xE2A2: 0x7B0B,
    0xE2A3: 0x7B4C,
    0xE2A4: 0x7B45,
    0xE2A5: 0x7B75,
    0xE2A6: 0x7B65,
    0xE2A7: 0x7B74,
    0xE2A8: 0x7B67,
    0xE2A9: 0x7B70,
    0xE2AA: 0x7B71,
    0xE2AB: 0x7B6C,
    0xE2AC: 0x7B6E,
    0xE2AD: 0x7B9D,
    0xE2AE: 0x7B98,
    0xE2AF: 0x7B9F,
    0xE2B0: 0x7B8D,
    0xE2B1: 0x7B9C,
    0xE2B2: 0x7B9A,
    0xE2B3: 0x7B8B,
    0xE2B4: 0x7B92,
    0xE2B5: 0x7B8F,
    0xE2B6: 0x7B5D,
    0xE2B7: 0x7B99,
    0xE2B8: 0x7BCB,
    0xE2B9: 0x7BC1,
    0xE2BA: 0x7BCC,
    0xE2BB: 0x7BCF,
    0xE2BC: 0x7BB4,
    0xE2BD: 0x7BC6,
    0xE2BE: 0x7BDD,
    0xE2BF: 0x7BE9,
    0xE2C0: 0x7C11,
    0xE2C1: 0x7C14,
    0xE2C2: 0x7BE6,
    0xE2C3: 0x7BE5,
    0xE2C4: 0x7C60,
    0xE2C5: 0x7C00,
    0xE2C6: 0x7C07,
    0xE2C7: 0x7C13,
    0xE2C8: 0x7BF3,
    0xE2C9: 0x7BF7,
    0xE2CA: 0x7C17,
    0xE2CB: 0x7C0D,
    0xE2CC: 0x7BF6,
    0xE2CD: 0x7C23,
    0xE2CE: 0x7C27,
    0xE2CF: 0x7C2A,
    0xE2D0: 0x7C1F,
    0xE2D1: 0x7C37,
    0xE2D2: 0x7C2B,
    0xE2D3: 0x7C3D,
    0xE2D4: 0x7C4C,
    0xE2D5: 0x7C43,
    0xE2D6: 0x7C54,
    0xE2D7: 0x7C4F,
    0xE2D8: 0x7C40,
    0xE2D9: 0x7C50,
    0xE2DA: 0x7C58,
    0xE2DB: 0x7C5F,
    0xE2DC: 0x7C64,
    0xE2DD: 0x7C56,
    0xE2DE: 0x7C65,
    0xE2DF: 0x7C6C,
    0xE2E0: 0x7C75,
    0xE2E1: 0x7C83,
    0xE2E2: 0x7C90,
    0xE2E3: 0x7CA4,
    0xE2E4: 0x7CAD,
    0xE2E5: 0x7CA2,
    0xE2E6: 0x7CAB,
    0xE2E7: 0x7CA1,
    0xE2E8: 0x7CA8,
    0xE2E9: 0x7CB3,
    0xE2EA: 0x7CB2,
    0xE2EB: 0x7CB1,
    0xE2EC: 0x7CAE,
    0xE2ED: 0x7CB9,
    0xE2EE: 0x7CBD,
    0xE2EF: 0x7CC0,
    0xE2F0: 0x7CC5,
    0xE2F1: 0x7CC2,
    0xE2F2: 0x7CD8,
    0xE2F3: 0x7CD2,
    0xE2F4: 0x7CDC,
    0xE2F5: 0x7CE2,
    0xE2F6: 0x9B3B,
    0xE2F7: 0x7CEF,
    0xE2F8: 0x7CF2,
    0xE2F9: 0x7CF4,
    0xE2FA: 0x7CF6,
    0xE2FB: 0x7CFA,
    0xE2FC: 0x7D06,
    0xE340: 0x7D02,
    0xE341: 0x7D1C,
    0xE342: 0x7D15,
    0xE343: 0x7D0A,
    0xE344: 0x7D45,
    0xE345: 0x7D4B,
    0xE346: 0x7D2E,
    0xE347: 0x7D32,
    0xE348: 0x7D3F,
    0xE349: 0x7D35,
    0xE34A: 0x7D46,
    0xE34B: 0x7D73,
    0xE34C: 0x7D56,
    0xE34D: 0x7D4E,
    0xE34E: 0x7D72,
    0xE34F: 0x7D68,
    0xE350: 0x7D6E,
    0xE351: 0x7D4F,
    0xE352: 0x7D63,
    0xE353: 0x7D93,
    0xE354: 0x7D89,
    0xE355: 0x7D5B,
    0xE356: 0x7D8F,
    0xE357: 0x7D7D,
    0xE358: 0x7D9B,
    0xE359: 0x7DBA,
    0xE35A: 0x7DAE,
    0xE35B: 0x7DA3,
    0xE35C: 0x7DB5,
    0xE35D: 0x7DC7,
    0xE35E: 0x7DBD,
    0xE35F: 0x7DAB,
    0xE360: 0x7E3D,
    0xE361: 0x7DA2,
    0xE362: 0x7DAF,
    0xE363: 0x7DDC,
    0xE364: 0x7DB8,
    0xE365: 0x7D9F,
    0xE366: 0x7DB0,
    0xE367: 0x7DD8,
    0xE368: 0x7DDD,
    0xE369: 0x7DE4,
    0xE36A: 0x7DDE,
    0xE36B: 0x7DFB,
    0xE36C: 0x7DF2,
    0xE36D: 0x7DE1,
    0xE36E: 0x7E05,
    0xE36F: 0x7E0A,
    0xE370: 0x7E23,
    0xE371: 0x7E21,
    0xE372: 0x7E12,
    0xE373: 0x7E31,
    0xE374: 0x7E1F,
    0xE375: 0x7E09,
    0xE376: 0x7E0B,
    0xE377: 0x7E22,
    0xE378: 0x7E46,
    0xE379: 0x7E66,
    0xE37A: 0x7E3B,
    0xE37B: 0x7E35,
    0xE37C: 0x7E39,
    0xE37D: 0x7E43,
    0xE37E: 0x7E37,
    0xE380: 0x7E32,
    0xE381: 0x7E3A,
    0xE382: 0x7E67,
    0xE383: 0x7E5D,
    0xE384: 0x7E56,
    0xE385: 0x7E5E,
    0xE386: 0x7E59,
    0xE387: 0x7E5A,
    0xE388: 0x7E79,
    0xE389: 0x7E6A,
    0xE38A: 0x7E69,
    0xE38B: 0x7E7C,
    0xE38C: 0x7E7B,
    0xE38D: 0x7E83,
    0xE38E: 0x7DD5,
    0xE38F: 0x7E7D,
    0xE390: 0x8FAE,
    0xE391: 0x7E7F,
    0xE392: 0x7E88,
    0xE393: 0x7E89,
    0xE394: 0x7E8C,
    0xE395: 0x7E92,
    0xE396: 0x7E90,
    0xE397: 0x7E93,
    0xE398: 0x7E94,
    0xE399: 0x7E96,
    0xE39A: 0x7E8E,
    0xE39B: 0x7E9B,
    0xE39C: 0x7E9C,
    0xE39D: 0x7F38,
    0xE39E: 0x7F3A,
    0xE39F: 0x7F45,
    0xE3A0: 0x7F4C,
    0xE3A1: 0x7F4D,
    0xE3A2: 0x7F4E,
    0xE3A3: 0x7F50,
    0xE3A4: 0x7F51,
    0xE3A5: 0x7F55,
    0xE3A6: 0x7F54,
    0xE3A7: 0x7F58,
    0xE3A8: 0x7F5F,
    0xE3A9: 0x7F60,
    0xE3AA: 0x7F68,
    0xE3AB: 0x7F69,
    0xE3AC: 0x7F67,
    0xE3AD: 0x7F78,
    0xE3AE: 0x7F82,
    0xE3AF: 0x7F86,
    0xE3B0: 0x7F83,
    0xE3B1: 0x7F88,
    0xE3B2: 0x7F87,
    0xE3B3: 0x7F8C,
    0xE3B4: 0x7F94,
    0xE3B5: 0x7F9E,
    0xE3B6: 0x7F9D,
    0xE3B7: 0x7F9A,
    0xE3B8: 0x7FA3,
    0xE3B9: 0x7FAF,
    0xE3BA: 0x7FB2,
    0xE3BB: 0x7FB9,
    0xE3BC: 0x7FAE,
    0xE3BD: 0x7FB6,
    0xE3BE: 0x7FB8,
    0xE3BF: 0x8B71,
    0xE3C0: 0x7FC5,
    0xE3C1: 0x7FC6,
    0xE3C2: 0x7FCA,
    0xE3C3: 0x7FD5,
    0xE3C4: 0x7FD4,
    0xE3C5: 0x7FE1,
    0xE3C6: 0x7FE6,
    0xE3C7: 0x7FE9,
    0xE3C8: 0x7FF3,
    0xE3C9: 0x7FF9,
    0xE3CA: 0x98DC,
    0xE3CB: 0x8006,
    0xE3CC: 0x8004,
    0xE3CD: 0x800B,
    0xE3CE: 0x8012,
    0xE3CF: 0x8018,
    0xE3D0: 0x8019,
    0xE3D1: 0x801C,
    0xE3D2: 0x8021,
    0xE3D3: 0x8028,
    0xE3D4: 0x803F,
    0xE3D5: 0x803B,
    0xE3D6: 0x804A,
    0xE3D7: 0x8046,
    0xE3D8: 0x8052,
    0xE3D9: 0x8058,
    0xE3DA: 0x805A,
    0xE3DB: 0x805F,
    0xE3DC: 0x8062,
    0xE3DD: 0x8068,
    0xE3DE: 0x8073,
    0xE3DF: 0x8072,
    0xE3E0: 0x8070,
    0xE3E1: 0x8076,
    0xE3E2: 0x8079,
    0xE3E3: 0x807D,
    0xE3E4: 0x807F,
    0xE3E5: 0x8084,
    0xE3E6: 0x8086,
    0xE3E7: 0x8085,
    0xE3E8: 0x809B,
    0xE3E9: 0x8093,
    0xE3EA: 0x809A,
    0xE3EB: 0x80AD,
    0xE3EC: 0x5190,
    0xE3ED: 0x80AC,
    0xE3EE: 0x80DB,
    0xE3EF: 0x80E5,
    0xE3F0: 0x80D9,
    0xE3F1: 0x80DD,
    0xE3F2: 0x80C4,
    0xE3F3: 0x80DA,
    0xE3F4: 0x80D6,
    0xE3F5: 0x8109,
    0xE3F6: 0x80EF,
    0xE3F7: 0x80F1,
    0xE3F8: 0x811B,
    0xE3F9: 0x8129,
    0xE3FA: 0x8123,
    0xE3FB: 0x812F,
    0xE3FC: 0x814B,
    0xE440: 0x968B,
    0xE441: 0x8146,
    0xE442: 0x813E,
    0xE443: 0x8153,
    0xE444: 0x8151,
    0xE445: 0x80FC,
    0xE446: 0x8171,
    0xE447: 0x816E,
    0xE448: 0x8165,
    0xE449: 0x8166,
    0xE44A: 0x8174,
    0xE44B: 0x8183,
    0xE44C: 0x8188,
    0xE44D: 0x818A,
    0xE44E: 0x8180,
    0xE44F: 0x8182,
    0xE450: 0x81A0,
    0xE451: 0x8195,
    0xE452: 0x81A4,
    0xE453: 0x81A3,
    0xE454: 0x815F,
    0xE455: 0x8193,
    0xE456: 0x81A9,
    0xE457: 0x81B0,
    0xE458: 0x81B5,
    0xE459: 0x81BE,
    0xE45A: 0x81B8,
    0xE45B: 0x81BD,
    0xE45C: 0x81C0,
    0xE45D: 0x81C2,
    0xE45E: 0x81BA,
    0xE45F: 0x81C9,
    0xE460: 0x81CD,
    0xE461: 0x81D1,
    0xE462: 0x81D9,
    0xE463: 0x81D8,
    0xE464: 0x81C8,
    0xE465: 0x81DA,
    0xE466: 0x81DF,
    0xE467: 0x81E0,
    0xE468: 0x81E7,
    0xE469: 0x81FA,
    0xE46A: 0x81FB,
    0xE46B: 0x81FE,
    0xE46C: 0x8201,
    0xE46D: 0x8202,
    0xE46E: 0x8205,
    0xE46F: 0x8207,
    0xE470: 0x820A,
    0xE471: 0x820D,
    0xE472: 0x8210,
    0xE473: 0x8216,
    0xE474: 0x8229,
    0xE475: 0x822B,
    0xE476: 0x8238,
    0xE477: 0x8233,
    0xE478: 0x8240,
    0xE479: 0x8259,
    0xE47A: 0x8258,
    0xE47B: 0x825D,
    0xE47C: 0x825A,
    0xE47D: 0x825F,
    0xE47E: 0x8264,
    0xE480: 0x8262,
    0xE481: 0x8268,
    0xE482: 0x826A,
    0xE483: 0x826B,
    0xE484: 0x822E,
    0xE485: 0x8271,
    0xE486: 0x8277,
    0xE487: 0x8278,
    0xE488: 0x827E,
    0xE489: 0x828D,
    0xE48A: 0x8292,
    0xE48B: 0x82AB,
    0xE48C: 0x829F,
    0xE48D: 0x82BB,
    0xE48E: 0x82AC,
    0xE48F: 0x82E1,
    0xE490: 0x82E3,
    0xE491: 0x82DF,
    0xE492: 0x82D2,
    0xE493: 0x82F4,
    0xE494: 0x82F3,
    0xE495: 0x82FA,
    0xE496: 0x8393,
    0xE497: 0x8303,
    0xE498: 0x82FB,
    0xE499: 0x82F9,
    0xE49A: 0x82DE,
    0xE49B: 0x8306,
    0xE49C: 0x82DC,
    0xE49D: 0x8309,
    0xE49E: 0x82D9,
    0xE49F: 0x8335,
    0xE4A0: 0x8334,
    0xE4A1: 0x8316,
    0xE4A2: 0x8332,
    0xE4A3: 0x8331,
    0xE4A4: 0x8340,
    0xE4A5: 0x8339,
    0xE4A6: 0x8350,
    0xE4A7: 0x8345,
    0xE4A8: 0x832F,
    0xE4A9: 0x832B,
    0xE4AA: 0x8317,
    0xE4AB: 0x8318,
    0xE4AC: 0x8385,
    0xE4AD: 0x839A,
    0xE4AE: 0x83AA,
    0xE4AF: 0x839F,
    0xE4B0: 0x83A2,
    0xE4B1: 0x8396,
    0xE4B2: 0x8323,
    0xE4B3: 0x838E,
    0xE4B4: 0x8387,
    0xE4B5: 0x838A,
    0xE4B6: 0x837C,
    0xE4B7: 0x83B5,
    0xE4B8: 0x8373,
    0xE4B9: 0x8375,
    0xE4BA: 0x83A0,
    0xE4BB: 0x8389,
    0xE4BC: 0x83A8,
    0xE4BD: 0x83F4,
    0xE4BE: 0x8413,
    0xE4BF: 0x83EB,
    0xE4C0: 0x83CE,
    0xE4C1: 0x83FD,
    0xE4C2: 0x8403,
    0xE4C3: 0x83D8,
    0xE4C4: 0x840B,
    0xE4C5: 0x83C1,
    0xE4C6: 0x83F7,
    0xE4C7: 0x8407,
    0xE4C8: 0x83E0,
    0xE4C9: 0x83F2,
    0xE4CA: 0x840D,
    0xE4CB: 0x8422,
    0xE4CC: 0x8420,
    0xE4CD: 0x83BD,
    0xE4CE: 0x8438,
    0xE4CF: 0x8506,
    0xE4D0: 0x83FB,
    0xE4D1: 0x846D,
    0xE4D2: 0x842A,
    0xE4D3: 0x843C,
    0xE4D4: 0x855A,
    0xE4D5: 0x8484,
    0xE4D6: 0x8477,
    0xE4D7: 0x846B,
    0xE4D8: 0x84AD,
    0xE4D9: 0x846E,
    0xE4DA: 0x8482,
    0xE4DB: 0x8469,
    0xE4DC: 0x8446,
    0xE4DD: 0x842C,
    0xE4DE: 0x846F,
    0xE4DF: 0x8479,
    0xE4E0: 0x8435,
    0xE4E1: 0x84CA,
    0xE4E2: 0x8462,
    0xE4E3: 0x84B9,
    0xE4E4: 0x84BF,
    0xE4E5: 0x849F,
    0xE4E6: 0x84D9,
    0xE4E7: 0x84CD,
    0xE4E8: 0x84BB,
    0xE4E9: 0x84DA,
    0xE4EA: 0x84D0,
    0xE4EB: 0x84C1,
    0xE4EC: 0x84C6,
    0xE4ED: 0x84D6,
    0xE4EE: 0x84A1,
    0xE4EF: 0x8521,
    0xE4F0: 0x84FF,
    0xE4F1: 0x84F4,
    0xE4F2: 0x8517,
    0xE4F3: 0x8518,
    0xE4F4: 0x852C,
    0xE4F5: 0x851F,
    0xE4F6: 0x8515,
    0xE4F7: 0x8514,
    0xE4F8: 0x84FC,
    0xE4F9: 0x8540,
    0xE4FA: 0x8563,
    0xE4FB: 0x8558,
    0xE4FC: 0x8548,
    0xE540: 0x8541,
    0xE541: 0x8602,
    0xE542: 0x854B,
    0xE543: 0x8555,
    0xE544: 0x8580,
    0xE545: 0x85A4,
    0xE546: 0x8588,
    0xE547: 0x8591,
    0xE548: 0x858A,
    0xE549: 0x85A8,
    0xE54A: 0x856D,
    0xE54B: 0x8594,
    0xE54C: 0x859B,
    0xE54D: 0x85EA,
    0xE54E: 0x8587,
    0xE54F: 0x859C,
    0xE550: 0x8577,
    0xE551: 0x857E,
    0xE552: 0x8590,
    0xE553: 0x85C9,
    0xE554: 0x85BA,
    0xE555: 0x85CF,
    0xE556: 0x85B9,
    0xE557: 0x85D0,
    0xE558: 0x85D5,
    0xE559: 0x85DD,
    0xE55A: 0x85E5,
    0xE55B: 0x85DC,
    0xE55C: 0x85F9,
    0xE55D: 0x860A,
    0xE55E: 0x8613,
    0xE55F: 0x860B,
    0xE560: 0x85FE,
    0xE561: 0x85FA,
    0xE562: 0x8606,
    0xE563: 0x8622,
    0xE564: 0x861A,
    0xE565: 0x8630,
    0xE566: 0x863F,
    0xE567: 0x864D,
    0xE568: 0x4E55,
    0xE569: 0x8654,
    0xE56A: 0x865F,
    0xE56B: 0x8667,
    0xE56C: 0x8671,
    0xE56D: 0x8693,
    0xE56E: 0x86A3,
    0xE56F: 0x86A9,
    0xE570: 0x86AA,
    0xE571: 0x868B,
    0xE572: 0x868C,
    0xE573: 0x86B6,
    0xE574: 0x86AF,
    0xE575: 0x86C4,
    0xE576: 0x86C6,
    0xE577: 0x86B0,
    0xE578: 0x86C9,
    0xE579: 0x8823,
    0xE57A: 0x86AB,
    0xE57B: 0x86D4,
    0xE57C: 0x86DE,
    0xE57D: 0x86E9,
    0xE57E: 0x86EC,
    0xE580: 0x86DF,
    0xE581: 0x86DB,
    0xE582: 0x86EF,
    0xE583: 0x8712,
    0xE584: 0x8706,
    0xE585: 0x8708,
    0xE586: 0x8700,
    0xE587: 0x8703,
    0xE588: 0x86FB,
    0xE589: 0x8711,
    0xE58A: 0x8709,
    0xE58B: 0x870D,
    0xE58C: 0x86F9,
    0xE58D: 0x870A,
    0xE58E: 0x8734,
    0xE58F: 0x873F,
    0xE590: 0x8737,
    0xE591: 0x873B,
    0xE592: 0x8725,
    0xE593: 0x8729,
    0xE594: 0x871A,
    0xE595: 0x8760,
    0xE596: 0x875F,
    0xE597: 0x8778,
    0xE598: 0x874C,
    0xE599: 0x874E,
    0xE59A: 0x8774,
    0xE59B: 0x8757,
    0xE59C: 0x8768,
    0xE59D: 0x876E,
    0xE59E: 0x8759,
    0xE59F: 0x8753,
    0xE5A0: 0x8763,
    0xE5A1: 0x876A,
    0xE5A2: 0x8805,
    0xE5A3: 0x87A2,
    0xE5A4: 0x879F,
    0xE5A5: 0x8782,
    0xE5A6: 0x87AF,
    0xE5A7: 0x87CB,
    0xE5A8: 0x87BD,
    0xE5A9: 0x87C0,
    0xE5AA: 0x87D0,
    0xE5AB: 0x96D6,
    0xE5AC: 0x87AB,
    0xE5AD: 0x87C4,
    0xE5AE: 0x87B3,
    0xE5AF: 0x87C7,
    0xE5B0: 0x87C6,
    0xE5B1: 0x87BB,
    0xE5B2: 0x87EF,
    0xE5B3: 0x87F2,
    0xE5B4: 0x87E0,
    0xE5B5: 0x880F,
    0xE5B6: 0x880D,
    0xE5B7: 0x87FE,
    0xE5B8: 0x87F6,
    0xE5B9: 0x87F7,
    0xE5BA: 0x880E,
    0xE5BB: 0x87D2,
    0xE5BC: 0x8811,
    0xE5BD: 0x8816,
    0xE5BE: 0x8815,
    0xE5BF: 0x8822,
    0xE5C0: 0x8821,
    0xE5C1: 0x8831,
    0xE5C2: 0x8836,
    0xE5C3: 0x8839,
    0xE5C4: 0x8827,
    0xE5C5: 0x883B,
    0xE5C6: 0x8844,
    0xE5C7: 0x8842,
    0xE5C8: 0x8852,
    0xE5C9: 0x8859,
    0xE5CA: 0x885E,
    0xE5CB: 0x8862,
    0xE5CC: 0x886B,
    0xE5CD: 0x8881,
    0xE5CE: 0x887E,
    0xE5CF: 0x889E,
    0xE5D0: 0x8875,
    0xE5D1: 0x887D,
    0xE5D2: 0x88B5,
    0xE5D3: 0x8872,
    0xE5D4: 0x8882,
    0xE5D5: 0x8897,
    0xE5D6: 0x8892,
    0xE5D7: 0x88AE,
    0xE5D8: 0x8899,
    0xE5D9: 0x88A2,
    0xE5DA: 0x888D,
    0xE5DB: 0x88A4,
    0xE5DC: 0x88B0,
    0xE5DD: 0x88BF,
    0xE5DE: 0x88B1,
    0xE5DF: 0x88C3,
    0xE5E0: 0x88C4,
    0xE5E1: 0x88D4,
    0xE5E2: 0x88D8,
    0xE5E3: 0x88D9,
    0xE5E4: 0x88DD,
    0xE5E5: 0x88F9,
    0xE5E6: 0x8902,
    0xE5E7: 0x88FC,
    0xE5E8: 0x88F4,
    0xE5E9: 0x88E8,
    0xE5EA: 0x88F2,
    0xE5EB: 0x8904,
    0xE5EC: 0x890C,
    0xE5ED: 0x890A,
    0xE5EE: 0x8913,
    0xE5EF: 0x8943,
    0xE5F0: 0x891E,
    0xE5F1: 0x8925,
    0xE5F2: 0x892A,
    0xE5F3: 0x892B,
    0xE5F4: 0x8941,
    0xE5F5: 0x8944,
    0xE5F6: 0x893B,
    0xE5F7: 0x8936,
    0xE5F8: 0x8938,
    0xE5F9: 0x894C,
    0xE5FA: 0x891D,
    0xE5FB: 0x8960,
    0xE5FC: 0x895E,
    0xE640: 0x8966,
    0xE641: 0x8964,
    0xE642: 0x896D,
    0xE643: 0x896A,
    0xE644: 0x896F,
    0xE645: 0x8974,
    0xE646: 0x8977,
    0xE647: 0x897E,
    0xE648: 0x8983,
    0xE649: 0x8988,
    0xE64A: 0x898A,
    0xE64B: 0x8993,
    0xE64C: 0x8998,
    0xE64D: 0x89A1,
    0xE64E: 0x89A9,
    0xE64F: 0x89A6,
    0xE650: 0x89AC,
    0xE651: 0x89AF,
    0xE652: 0x89B2,
    0xE653: 0x89BA,
    0xE654: 0x89BD,
    0xE655: 0x89BF,
    0xE656: 0x89C0,
    0xE657: 0x89DA,
    0xE658: 0x89DC,
    0xE659: 0x89DD,
    0xE65A: 0x89E7,
    0xE65B: 0x89F4,
    0xE65C: 0x89F8,
    0xE65D: 0x8A03,
    0xE65E: 0x8A16,
    0xE65F: 0x8A10,
    0xE660: 0x8A0C,
    0xE661: 0x8A1B,
    0xE662: 0x8A1D,
    0xE663: 0x8A25,
    0xE664: 0x8A36,
    0xE665: 0x8A41,
    0xE666: 0x8A5B,
    0xE667: 0x8A52,
    0xE668: 0x8A46,
    0xE669: 0x8A48,
    0xE66A: 0x8A7C,
    0xE66B: 0x8A6D,
    0xE66C: 0x8A6C,
    0xE66D: 0x8A62,
    0xE66E: 0x8A85,
    0xE66F: 0x8A82,
    0xE670: 0x8A84,
    0xE671: 0x8AA8,
    0xE672: 0x8AA1,
    0xE673: 0x8A91,
    0xE674: 0x8AA5,
    0xE675: 0x8AA6,
    0xE676: 0x8A9A,
    0xE677: 0x8AA3,
    0xE678: 0x8AC4,
    0xE679: 0x8ACD,
    0xE67A: 0x8AC2,
    0xE67B: 0x8ADA,
    0xE67C: 0x8AEB,
    0xE67D: 0x8AF3,
    0xE67E: 0x8AE7,
    0xE680: 0x8AE4,
    0xE681: 0x8AF1,
    0xE682: 0x8B14,
    0xE683: 0x8AE0,
    0xE684: 0x8AE2,
    0xE685: 0x8AF7,
    0xE686: 0x8ADE,
    0xE687: 0x8ADB,
    0xE688: 0x8B0C,
    0xE689: 0x8B07,
    0xE68A: 0x8B1A,
    0xE68B: 0x8AE1,
    0xE68C: 0x8B16,
    0xE68D: 0x8B10,
    0xE68E: 0x8B17,
    0xE68F: 0x8B20,
    0xE690: 0x8B33,
    0xE691: 0x97AB,
    0xE692: 0x8B26,
    0xE693: 0x8B2B,
    0xE694: 0x8B3E,
    0xE695: 0x8B28,
    0xE696: 0x8B41,
    0xE697: 0x8B4C,
    0xE698: 0x8B4F,
    0xE699: 0x8B4E,
    0xE69A: 0x8B49,
    0xE69B: 0x8B56,
    0xE69C: 0x8B5B,
    0xE69D: 0x8B5A,
    0xE69E: 0x8B6B,
    0xE69F: 0x8B5F,
    0xE6A0: 0x8B6C,
    0xE6A1: 0x8B6F,
    0xE6A2: 0x8B74,
    0xE6A3: 0x8B7D,
    0xE6A4: 0x8B80,
    0xE6A5: 0x8B8C,
    0xE6A6: 0x8B8E,
    0xE6A7: 0x8B92,
    0xE6A8: 0x8B93,
    0xE6A9: 0x8B96,
    0xE6AA: 0x8B99,
    0xE6AB: 0x8B9A,
    0xE6AC: 0x8C3A,
    0xE6AD: 0x8C41,
    0xE6AE: 0x8C3F,
    0xE6AF: 0x8C48,
    0xE6B0: 0x8C4C,
    0xE6B1: 0x8C4E,
    0xE6B2: 0x8C50,
    0xE6B3: 0x8C55,
    0xE6B4: 0x8C62,
    0xE6B5: 0x8C6C,
    0xE6B6: 0x8C78,
    0xE6B7: 0x8C7A,
    0xE6B8: 0x8C82,
    0xE6B9: 0x8C89,
    0xE6BA: 0x8C85,
    0xE6BB: 0x8C8A,
    0xE6BC: 0x8C8D,
    0xE6BD: 0x8C8E,
    0xE6BE: 0x8C94,
    0xE6BF: 0x8C7C,
    0xE6C0: 0x8C98,
    0xE6C1: 0x621D,
    0xE6C2: 0x8CAD,
    0xE6C3: 0x8CAA,
    0xE6C4: 0x8CBD,
    0xE6C5: 0x8CB2,
    0xE6C6: 0x8CB3,
    0xE6C7: 0x8CAE,
    0xE6C8: 0x8CB6,
    0xE6C9: 0x8CC8,
    0xE6CA: 0x8CC1,
    0xE6CB: 0x8CE4,
    0xE6CC: 0x8CE3,
    0xE6CD: 0x8CDA,
    0xE6CE: 0x8CFD,
    0xE6CF: 0x8CFA,
    0xE6D0: 0x8CFB,
    0xE6D1: 0x8D04,
    0xE6D2: 0x8D05,
    0xE6D3: 0x8D0A,
    0xE6D4: 0x8D07,
    0xE6D5: 0x8D0F,
    0xE6D6: 0x8D0D,
    0xE6D7: 0x8D10,
    0xE6D8: 0x9F4E,
    0xE6D9: 0x8D13,
    0xE6DA: 0x8CCD,
    0xE6DB: 0x8D14,
    0xE6DC: 0x8D16,
    0xE6DD: 0x8D67,
    0xE6DE: 0x8D6D,
    0xE6DF: 0x8D71,
    0xE6E0: 0x8D73,
    0xE6E1: 0x8D81,
    0xE6E2: 0x8D99,
    0xE6E3: 0x8DC2,
    0xE6E4: 0x8DBE,
    0xE6E5: 0x8DBA,
    0xE6E6: 0x8DCF,
    0xE6E7: 0x8DDA,
    0xE6E8: 0x8DD6,
    0xE6E9: 0x8DCC,
    0xE6EA: 0x8DDB,
    0xE6EB: 0x8DCB,
    0xE6EC: 0x8DEA,
    0xE6ED: 0x8DEB,
    0xE6EE: 0x8DDF,
    0xE6EF: 0x8DE3,
    0xE6F0: 0x8DFC,
    0xE6F1: 0x8E08,
    0xE6F2: 0x8E09,
    0xE6F3: 0x8DFF,
    0xE6F4: 0x8E1D,
    0xE6F5: 0x8E1E,
    0xE6F6: 0x8E10,
    0xE6F7: 0x8E1F,
    0xE6F8: 0x8E42,
    0xE6F9: 0x8E35,
    0xE6FA: 0x8E30,
    0xE6FB: 0x8E34,
    0xE6FC: 0x8E4A,
    0xE740: 0x8E47,
    0xE741: 0x8E49,
    0xE742: 0x8E4C,
    0xE743: 0x8E50,
    0xE744: 0x8E48,
    0xE745: 0x8E59,
    0xE746: 0x8E64,
    0xE747: 0x8E60,
    0xE748: 0x8E2A,
    0xE749: 0x8E63,
    0xE74A: 0x8E55,
    0xE74B: 0x8E76,
    0xE74C: 0x8E72,
    0xE74D: 0x8E7C,
    0xE74E: 0x8E81,
    0xE74F: 0x8E87,
    0xE750: 0x8E85,
    0xE751: 0x8E84,
    0xE752: 0x8E8B,
    0xE753: 0x8E8A,
    0xE754: 0x8E93,
    0xE755: 0x8E91,
    0xE756: 0x8E94,
    0xE757: 0x8E99,
    0xE758: 0x8EAA,
    0xE759: 0x8EA1,
    0xE75A: 0x8EAC,
    0xE75B: 0x8EB0,
    0xE75C: 0x8EC6,
    0xE75D: 0x8EB1,
    0xE75E: 0x8EBE,
    0xE75F: 0x8EC5,
    0xE760: 0x8EC8,
    0xE761: 0x8ECB,
    0xE762: 0x8EDB,
    0xE763: 0x8EE3,
    0xE764: 0x8EFC,
    0xE765: 0x8EFB,
    0xE766: 0x8EEB,
    0xE767: 0x8EFE,
    0xE768: 0x8F0A,
    0xE769: 0x8F05,
    0xE76A: 0x8F15,
    0xE76B: 0x8F12,
    0xE76C: 0x8F19,
    0xE76D: 0x8F13,
    0xE76E: 0x8F1C,
    0xE76F: 0x8F1F,
    0xE770: 0x8F1B,
    0xE771: 0x8F0C,
    0xE772: 0x8F26,
    0xE773: 0x8F33,
    0xE774: 0x8F3B,
    0xE775: 0x8F39,
    0xE776: 0x8F45,
    0xE777: 0x8F42,
    0xE778: 0x8F3E,
    0xE779: 0x8F4C,
    0xE77A: 0x8F49,
    0xE77B: 0x8F46,
    0xE77C: 0x8F4E,
    0xE77D: 0x8F57,
    0xE77E: 0x8F5C,
    0xE780: 0x8F62,
    0xE781: 0x8F63,
    0xE782: 0x8F64,
    0xE783: 0x8F9C,
    0xE784: 0x8F9F,
    0xE785: 0x8FA3,
    0xE786: 0x8FAD,
    0xE787: 0x8FAF,
    0xE788: 0x8FB7,
    0xE789: 0x8FDA,
    0xE78A: 0x8FE5,
    0xE78B: 0x8FE2,
    0xE78C: 0x8FEA,
    0xE78D: 0x8FEF,
    0xE78E: 0x9087,
    0xE78F: 0x8FF4,
    0xE790: 0x9005,
    0xE791: 0x8FF9,
    0xE792: 0x8FFA,
    0xE793: 0x9011,
    0xE794: 0x9015,
    0xE795: 0x9021,
    0xE796: 0x900D,
    0xE797: 0x901E,
    0xE798: 0x9016,
    0xE799: 0x900B,
    0xE79A: 0x9027,
    0xE79B: 0x9036,
    0xE79C: 0x9035,
    0xE79D: 0x9039,
    0xE79E: 0x8FF8,
    0xE79F: 0x904F,
    0xE7A0: 0x9050,
    0xE7A1: 0x9051,
    0xE7A2: 0x9052,
    0xE7A3: 0x900E,
    0xE7A4: 0x9049,
    0xE7A5: 0x903E,
    0xE7A6: 0x9056,
    0xE7A7: 0x9058,
    0xE7A8: 0x905E,
    0xE7A9: 0x9068,
    0xE7AA: 0x906F,
    0xE7AB: 0x9076,
    0xE7AC: 0x96A8,
    0xE7AD: 0x9072,
    0xE7AE: 0x9082,
    0xE7AF: 0x907D,
    0xE7B0: 0x9081,
    0xE7B1: 0x9080,
    0xE7B2: 0x908A,
    0xE7B3: 0x9089,
    0xE7B4: 0x908F,
    0xE7B5: 0x90A8,
    0xE7B6: 0x90AF,
    0xE7B7: 0x90B1,
    0xE7B8: 0x90B5,
    0xE7B9: 0x90E2,
    0xE7BA: 0x90E4,
    0xE7BB: 0x6248,
    0xE7BC: 0x90DB,
    0xE7BD: 0x9102,
    0xE7BE: 0x9112,
    0xE7BF: 0x9119,
    0xE7C0: 0x9132,
    0xE7C1: 0x9130,
    0xE7C2: 0x914A,
    0xE7C3: 0x9156,
    0xE7C4: 0x9158,
    0xE7C5: 0x9163,
    0xE7C6: 0x9165,
    0xE7C7: 0x9169,
    0xE7C8: 0x9173,
    0xE7C9: 0x9172,
    0xE7CA: 0x918B,
    0xE7CB: 0x9189,
    0xE7CC: 0x9182,
    0xE7CD: 0x91A2,
    0xE7CE: 0x91AB,
    0xE7CF: 0x91AF,
    0xE7D0: 0x91AA,
    0xE7D1: 0x91B5,
    0xE7D2: 0x91B4,
    0xE7D3: 0x91BA,
    0xE7D4: 0x91C0,
    0xE7D5: 0x91C1,
    0xE7D6: 0x91C9,
    0xE7D7: 0x91CB,
    0xE7D8: 0x91D0,
    0xE7D9: 0x91D6,
    0xE7DA: 0x91DF,
    0xE7DB: 0x91E1,
    0xE7DC: 0x91DB,
    0xE7DD: 0x91FC,
    0xE7DE: 0x91F5,
    0xE7DF: 0x91F6,
    0xE7E0: 0x921E,
    0xE7E1: 0x91FF,
    0xE7E2: 0x9214,
    0xE7E3: 0x922C,
    0xE7E4: 0x9215,
    0xE7E5: 0x9211,
    0xE7E6: 0x925E,
    0xE7E7: 0x9257,
    0xE7E8: 0x9245,
    0xE7E9: 0x9249,
    0xE7EA: 0x9264,
    0xE7EB: 0x9248,
    0xE7EC: 0x9295,
    0xE7ED: 0x923F,
    0xE7EE: 0x924B,
    0xE7EF: 0x9250,
    0xE7F0: 0x929C,
    0xE7F1: 0x9296,
    0xE7F2: 0x9293,
    0xE7F3: 0x929B,
    0xE7F4: 0x925A,
    0xE7F5: 0x92CF,
    0xE7F6: 0x92B9,
    0xE7F7: 0x92B7,
    0xE7F8: 0x92E9,
    0xE7F9: 0x930F,
    0xE7FA: 0x92FA,
    0xE7FB: 0x9344,
    0xE7FC: 0x932E,
    0xE840: 0x9319,
    0xE841: 0x9322,
    0xE842: 0x931A,
    0xE843: 0x9323,
    0xE844: 0x933A,
    0xE845: 0x9335,
    0xE846: 0x933B,
    0xE847: 0x935C,
    0xE848: 0x9360,
    0xE849: 0x937C,
    0xE84A: 0x936E,
    0xE84B: 0x9356,
    0xE84C: 0x93B0,
    0xE84D: 0x93AC,
    0xE84E: 0x93AD,
    0xE84F: 0x9394,
    0xE850: 0x93B9,
    0xE851: 0x93D6,
    0xE852: 0x93D7,
    0xE853: 0x93E8,
    0xE854: 0x93E5,
    0xE855: 0x93D8,
    0xE856: 0x93C3,
    0xE857: 0x93DD,
    0xE858: 0x93D0,
    0xE859: 0x93C8,
    0xE85A: 0x93E4,
    0xE85B: 0x941A,
    0xE85C: 0x9414,
    0xE85D: 0x9413,
    0xE85E: 0x9403,
    0xE85F: 0x9407,
    0xE860: 0x9410,
    0xE861: 0x9436,
    0xE862: 0x942B,
    0xE863: 0x9435,
    0xE864: 0x9421,
    0xE865: 0x943A,
    0xE866: 0x9441,
    0xE867: 0x9452,
    0xE868: 0x9444,
    0xE869: 0x945B,
    0xE86A: 0x9460,
    0xE86B: 0x9462,
    0xE86C: 0x945E,
    0xE86D: 0x946A,
    0xE86E: 0x9229,
    0xE86F: 0x9470,
    0xE870: 0x9475,
    0xE871: 0x9477,
    0xE872: 0x947D,
    0xE873: 0x945A,
    0xE874: 0x947C,
    0xE875: 0x947E,
    0xE876: 0x9481,
    0xE877: 0x947F,
    0xE878: 0x9582,
    0xE879: 0x9587,
    0xE87A: 0x958A,
    0xE87B: 0x9594,
    0xE87C: 0x9596,
    0xE87D: 0x9598,
    0xE87E: 0x9599,
    0xE880: 0x95A0,
    0xE881: 0x95A8,
    0xE882: 0x95A7,
    0xE883: 0x95AD,
    0xE884: 0x95BC,
    0xE885: 0x95BB,
    0xE886: 0x95B9,
    0xE887: 0x95BE,
    0xE888: 0x95CA,
    0xE889: 0x6FF6,
    0xE88A: 0x95C3,
    0xE88B: 0x95CD,
    0xE88C: 0x95CC,
    0xE88D: 0x95D5,
    0xE88E: 0x95D4,
    0xE88F: 0x95D6,
    0xE890: 0x95DC,
    0xE891: 0x95E1,
    0xE892: 0x95E5,
    0xE893: 0x95E2,
    0xE894: 0x9621,
    0xE895: 0x9628,
    0xE896: 0x962E,
    0xE897: 0x962F,
    0xE898: 0x9642,
    0xE899: 0x964C,
    0xE89A: 0x964F,
    0xE89B: 0x964B,
    0xE89C: 0x9677,
    0xE89D: 0x965C,
    0xE89E: 0x965E,
    0xE89F: 0x965D,
    0xE8A0: 0x965F,
    0xE8A1: 0x9666,
    0xE8A2: 0x9672,
    0xE8A3: 0x966C,
    0xE8A4: 0x968D,
    0xE8A5: 0x9698,
    0xE8A6: 0x9695,
    0xE8A7: 0x9697,
    0xE8A8: 0x96AA,
    0xE8A9: 0x96A7,
    0xE8AA: 0x96B1,
    0xE8AB: 0x96B2,
    0xE8AC: 0x96B0,
    0xE8AD: 0x96B4,
    0xE8AE: 0x96B6,
    0xE8AF: 0x96B8,
    0xE8B0: 0x96B9,
    0xE8B1: 0x96CE,
    0xE8B2: 0x96CB,
    0xE8B3: 0x96C9,
    0xE8B4: 0x96CD,
    0xE8B5: 0x894D,
    0xE8B6: 0x96DC,
    0xE8B7: 0x970D,
    0xE8B8: 0x96D5,
    0xE8B9: 0x96F9,
    0xE8BA: 0x9704,
    0xE8BB: 0x9706,
    0xE8BC: 0x9708,
    0xE8BD: 0x9713,
    0xE8BE: 0x970E,
    0xE8BF: 0x9711,
    0xE8C0: 0x970F,
    0xE8C1: 0x9716,
    0xE8C2: 0x9719,
    0xE8C3: 0x9724,
    0xE8C4: 0x972A,
    0xE8C5: 0x9730,
    0xE8C6: 0x9739,
    0xE8C7: 0x973D,
    0xE8C8: 0x973E,
    0xE8C9: 0x9744,
    0xE8CA: 0x9746,
    0xE8CB: 0x9748,
    0xE8CC: 0x9742,
    0xE8CD: 0x9749,
    0xE8CE: 0x975C,
    0xE8CF: 0x9760,
    0xE8D0: 0x9764,
    0xE8D1: 0x9766,
    0xE8D2: 0x9768,
    0xE8D3: 0x52D2,
    0xE8D4: 0x976B,
    0xE8D5: 0x9771,
    0xE8D6: 0x9779,
    0xE8D7: 0x9785,
    0xE8D8: 0x977C,
    0xE8D9: 0x9781,
    0xE8DA: 0x977A,
    0xE8DB: 0x9786,
    0xE8DC: 0x978B,
    0xE8DD: 0x978F,
    0xE8DE: 0x9790,
    0xE8DF: 0x979C,
    0xE8E0: 0x97A8,
    0xE8E1: 0x97A6,
    0xE8E2: 0x97A3,
    0xE8E3: 0x97B3,
    0xE8E4: 0x97B4,
    0xE8E5: 0x97C3,
    0xE8E6: 0x97C6,
    0xE8E7: 0x97C8,
    0xE8E8: 0x97CB,
    0xE8E9: 0x97DC,
    0xE8EA: 0x97ED,
    0xE8EB: 0x9F4F,
    0xE8EC: 0x97F2,
    0xE8ED: 0x7ADF,
    0xE8EE: 0x97F6,
    0xE8EF: 0x97F5,
    0xE8F0: 0x980F,
    0xE8F1: 0x980C,
    0xE8F2: 0x9838,
    0xE8F3: 0x9824,
    0xE8F4: 0x9821,
    0xE8F5: 0x9837,
    0xE8F6: 0x983D,
    0xE8F7: 0x9846,
    0xE8F8: 0x984F,
    0xE8F9: 0x984B,
    0xE8FA: 0x986B,
    0xE8FB: 0x986F,
    0xE8FC: 0x9870,
    0xE940: 0x9871,
    0xE941: 0x9874,
    0xE942: 0x9873,
    0xE943: 0x98AA,
    0xE944: 0x98AF,
    0xE945: 0x98B1,
    0xE946: 0x98B6,
    0xE947: 0x98C4,
    0xE948: 0x98C3,
    0xE949: 0x98C6,
    0xE94A: 0x98E9,
    0xE94B: 0x98EB,
    0xE94C: 0x9903,
    0xE94D: 0x9909,
    0xE94E: 0x9912,
    0xE94F: 0x9914,
    0xE950: 0x9918,
    0xE951: 0x9921,
    0xE952: 0x991D,
    0xE953: 0x991E,
    0xE954: 0x9924,
    0xE955: 0x9920,
    0xE956: 0x992C,
    0xE957: 0x992E,
    0xE958: 0x993D,
    0xE959: 0x993E,
    0xE95A: 0x9942,
    0xE95B: 0x9949,
    0xE95C: 0x9945,
    0xE95D: 0x9950,
    0xE95E: 0x994B,
    0xE95F: 0x9951,
    0xE960: 0x9952,
    0xE961: 0x994C,
    0xE962: 0x9955,
    0xE963: 0x9997,
    0xE964: 0x9998,
    0xE965: 0x99A5,
    0xE966: 0x99AD,
    0xE967: 0x99AE,
    0xE968: 0x99BC,
    0xE969: 0x99DF,
    0xE96A: 0x99DB,
    0xE96B: 0x99DD,
    0xE96C: 0x99D8,
    0xE96D: 0x99D1,
    0xE96E: 0x99ED,
    0xE96F: 0x99EE,
    0xE970: 0x99F1,
    0xE971: 0x99F2,
    0xE972: 0x99FB,
    0xE973: 0x99F8,
    0xE974: 0x9A01,
    0xE975: 0x9A0F,
    0xE976: 0x9A05,
    0xE977: 0x99E2,
    0xE978: 0x9A19,
    0xE979: 0x9A2B,
    0xE97A: 0x9A37,
    0xE97B: 0x9A45,
    0xE97C: 0x9A42,
    0xE97D: 0x9A40,
    0xE97E: 0x9A43,
    0xE980: 0x9A3E,
    0xE981: 0x9A55,
    0xE982: 0x9A4D,
    0xE983: 0x9A5B,
    0xE984: 0x9A57,
    0xE985: 0x9A5F,
    0xE986: 0x9A62,
    0xE987: 0x9A65,
    0xE988: 0x9A64,
    0xE989: 0x9A69,
    0xE98A: 0x9A6B,
    0xE98B: 0x9A6A,
    0xE98C: 0x9AAD,
    0xE98D: 0x9AB0,
    0xE98E: 0x9ABC,
    0xE98F: 0x9AC0,
    0xE990: 0x9ACF,
    0xE991: 0x9AD1,
    0xE992: 0x9AD3,
    0xE993: 0x9AD4,
    0xE994: 0x9ADE,
    0xE995: 0x9ADF,
    0xE996: 0x9AE2,
    0xE997: 0x9AE3,
    0xE998: 0x9AE6,
    0xE999: 0x9AEF,
    0xE99A: 0x9AEB,
    0xE99B: 0x9AEE,
    0xE99C: 0x9AF4,
    0xE99D: 0x9AF1,
    0xE99E: 0x9AF7,
    0xE99F: 0x9AFB,
    0xE9A0: 0x9B06,
    0xE9A1: 0x9B18,
    0xE9A2: 0x9B1A,
    0xE9A3: 0x9B1F,
    0xE9A4: 0x9B22,
    0xE9A5: 0x9B23,
    0xE9A6: 0x9B25,
    0xE9A7: 0x9B27,
    0xE9A8: 0x9B28,
    0xE9A9: 0x9B29,
    0xE9AA: 0x9B2A,
    0xE9AB: 0x9B2E,
    0xE9AC: 0x9B2F,
    0xE9AD: 0x9B32,
    0xE9AE: 0x9B44,
    0xE9AF: 0x9B43,
    0xE9B0: 0x9B4F,
    0xE9B1: 0x9B4D,
    0xE9B2: 0x9B4E,
    0xE9B3: 0x9B51,
    0xE9B4: 0x9B58,
    0xE9B5: 0x9B74,
    0xE9B6: 0x9B93,
    0xE9B7: 0x9B83,
    0xE9B8: 0x9B91,
    0xE9B9: 0x9B96,
    0xE9BA: 0x9B97,
    0xE9BB: 0x9B9F,
    0xE9BC: 0x9BA0,
    0xE9BD: 0x9BA8,
    0xE9BE: 0x9BB4,
    0xE9BF: 0x9BC0,
    0xE9C0: 0x9BCA,
    0xE9C1: 0x9BB9,
    0xE9C2: 0x9BC6,
    0xE9C3: 0x9BCF,
    0xE9C4: 0x9BD1,
    0xE9C5: 0x9BD2,
    0xE9C6: 0x9BE3,
    0xE9C7: 0x9BE2,
    0xE9C8: 0x9BE4,
    0xE9C9: 0x9BD4,
    0xE9CA: 0x9BE1,
    0xE9CB: 0x9C3A,
    0xE9CC: 0x9BF2,
    0xE9CD: 0x9BF1,
    0xE9CE: 0x9BF0,
    0xE9CF: 0x9C15,
    0xE9D0: 0x9C14,
    0xE9D1: 0x9C09,
    0xE9D2: 0x9C13,
    0xE9D3: 0x9C0C,
    0xE9D4: 0x9C06,
    0xE9D5: 0x9C08,
    0xE9D6: 0x9C12,
    0xE9D7: 0x9C0A,
    0xE9D8: 0x9C04,
    0xE9D9: 0x9C2E,
    0xE9DA: 0x9C1B,
    0xE9DB: 0x9C25,
    0xE9DC: 0x9C24,
    0xE9DD: 0x9C21,
    0xE9DE: 0x9C30,
    0xE9DF: 0x9C47,
    0xE9E0: 0x9C32,
    0xE9E1: 0x9C46,
    0xE9E2: 0x9C3E,
    0xE9E3: 0x9C5A,
    0xE9E4: 0x9C60,
    0xE9E5: 0x9C67,
    0xE9E6: 0x9C76,
    0xE9E7: 0x9C78,
    0xE9E8: 0x9CE7,
    0xE9E9: 0x9CEC,
    0xE9EA: 0x9CF0,
    0xE9EB: 0x9D09,
    0xE9EC: 0x9D08,
    0xE9ED: 0x9CEB,
    0xE9EE: 0x9D03,
    0xE9EF: 0x9D06,
    0xE9F0: 0x9D2A,
    0xE9F1: 0x9D26,
    0xE9F2: 0x9DAF,
    0xE9F3: 0x9D23,
    0xE9F4: 0x9D1F,
    0xE9F5: 0x9D44,
    0xE9F6: 0x9D15,
    0xE9F7: 0x9D12,
    0xE9F8: 0x9D41,
    0xE9F9: 0x9D3F,
    0xE9FA: 0x9D3E,
    0xE9FB: 0x9D46,
    0xE9FC: 0x9D48,
    0xEA40: 0x9D5D,
    0xEA41: 0x9D5E,
    0xEA42: 0x9D64,
    0xEA43: 0x9D51,
    0xEA44: 0x9D50,
    0xEA45: 0x9D59,
    0xEA46: 0x9D72,
    0xEA47: 0x9D89,
    0xEA48: 0x9D87,
    0xEA49: 0x9DAB,
    0xEA4A: 0x9D6F,
    0xEA4B: 0x9D7A,
    0xEA4C: 0x9D9A,
    0xEA4D: 0x9DA4,
    0xEA4E: 0x9DA9,
    0xEA4F: 0x9DB2,
    0xEA50: 0x9DC4,
    0xEA51: 0x9DC1,
    0xEA52: 0x9DBB,
    0xEA53: 0x9DB8,
    0xEA54: 0x9DBA,
    0xEA55: 0x9DC6,
    0xEA56: 0x9DCF,
    0xEA57: 0x9DC2,
    0xEA58: 0x9DD9,
    0xEA59: 0x9DD3,
    0xEA5A: 0x9DF8,
    0xEA5B: 0x9DE6,
    0xEA5C: 0x9DED,
    0xEA5D: 0x9DEF,
    0xEA5E: 0x9DFD,
    0xEA5F: 0x9E1A,
    0xEA60: 0x9E1B,
    0xEA61: 0x9E1E,
    0xEA62: 0x9E75,
    0xEA63: 0x9E79,
    0xEA64: 0x9E7D,
    0xEA65: 0x9E81,
    0xEA66: 0x9E88,
    0xEA67: 0x9E8B,
    0xEA68: 0x9E8C,
    0xEA69: 0x9E92,
    0xEA6A: 0x9E95,
    0xEA6B: 0x9E91,
    0xEA6C: 0x9E9D,
    0xEA6D: 0x9EA5,
    0xEA6E: 0x9EA9,
    0xEA6F: 0x9EB8,
    0xEA70: 0x9EAA,
    0xEA71: 0x9EAD,
    0xEA72: 0x9761,
    0xEA73: 0x9ECC,
    0xEA74: 0x9ECE,
    0xEA75: 0x9ECF,
    0xEA76: 0x9ED0,
    0xEA77: 0x9ED4,
    0xEA78: 0x9EDC,
    0xEA79: 0x9EDE,
    0xEA7A: 0x9EDD,
    0xEA7B: 0x9EE0,
    0xEA7C: 0x9EE5,
    0xEA7D: 0x9EE8,
    0xEA7E: 0x9EEF,
    0xEA80: 0x9EF4,
    0xEA81: 0x9EF6,
    0xEA82: 0x9EF7,
    0xEA83: 0x9EF9,
    0xEA84: 0x9EFB,
    0xEA85: 0x9EFC,
    0xEA86: 0x9EFD,
    0xEA87: 0x9F07,
    0xEA88: 0x9F08,
    0xEA89: 0x76B7,
    0xEA8A: 0x9F15,
    0xEA8B: 0x9F21,
    0xEA8C: 0x9F2C,
    0xEA8D: 0x9F3E,
    0xEA8E: 0x9F4A,
    0xEA8F: 0x9F52,
    0xEA90: 0x9F54,
    0xEA91: 0x9F63,
    0xEA92: 0x9F5F,
    0xEA93: 0x9F60,
    0xEA94: 0x9F61,
    0xEA95: 0x9F66,
    0xEA96: 0x9F67,
    0xEA97: 0x9F6C,
    0xEA98: 0x9F6A,
    0xEA99: 0x9F77,
    0xEA9A: 0x9F72,
    0xEA9B: 0x9F76,
    0xEA9C: 0x9F95,
    0xEA9D: 0x9F9C,
    0xEA9E: 0x9FA0,
    0xEA9F: 0x582F,
    0xEAA0: 0x69C7,
    0xEAA1: 0x9059,
    0xEAA2: 0x7464,
    0xEAA3: 0x51DC,
    0xEAA4: 0x7199,
};


/***/ }),
/* 9 */
/***/ (function(module, exports, __nested_webpack_require_183922__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var GenericGF_1 = __nested_webpack_require_183922__(1);
var GenericGFPoly_1 = __nested_webpack_require_183922__(2);
function runEuclideanAlgorithm(field, a, b, R) {
    var _a;
    // Assume a's degree is >= b's
    if (a.degree() < b.degree()) {
        _a = [b, a], a = _a[0], b = _a[1];
    }
    var rLast = a;
    var r = b;
    var tLast = field.zero;
    var t = field.one;
    // Run Euclidean algorithm until r's degree is less than R/2
    while (r.degree() >= R / 2) {
        var rLastLast = rLast;
        var tLastLast = tLast;
        rLast = r;
        tLast = t;
        // Divide rLastLast by rLast, with quotient in q and remainder in r
        if (rLast.isZero()) {
            // Euclidean algorithm already terminated?
            return null;
        }
        r = rLastLast;
        var q = field.zero;
        var denominatorLeadingTerm = rLast.getCoefficient(rLast.degree());
        var dltInverse = field.inverse(denominatorLeadingTerm);
        while (r.degree() >= rLast.degree() && !r.isZero()) {
            var degreeDiff = r.degree() - rLast.degree();
            var scale = field.multiply(r.getCoefficient(r.degree()), dltInverse);
            q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale));
            r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale));
        }
        t = q.multiplyPoly(tLast).addOrSubtract(tLastLast);
        if (r.degree() >= rLast.degree()) {
            return null;
        }
    }
    var sigmaTildeAtZero = t.getCoefficient(0);
    if (sigmaTildeAtZero === 0) {
        return null;
    }
    var inverse = field.inverse(sigmaTildeAtZero);
    return [t.multiply(inverse), r.multiply(inverse)];
}
function findErrorLocations(field, errorLocator) {
    // This is a direct application of Chien's search
    var numErrors = errorLocator.degree();
    if (numErrors === 1) {
        return [errorLocator.getCoefficient(1)];
    }
    var result = new Array(numErrors);
    var errorCount = 0;
    for (var i = 1; i < field.size && errorCount < numErrors; i++) {
        if (errorLocator.evaluateAt(i) === 0) {
            result[errorCount] = field.inverse(i);
            errorCount++;
        }
    }
    if (errorCount !== numErrors) {
        return null;
    }
    return result;
}
function findErrorMagnitudes(field, errorEvaluator, errorLocations) {
    // This is directly applying Forney's Formula
    var s = errorLocations.length;
    var result = new Array(s);
    for (var i = 0; i < s; i++) {
        var xiInverse = field.inverse(errorLocations[i]);
        var denominator = 1;
        for (var j = 0; j < s; j++) {
            if (i !== j) {
                denominator = field.multiply(denominator, GenericGF_1.addOrSubtractGF(1, field.multiply(errorLocations[j], xiInverse)));
            }
        }
        result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator));
        if (field.generatorBase !== 0) {
            result[i] = field.multiply(result[i], xiInverse);
        }
    }
    return result;
}
function decode(bytes, twoS) {
    var outputBytes = new Uint8ClampedArray(bytes.length);
    outputBytes.set(bytes);
    var field = new GenericGF_1.default(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1
    var poly = new GenericGFPoly_1.default(field, outputBytes);
    var syndromeCoefficients = new Uint8ClampedArray(twoS);
    var error = false;
    for (var s = 0; s < twoS; s++) {
        var evaluation = poly.evaluateAt(field.exp(s + field.generatorBase));
        syndromeCoefficients[syndromeCoefficients.length - 1 - s] = evaluation;
        if (evaluation !== 0) {
            error = true;
        }
    }
    if (!error) {
        return outputBytes;
    }
    var syndrome = new GenericGFPoly_1.default(field, syndromeCoefficients);
    var sigmaOmega = runEuclideanAlgorithm(field, field.buildMonomial(twoS, 1), syndrome, twoS);
    if (sigmaOmega === null) {
        return null;
    }
    var errorLocations = findErrorLocations(field, sigmaOmega[0]);
    if (errorLocations == null) {
        return null;
    }
    var errorMagnitudes = findErrorMagnitudes(field, sigmaOmega[1], errorLocations);
    for (var i = 0; i < errorLocations.length; i++) {
        var position = outputBytes.length - 1 - field.log(errorLocations[i]);
        if (position < 0) {
            return null;
        }
        outputBytes[position] = GenericGF_1.addOrSubtractGF(outputBytes[position], errorMagnitudes[i]);
    }
    return outputBytes;
}
exports.decode = decode;


/***/ }),
/* 10 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.VERSIONS = [
    {
        infoBits: null,
        versionNumber: 1,
        alignmentPatternCenters: [],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 7,
                ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 19 }],
            },
            {
                ecCodewordsPerBlock: 10,
                ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 16 }],
            },
            {
                ecCodewordsPerBlock: 13,
                ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 13 }],
            },
            {
                ecCodewordsPerBlock: 17,
                ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 9 }],
            },
        ],
    },
    {
        infoBits: null,
        versionNumber: 2,
        alignmentPatternCenters: [6, 18],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 10,
                ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 34 }],
            },
            {
                ecCodewordsPerBlock: 16,
                ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 28 }],
            },
            {
                ecCodewordsPerBlock: 22,
                ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 22 }],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 16 }],
            },
        ],
    },
    {
        infoBits: null,
        versionNumber: 3,
        alignmentPatternCenters: [6, 22],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 15,
                ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 55 }],
            },
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 44 }],
            },
            {
                ecCodewordsPerBlock: 18,
                ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 17 }],
            },
            {
                ecCodewordsPerBlock: 22,
                ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 13 }],
            },
        ],
    },
    {
        infoBits: null,
        versionNumber: 4,
        alignmentPatternCenters: [6, 26],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 20,
                ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 80 }],
            },
            {
                ecCodewordsPerBlock: 18,
                ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 32 }],
            },
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 24 }],
            },
            {
                ecCodewordsPerBlock: 16,
                ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 9 }],
            },
        ],
    },
    {
        infoBits: null,
        versionNumber: 5,
        alignmentPatternCenters: [6, 30],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [{ numBlocks: 1, dataCodewordsPerBlock: 108 }],
            },
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 43 }],
            },
            {
                ecCodewordsPerBlock: 18,
                ecBlocks: [
                    { numBlocks: 2, dataCodewordsPerBlock: 15 },
                    { numBlocks: 2, dataCodewordsPerBlock: 16 },
                ],
            },
            {
                ecCodewordsPerBlock: 22,
                ecBlocks: [
                    { numBlocks: 2, dataCodewordsPerBlock: 11 },
                    { numBlocks: 2, dataCodewordsPerBlock: 12 },
                ],
            },
        ],
    },
    {
        infoBits: null,
        versionNumber: 6,
        alignmentPatternCenters: [6, 34],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 18,
                ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 68 }],
            },
            {
                ecCodewordsPerBlock: 16,
                ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 27 }],
            },
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 19 }],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 15 }],
            },
        ],
    },
    {
        infoBits: 0x07C94,
        versionNumber: 7,
        alignmentPatternCenters: [6, 22, 38],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 20,
                ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 78 }],
            },
            {
                ecCodewordsPerBlock: 18,
                ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 31 }],
            },
            {
                ecCodewordsPerBlock: 18,
                ecBlocks: [
                    { numBlocks: 2, dataCodewordsPerBlock: 14 },
                    { numBlocks: 4, dataCodewordsPerBlock: 15 },
                ],
            },
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [
                    { numBlocks: 4, dataCodewordsPerBlock: 13 },
                    { numBlocks: 1, dataCodewordsPerBlock: 14 },
                ],
            },
        ],
    },
    {
        infoBits: 0x085BC,
        versionNumber: 8,
        alignmentPatternCenters: [6, 24, 42],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 97 }],
            },
            {
                ecCodewordsPerBlock: 22,
                ecBlocks: [
                    { numBlocks: 2, dataCodewordsPerBlock: 38 },
                    { numBlocks: 2, dataCodewordsPerBlock: 39 },
                ],
            },
            {
                ecCodewordsPerBlock: 22,
                ecBlocks: [
                    { numBlocks: 4, dataCodewordsPerBlock: 18 },
                    { numBlocks: 2, dataCodewordsPerBlock: 19 },
                ],
            },
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [
                    { numBlocks: 4, dataCodewordsPerBlock: 14 },
                    { numBlocks: 2, dataCodewordsPerBlock: 15 },
                ],
            },
        ],
    },
    {
        infoBits: 0x09A99,
        versionNumber: 9,
        alignmentPatternCenters: [6, 26, 46],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [{ numBlocks: 2, dataCodewordsPerBlock: 116 }],
            },
            {
                ecCodewordsPerBlock: 22,
                ecBlocks: [
                    { numBlocks: 3, dataCodewordsPerBlock: 36 },
                    { numBlocks: 2, dataCodewordsPerBlock: 37 },
                ],
            },
            {
                ecCodewordsPerBlock: 20,
                ecBlocks: [
                    { numBlocks: 4, dataCodewordsPerBlock: 16 },
                    { numBlocks: 4, dataCodewordsPerBlock: 17 },
                ],
            },
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [
                    { numBlocks: 4, dataCodewordsPerBlock: 12 },
                    { numBlocks: 4, dataCodewordsPerBlock: 13 },
                ],
            },
        ],
    },
    {
        infoBits: 0x0A4D3,
        versionNumber: 10,
        alignmentPatternCenters: [6, 28, 50],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 18,
                ecBlocks: [
                    { numBlocks: 2, dataCodewordsPerBlock: 68 },
                    { numBlocks: 2, dataCodewordsPerBlock: 69 },
                ],
            },
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [
                    { numBlocks: 4, dataCodewordsPerBlock: 43 },
                    { numBlocks: 1, dataCodewordsPerBlock: 44 },
                ],
            },
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [
                    { numBlocks: 6, dataCodewordsPerBlock: 19 },
                    { numBlocks: 2, dataCodewordsPerBlock: 20 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 6, dataCodewordsPerBlock: 15 },
                    { numBlocks: 2, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x0BBF6,
        versionNumber: 11,
        alignmentPatternCenters: [6, 30, 54],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 20,
                ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 81 }],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 1, dataCodewordsPerBlock: 50 },
                    { numBlocks: 4, dataCodewordsPerBlock: 51 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 4, dataCodewordsPerBlock: 22 },
                    { numBlocks: 4, dataCodewordsPerBlock: 23 },
                ],
            },
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [
                    { numBlocks: 3, dataCodewordsPerBlock: 12 },
                    { numBlocks: 8, dataCodewordsPerBlock: 13 },
                ],
            },
        ],
    },
    {
        infoBits: 0x0C762,
        versionNumber: 12,
        alignmentPatternCenters: [6, 32, 58],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [
                    { numBlocks: 2, dataCodewordsPerBlock: 92 },
                    { numBlocks: 2, dataCodewordsPerBlock: 93 },
                ],
            },
            {
                ecCodewordsPerBlock: 22,
                ecBlocks: [
                    { numBlocks: 6, dataCodewordsPerBlock: 36 },
                    { numBlocks: 2, dataCodewordsPerBlock: 37 },
                ],
            },
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [
                    { numBlocks: 4, dataCodewordsPerBlock: 20 },
                    { numBlocks: 6, dataCodewordsPerBlock: 21 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 7, dataCodewordsPerBlock: 14 },
                    { numBlocks: 4, dataCodewordsPerBlock: 15 },
                ],
            },
        ],
    },
    {
        infoBits: 0x0D847,
        versionNumber: 13,
        alignmentPatternCenters: [6, 34, 62],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [{ numBlocks: 4, dataCodewordsPerBlock: 107 }],
            },
            {
                ecCodewordsPerBlock: 22,
                ecBlocks: [
                    { numBlocks: 8, dataCodewordsPerBlock: 37 },
                    { numBlocks: 1, dataCodewordsPerBlock: 38 },
                ],
            },
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [
                    { numBlocks: 8, dataCodewordsPerBlock: 20 },
                    { numBlocks: 4, dataCodewordsPerBlock: 21 },
                ],
            },
            {
                ecCodewordsPerBlock: 22,
                ecBlocks: [
                    { numBlocks: 12, dataCodewordsPerBlock: 11 },
                    { numBlocks: 4, dataCodewordsPerBlock: 12 },
                ],
            },
        ],
    },
    {
        infoBits: 0x0E60D,
        versionNumber: 14,
        alignmentPatternCenters: [6, 26, 46, 66],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 3, dataCodewordsPerBlock: 115 },
                    { numBlocks: 1, dataCodewordsPerBlock: 116 },
                ],
            },
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [
                    { numBlocks: 4, dataCodewordsPerBlock: 40 },
                    { numBlocks: 5, dataCodewordsPerBlock: 41 },
                ],
            },
            {
                ecCodewordsPerBlock: 20,
                ecBlocks: [
                    { numBlocks: 11, dataCodewordsPerBlock: 16 },
                    { numBlocks: 5, dataCodewordsPerBlock: 17 },
                ],
            },
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [
                    { numBlocks: 11, dataCodewordsPerBlock: 12 },
                    { numBlocks: 5, dataCodewordsPerBlock: 13 },
                ],
            },
        ],
    },
    {
        infoBits: 0x0F928,
        versionNumber: 15,
        alignmentPatternCenters: [6, 26, 48, 70],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 22,
                ecBlocks: [
                    { numBlocks: 5, dataCodewordsPerBlock: 87 },
                    { numBlocks: 1, dataCodewordsPerBlock: 88 },
                ],
            },
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [
                    { numBlocks: 5, dataCodewordsPerBlock: 41 },
                    { numBlocks: 5, dataCodewordsPerBlock: 42 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 5, dataCodewordsPerBlock: 24 },
                    { numBlocks: 7, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [
                    { numBlocks: 11, dataCodewordsPerBlock: 12 },
                    { numBlocks: 7, dataCodewordsPerBlock: 13 },
                ],
            },
        ],
    },
    {
        infoBits: 0x10B78,
        versionNumber: 16,
        alignmentPatternCenters: [6, 26, 50, 74],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [
                    { numBlocks: 5, dataCodewordsPerBlock: 98 },
                    { numBlocks: 1, dataCodewordsPerBlock: 99 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 7, dataCodewordsPerBlock: 45 },
                    { numBlocks: 3, dataCodewordsPerBlock: 46 },
                ],
            },
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [
                    { numBlocks: 15, dataCodewordsPerBlock: 19 },
                    { numBlocks: 2, dataCodewordsPerBlock: 20 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 3, dataCodewordsPerBlock: 15 },
                    { numBlocks: 13, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x1145D,
        versionNumber: 17,
        alignmentPatternCenters: [6, 30, 54, 78],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 1, dataCodewordsPerBlock: 107 },
                    { numBlocks: 5, dataCodewordsPerBlock: 108 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 10, dataCodewordsPerBlock: 46 },
                    { numBlocks: 1, dataCodewordsPerBlock: 47 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 1, dataCodewordsPerBlock: 22 },
                    { numBlocks: 15, dataCodewordsPerBlock: 23 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 2, dataCodewordsPerBlock: 14 },
                    { numBlocks: 17, dataCodewordsPerBlock: 15 },
                ],
            },
        ],
    },
    {
        infoBits: 0x12A17,
        versionNumber: 18,
        alignmentPatternCenters: [6, 30, 56, 82],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 5, dataCodewordsPerBlock: 120 },
                    { numBlocks: 1, dataCodewordsPerBlock: 121 },
                ],
            },
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [
                    { numBlocks: 9, dataCodewordsPerBlock: 43 },
                    { numBlocks: 4, dataCodewordsPerBlock: 44 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 17, dataCodewordsPerBlock: 22 },
                    { numBlocks: 1, dataCodewordsPerBlock: 23 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 2, dataCodewordsPerBlock: 14 },
                    { numBlocks: 19, dataCodewordsPerBlock: 15 },
                ],
            },
        ],
    },
    {
        infoBits: 0x13532,
        versionNumber: 19,
        alignmentPatternCenters: [6, 30, 58, 86],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 3, dataCodewordsPerBlock: 113 },
                    { numBlocks: 4, dataCodewordsPerBlock: 114 },
                ],
            },
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [
                    { numBlocks: 3, dataCodewordsPerBlock: 44 },
                    { numBlocks: 11, dataCodewordsPerBlock: 45 },
                ],
            },
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [
                    { numBlocks: 17, dataCodewordsPerBlock: 21 },
                    { numBlocks: 4, dataCodewordsPerBlock: 22 },
                ],
            },
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [
                    { numBlocks: 9, dataCodewordsPerBlock: 13 },
                    { numBlocks: 16, dataCodewordsPerBlock: 14 },
                ],
            },
        ],
    },
    {
        infoBits: 0x149A6,
        versionNumber: 20,
        alignmentPatternCenters: [6, 34, 62, 90],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 3, dataCodewordsPerBlock: 107 },
                    { numBlocks: 5, dataCodewordsPerBlock: 108 },
                ],
            },
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [
                    { numBlocks: 3, dataCodewordsPerBlock: 41 },
                    { numBlocks: 13, dataCodewordsPerBlock: 42 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 15, dataCodewordsPerBlock: 24 },
                    { numBlocks: 5, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 15, dataCodewordsPerBlock: 15 },
                    { numBlocks: 10, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x15683,
        versionNumber: 21,
        alignmentPatternCenters: [6, 28, 50, 72, 94],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 4, dataCodewordsPerBlock: 116 },
                    { numBlocks: 4, dataCodewordsPerBlock: 117 },
                ],
            },
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 42 }],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 17, dataCodewordsPerBlock: 22 },
                    { numBlocks: 6, dataCodewordsPerBlock: 23 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 19, dataCodewordsPerBlock: 16 },
                    { numBlocks: 6, dataCodewordsPerBlock: 17 },
                ],
            },
        ],
    },
    {
        infoBits: 0x168C9,
        versionNumber: 22,
        alignmentPatternCenters: [6, 26, 50, 74, 98],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 2, dataCodewordsPerBlock: 111 },
                    { numBlocks: 7, dataCodewordsPerBlock: 112 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 46 }],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 7, dataCodewordsPerBlock: 24 },
                    { numBlocks: 16, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 24,
                ecBlocks: [{ numBlocks: 34, dataCodewordsPerBlock: 13 }],
            },
        ],
    },
    {
        infoBits: 0x177EC,
        versionNumber: 23,
        alignmentPatternCenters: [6, 30, 54, 74, 102],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 4, dataCodewordsPerBlock: 121 },
                    { numBlocks: 5, dataCodewordsPerBlock: 122 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 4, dataCodewordsPerBlock: 47 },
                    { numBlocks: 14, dataCodewordsPerBlock: 48 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 11, dataCodewordsPerBlock: 24 },
                    { numBlocks: 14, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 16, dataCodewordsPerBlock: 15 },
                    { numBlocks: 14, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x18EC4,
        versionNumber: 24,
        alignmentPatternCenters: [6, 28, 54, 80, 106],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 6, dataCodewordsPerBlock: 117 },
                    { numBlocks: 4, dataCodewordsPerBlock: 118 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 6, dataCodewordsPerBlock: 45 },
                    { numBlocks: 14, dataCodewordsPerBlock: 46 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 11, dataCodewordsPerBlock: 24 },
                    { numBlocks: 16, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 30, dataCodewordsPerBlock: 16 },
                    { numBlocks: 2, dataCodewordsPerBlock: 17 },
                ],
            },
        ],
    },
    {
        infoBits: 0x191E1,
        versionNumber: 25,
        alignmentPatternCenters: [6, 32, 58, 84, 110],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 26,
                ecBlocks: [
                    { numBlocks: 8, dataCodewordsPerBlock: 106 },
                    { numBlocks: 4, dataCodewordsPerBlock: 107 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 8, dataCodewordsPerBlock: 47 },
                    { numBlocks: 13, dataCodewordsPerBlock: 48 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 7, dataCodewordsPerBlock: 24 },
                    { numBlocks: 22, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 22, dataCodewordsPerBlock: 15 },
                    { numBlocks: 13, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x1AFAB,
        versionNumber: 26,
        alignmentPatternCenters: [6, 30, 58, 86, 114],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 10, dataCodewordsPerBlock: 114 },
                    { numBlocks: 2, dataCodewordsPerBlock: 115 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 19, dataCodewordsPerBlock: 46 },
                    { numBlocks: 4, dataCodewordsPerBlock: 47 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 28, dataCodewordsPerBlock: 22 },
                    { numBlocks: 6, dataCodewordsPerBlock: 23 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 33, dataCodewordsPerBlock: 16 },
                    { numBlocks: 4, dataCodewordsPerBlock: 17 },
                ],
            },
        ],
    },
    {
        infoBits: 0x1B08E,
        versionNumber: 27,
        alignmentPatternCenters: [6, 34, 62, 90, 118],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 8, dataCodewordsPerBlock: 122 },
                    { numBlocks: 4, dataCodewordsPerBlock: 123 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 22, dataCodewordsPerBlock: 45 },
                    { numBlocks: 3, dataCodewordsPerBlock: 46 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 8, dataCodewordsPerBlock: 23 },
                    { numBlocks: 26, dataCodewordsPerBlock: 24 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 12, dataCodewordsPerBlock: 15 },
                    { numBlocks: 28, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x1CC1A,
        versionNumber: 28,
        alignmentPatternCenters: [6, 26, 50, 74, 98, 122],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 3, dataCodewordsPerBlock: 117 },
                    { numBlocks: 10, dataCodewordsPerBlock: 118 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 3, dataCodewordsPerBlock: 45 },
                    { numBlocks: 23, dataCodewordsPerBlock: 46 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 4, dataCodewordsPerBlock: 24 },
                    { numBlocks: 31, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 11, dataCodewordsPerBlock: 15 },
                    { numBlocks: 31, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x1D33F,
        versionNumber: 29,
        alignmentPatternCenters: [6, 30, 54, 78, 102, 126],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 7, dataCodewordsPerBlock: 116 },
                    { numBlocks: 7, dataCodewordsPerBlock: 117 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 21, dataCodewordsPerBlock: 45 },
                    { numBlocks: 7, dataCodewordsPerBlock: 46 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 1, dataCodewordsPerBlock: 23 },
                    { numBlocks: 37, dataCodewordsPerBlock: 24 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 19, dataCodewordsPerBlock: 15 },
                    { numBlocks: 26, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x1ED75,
        versionNumber: 30,
        alignmentPatternCenters: [6, 26, 52, 78, 104, 130],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 5, dataCodewordsPerBlock: 115 },
                    { numBlocks: 10, dataCodewordsPerBlock: 116 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 19, dataCodewordsPerBlock: 47 },
                    { numBlocks: 10, dataCodewordsPerBlock: 48 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 15, dataCodewordsPerBlock: 24 },
                    { numBlocks: 25, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 23, dataCodewordsPerBlock: 15 },
                    { numBlocks: 25, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x1F250,
        versionNumber: 31,
        alignmentPatternCenters: [6, 30, 56, 82, 108, 134],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 13, dataCodewordsPerBlock: 115 },
                    { numBlocks: 3, dataCodewordsPerBlock: 116 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 2, dataCodewordsPerBlock: 46 },
                    { numBlocks: 29, dataCodewordsPerBlock: 47 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 42, dataCodewordsPerBlock: 24 },
                    { numBlocks: 1, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 23, dataCodewordsPerBlock: 15 },
                    { numBlocks: 28, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x209D5,
        versionNumber: 32,
        alignmentPatternCenters: [6, 34, 60, 86, 112, 138],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [{ numBlocks: 17, dataCodewordsPerBlock: 115 }],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 10, dataCodewordsPerBlock: 46 },
                    { numBlocks: 23, dataCodewordsPerBlock: 47 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 10, dataCodewordsPerBlock: 24 },
                    { numBlocks: 35, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 19, dataCodewordsPerBlock: 15 },
                    { numBlocks: 35, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x216F0,
        versionNumber: 33,
        alignmentPatternCenters: [6, 30, 58, 86, 114, 142],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 17, dataCodewordsPerBlock: 115 },
                    { numBlocks: 1, dataCodewordsPerBlock: 116 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 14, dataCodewordsPerBlock: 46 },
                    { numBlocks: 21, dataCodewordsPerBlock: 47 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 29, dataCodewordsPerBlock: 24 },
                    { numBlocks: 19, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 11, dataCodewordsPerBlock: 15 },
                    { numBlocks: 46, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x228BA,
        versionNumber: 34,
        alignmentPatternCenters: [6, 34, 62, 90, 118, 146],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 13, dataCodewordsPerBlock: 115 },
                    { numBlocks: 6, dataCodewordsPerBlock: 116 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 14, dataCodewordsPerBlock: 46 },
                    { numBlocks: 23, dataCodewordsPerBlock: 47 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 44, dataCodewordsPerBlock: 24 },
                    { numBlocks: 7, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 59, dataCodewordsPerBlock: 16 },
                    { numBlocks: 1, dataCodewordsPerBlock: 17 },
                ],
            },
        ],
    },
    {
        infoBits: 0x2379F,
        versionNumber: 35,
        alignmentPatternCenters: [6, 30, 54, 78, 102, 126, 150],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 12, dataCodewordsPerBlock: 121 },
                    { numBlocks: 7, dataCodewordsPerBlock: 122 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 12, dataCodewordsPerBlock: 47 },
                    { numBlocks: 26, dataCodewordsPerBlock: 48 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 39, dataCodewordsPerBlock: 24 },
                    { numBlocks: 14, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 22, dataCodewordsPerBlock: 15 },
                    { numBlocks: 41, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x24B0B,
        versionNumber: 36,
        alignmentPatternCenters: [6, 24, 50, 76, 102, 128, 154],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 6, dataCodewordsPerBlock: 121 },
                    { numBlocks: 14, dataCodewordsPerBlock: 122 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 6, dataCodewordsPerBlock: 47 },
                    { numBlocks: 34, dataCodewordsPerBlock: 48 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 46, dataCodewordsPerBlock: 24 },
                    { numBlocks: 10, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 2, dataCodewordsPerBlock: 15 },
                    { numBlocks: 64, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x2542E,
        versionNumber: 37,
        alignmentPatternCenters: [6, 28, 54, 80, 106, 132, 158],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 17, dataCodewordsPerBlock: 122 },
                    { numBlocks: 4, dataCodewordsPerBlock: 123 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 29, dataCodewordsPerBlock: 46 },
                    { numBlocks: 14, dataCodewordsPerBlock: 47 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 49, dataCodewordsPerBlock: 24 },
                    { numBlocks: 10, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 24, dataCodewordsPerBlock: 15 },
                    { numBlocks: 46, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x26A64,
        versionNumber: 38,
        alignmentPatternCenters: [6, 32, 58, 84, 110, 136, 162],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 4, dataCodewordsPerBlock: 122 },
                    { numBlocks: 18, dataCodewordsPerBlock: 123 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 13, dataCodewordsPerBlock: 46 },
                    { numBlocks: 32, dataCodewordsPerBlock: 47 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 48, dataCodewordsPerBlock: 24 },
                    { numBlocks: 14, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 42, dataCodewordsPerBlock: 15 },
                    { numBlocks: 32, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x27541,
        versionNumber: 39,
        alignmentPatternCenters: [6, 26, 54, 82, 110, 138, 166],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 20, dataCodewordsPerBlock: 117 },
                    { numBlocks: 4, dataCodewordsPerBlock: 118 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 40, dataCodewordsPerBlock: 47 },
                    { numBlocks: 7, dataCodewordsPerBlock: 48 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 43, dataCodewordsPerBlock: 24 },
                    { numBlocks: 22, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 10, dataCodewordsPerBlock: 15 },
                    { numBlocks: 67, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
    {
        infoBits: 0x28C69,
        versionNumber: 40,
        alignmentPatternCenters: [6, 30, 58, 86, 114, 142, 170],
        errorCorrectionLevels: [
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 19, dataCodewordsPerBlock: 118 },
                    { numBlocks: 6, dataCodewordsPerBlock: 119 },
                ],
            },
            {
                ecCodewordsPerBlock: 28,
                ecBlocks: [
                    { numBlocks: 18, dataCodewordsPerBlock: 47 },
                    { numBlocks: 31, dataCodewordsPerBlock: 48 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 34, dataCodewordsPerBlock: 24 },
                    { numBlocks: 34, dataCodewordsPerBlock: 25 },
                ],
            },
            {
                ecCodewordsPerBlock: 30,
                ecBlocks: [
                    { numBlocks: 20, dataCodewordsPerBlock: 15 },
                    { numBlocks: 61, dataCodewordsPerBlock: 16 },
                ],
            },
        ],
    },
];


/***/ }),
/* 11 */
/***/ (function(module, exports, __nested_webpack_require_231645__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var BitMatrix_1 = __nested_webpack_require_231645__(0);
function squareToQuadrilateral(p1, p2, p3, p4) {
    var dx3 = p1.x - p2.x + p3.x - p4.x;
    var dy3 = p1.y - p2.y + p3.y - p4.y;
    if (dx3 === 0 && dy3 === 0) { // Affine
        return {
            a11: p2.x - p1.x,
            a12: p2.y - p1.y,
            a13: 0,
            a21: p3.x - p2.x,
            a22: p3.y - p2.y,
            a23: 0,
            a31: p1.x,
            a32: p1.y,
            a33: 1,
        };
    }
    else {
        var dx1 = p2.x - p3.x;
        var dx2 = p4.x - p3.x;
        var dy1 = p2.y - p3.y;
        var dy2 = p4.y - p3.y;
        var denominator = dx1 * dy2 - dx2 * dy1;
        var a13 = (dx3 * dy2 - dx2 * dy3) / denominator;
        var a23 = (dx1 * dy3 - dx3 * dy1) / denominator;
        return {
            a11: p2.x - p1.x + a13 * p2.x,
            a12: p2.y - p1.y + a13 * p2.y,
            a13: a13,
            a21: p4.x - p1.x + a23 * p4.x,
            a22: p4.y - p1.y + a23 * p4.y,
            a23: a23,
            a31: p1.x,
            a32: p1.y,
            a33: 1,
        };
    }
}
function quadrilateralToSquare(p1, p2, p3, p4) {
    // Here, the adjoint serves as the inverse:
    var sToQ = squareToQuadrilateral(p1, p2, p3, p4);
    return {
        a11: sToQ.a22 * sToQ.a33 - sToQ.a23 * sToQ.a32,
        a12: sToQ.a13 * sToQ.a32 - sToQ.a12 * sToQ.a33,
        a13: sToQ.a12 * sToQ.a23 - sToQ.a13 * sToQ.a22,
        a21: sToQ.a23 * sToQ.a31 - sToQ.a21 * sToQ.a33,
        a22: sToQ.a11 * sToQ.a33 - sToQ.a13 * sToQ.a31,
        a23: sToQ.a13 * sToQ.a21 - sToQ.a11 * sToQ.a23,
        a31: sToQ.a21 * sToQ.a32 - sToQ.a22 * sToQ.a31,
        a32: sToQ.a12 * sToQ.a31 - sToQ.a11 * sToQ.a32,
        a33: sToQ.a11 * sToQ.a22 - sToQ.a12 * sToQ.a21,
    };
}
function times(a, b) {
    return {
        a11: a.a11 * b.a11 + a.a21 * b.a12 + a.a31 * b.a13,
        a12: a.a12 * b.a11 + a.a22 * b.a12 + a.a32 * b.a13,
        a13: a.a13 * b.a11 + a.a23 * b.a12 + a.a33 * b.a13,
        a21: a.a11 * b.a21 + a.a21 * b.a22 + a.a31 * b.a23,
        a22: a.a12 * b.a21 + a.a22 * b.a22 + a.a32 * b.a23,
        a23: a.a13 * b.a21 + a.a23 * b.a22 + a.a33 * b.a23,
        a31: a.a11 * b.a31 + a.a21 * b.a32 + a.a31 * b.a33,
        a32: a.a12 * b.a31 + a.a22 * b.a32 + a.a32 * b.a33,
        a33: a.a13 * b.a31 + a.a23 * b.a32 + a.a33 * b.a33,
    };
}
function extract(image, location) {
    var qToS = quadrilateralToSquare({ x: 3.5, y: 3.5 }, { x: location.dimension - 3.5, y: 3.5 }, { x: location.dimension - 6.5, y: location.dimension - 6.5 }, { x: 3.5, y: location.dimension - 3.5 });
    var sToQ = squareToQuadrilateral(location.topLeft, location.topRight, location.alignmentPattern, location.bottomLeft);
    var transform = times(sToQ, qToS);
    var matrix = BitMatrix_1.BitMatrix.createEmpty(location.dimension, location.dimension);
    var mappingFunction = function (x, y) {
        var denominator = transform.a13 * x + transform.a23 * y + transform.a33;
        return {
            x: (transform.a11 * x + transform.a21 * y + transform.a31) / denominator,
            y: (transform.a12 * x + transform.a22 * y + transform.a32) / denominator,
        };
    };
    for (var y = 0; y < location.dimension; y++) {
        for (var x = 0; x < location.dimension; x++) {
            var xValue = x + 0.5;
            var yValue = y + 0.5;
            var sourcePixel = mappingFunction(xValue, yValue);
            matrix.set(x, y, image.get(Math.floor(sourcePixel.x), Math.floor(sourcePixel.y)));
        }
    }
    return {
        matrix: matrix,
        mappingFunction: mappingFunction,
    };
}
exports.extract = extract;


/***/ }),
/* 12 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var MAX_FINDERPATTERNS_TO_SEARCH = 4;
var MIN_QUAD_RATIO = 0.5;
var MAX_QUAD_RATIO = 1.5;
var distance = function (a, b) { return Math.sqrt(Math.pow((b.x - a.x), 2) + Math.pow((b.y - a.y), 2)); };
function sum(values) {
    return values.reduce(function (a, b) { return a + b; });
}
// Takes three finder patterns and organizes them into topLeft, topRight, etc
function reorderFinderPatterns(pattern1, pattern2, pattern3) {
    var _a, _b, _c, _d;
    // Find distances between pattern centers
    var oneTwoDistance = distance(pattern1, pattern2);
    var twoThreeDistance = distance(pattern2, pattern3);
    var oneThreeDistance = distance(pattern1, pattern3);
    var bottomLeft;
    var topLeft;
    var topRight;
    // Assume one closest to other two is B; A and C will just be guesses at first
    if (twoThreeDistance >= oneTwoDistance && twoThreeDistance >= oneThreeDistance) {
        _a = [pattern2, pattern1, pattern3], bottomLeft = _a[0], topLeft = _a[1], topRight = _a[2];
    }
    else if (oneThreeDistance >= twoThreeDistance && oneThreeDistance >= oneTwoDistance) {
        _b = [pattern1, pattern2, pattern3], bottomLeft = _b[0], topLeft = _b[1], topRight = _b[2];
    }
    else {
        _c = [pattern1, pattern3, pattern2], bottomLeft = _c[0], topLeft = _c[1], topRight = _c[2];
    }
    // Use cross product to figure out whether bottomLeft (A) and topRight (C) are correct or flipped in relation to topLeft (B)
    // This asks whether BC x BA has a positive z component, which is the arrangement we want. If it's negative, then
    // we've got it flipped around and should swap topRight and bottomLeft.
    if (((topRight.x - topLeft.x) * (bottomLeft.y - topLeft.y)) - ((topRight.y - topLeft.y) * (bottomLeft.x - topLeft.x)) < 0) {
        _d = [topRight, bottomLeft], bottomLeft = _d[0], topRight = _d[1];
    }
    return { bottomLeft: bottomLeft, topLeft: topLeft, topRight: topRight };
}
// Computes the dimension (number of modules on a side) of the QR Code based on the position of the finder patterns
function computeDimension(topLeft, topRight, bottomLeft, matrix) {
    var moduleSize = (sum(countBlackWhiteRun(topLeft, bottomLeft, matrix, 5)) / 7 + // Divide by 7 since the ratio is 1:1:3:1:1
        sum(countBlackWhiteRun(topLeft, topRight, matrix, 5)) / 7 +
        sum(countBlackWhiteRun(bottomLeft, topLeft, matrix, 5)) / 7 +
        sum(countBlackWhiteRun(topRight, topLeft, matrix, 5)) / 7) / 4;
    if (moduleSize < 1) {
        throw new Error("Invalid module size");
    }
    var topDimension = Math.round(distance(topLeft, topRight) / moduleSize);
    var sideDimension = Math.round(distance(topLeft, bottomLeft) / moduleSize);
    var dimension = Math.floor((topDimension + sideDimension) / 2) + 7;
    switch (dimension % 4) {
        case 0:
            dimension++;
            break;
        case 2:
            dimension--;
            break;
    }
    return { dimension: dimension, moduleSize: moduleSize };
}
// Takes an origin point and an end point and counts the sizes of the black white run from the origin towards the end point.
// Returns an array of elements, representing the pixel size of the black white run.
// Uses a variant of http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
function countBlackWhiteRunTowardsPoint(origin, end, matrix, length) {
    var switchPoints = [{ x: Math.floor(origin.x), y: Math.floor(origin.y) }];
    var steep = Math.abs(end.y - origin.y) > Math.abs(end.x - origin.x);
    var fromX;
    var fromY;
    var toX;
    var toY;
    if (steep) {
        fromX = Math.floor(origin.y);
        fromY = Math.floor(origin.x);
        toX = Math.floor(end.y);
        toY = Math.floor(end.x);
    }
    else {
        fromX = Math.floor(origin.x);
        fromY = Math.floor(origin.y);
        toX = Math.floor(end.x);
        toY = Math.floor(end.y);
    }
    var dx = Math.abs(toX - fromX);
    var dy = Math.abs(toY - fromY);
    var error = Math.floor(-dx / 2);
    var xStep = fromX < toX ? 1 : -1;
    var yStep = fromY < toY ? 1 : -1;
    var currentPixel = true;
    // Loop up until x == toX, but not beyond
    for (var x = fromX, y = fromY; x !== toX + xStep; x += xStep) {
        // Does current pixel mean we have moved white to black or vice versa?
        // Scanning black in state 0,2 and white in state 1, so if we find the wrong
        // color, advance to next state or end if we are in state 2 already
        var realX = steep ? y : x;
        var realY = steep ? x : y;
        if (matrix.get(realX, realY) !== currentPixel) {
            currentPixel = !currentPixel;
            switchPoints.push({ x: realX, y: realY });
            if (switchPoints.length === length + 1) {
                break;
            }
        }
        error += dy;
        if (error > 0) {
            if (y === toY) {
                break;
            }
            y += yStep;
            error -= dx;
        }
    }
    var distances = [];
    for (var i = 0; i < length; i++) {
        if (switchPoints[i] && switchPoints[i + 1]) {
            distances.push(distance(switchPoints[i], switchPoints[i + 1]));
        }
        else {
            distances.push(0);
        }
    }
    return distances;
}
// Takes an origin point and an end point and counts the sizes of the black white run in the origin point
// along the line that intersects with the end point. Returns an array of elements, representing the pixel sizes
// of the black white run. Takes a length which represents the number of switches from black to white to look for.
function countBlackWhiteRun(origin, end, matrix, length) {
    var _a;
    var rise = end.y - origin.y;
    var run = end.x - origin.x;
    var towardsEnd = countBlackWhiteRunTowardsPoint(origin, end, matrix, Math.ceil(length / 2));
    var awayFromEnd = countBlackWhiteRunTowardsPoint(origin, { x: origin.x - run, y: origin.y - rise }, matrix, Math.ceil(length / 2));
    var middleValue = towardsEnd.shift() + awayFromEnd.shift() - 1; // Substract one so we don't double count a pixel
    return (_a = awayFromEnd.concat(middleValue)).concat.apply(_a, towardsEnd);
}
// Takes in a black white run and an array of expected ratios. Returns the average size of the run as well as the "error" -
// that is the amount the run diverges from the expected ratio
function scoreBlackWhiteRun(sequence, ratios) {
    var averageSize = sum(sequence) / sum(ratios);
    var error = 0;
    ratios.forEach(function (ratio, i) {
        error += Math.pow((sequence[i] - ratio * averageSize), 2);
    });
    return { averageSize: averageSize, error: error };
}
// Takes an X,Y point and an array of sizes and scores the point against those ratios.
// For example for a finder pattern takes the ratio list of 1:1:3:1:1 and checks horizontal, vertical and diagonal ratios
// against that.
function scorePattern(point, ratios, matrix) {
    try {
        var horizontalRun = countBlackWhiteRun(point, { x: -1, y: point.y }, matrix, ratios.length);
        var verticalRun = countBlackWhiteRun(point, { x: point.x, y: -1 }, matrix, ratios.length);
        var topLeftPoint = {
            x: Math.max(0, point.x - point.y) - 1,
            y: Math.max(0, point.y - point.x) - 1,
        };
        var topLeftBottomRightRun = countBlackWhiteRun(point, topLeftPoint, matrix, ratios.length);
        var bottomLeftPoint = {
            x: Math.min(matrix.width, point.x + point.y) + 1,
            y: Math.min(matrix.height, point.y + point.x) + 1,
        };
        var bottomLeftTopRightRun = countBlackWhiteRun(point, bottomLeftPoint, matrix, ratios.length);
        var horzError = scoreBlackWhiteRun(horizontalRun, ratios);
        var vertError = scoreBlackWhiteRun(verticalRun, ratios);
        var diagDownError = scoreBlackWhiteRun(topLeftBottomRightRun, ratios);
        var diagUpError = scoreBlackWhiteRun(bottomLeftTopRightRun, ratios);
        var ratioError = Math.sqrt(horzError.error * horzError.error +
            vertError.error * vertError.error +
            diagDownError.error * diagDownError.error +
            diagUpError.error * diagUpError.error);
        var avgSize = (horzError.averageSize + vertError.averageSize + diagDownError.averageSize + diagUpError.averageSize) / 4;
        var sizeError = (Math.pow((horzError.averageSize - avgSize), 2) +
            Math.pow((vertError.averageSize - avgSize), 2) +
            Math.pow((diagDownError.averageSize - avgSize), 2) +
            Math.pow((diagUpError.averageSize - avgSize), 2)) / avgSize;
        return ratioError + sizeError;
    }
    catch (_a) {
        return Infinity;
    }
}
function recenterLocation(matrix, p) {
    var leftX = Math.round(p.x);
    while (matrix.get(leftX, Math.round(p.y))) {
        leftX--;
    }
    var rightX = Math.round(p.x);
    while (matrix.get(rightX, Math.round(p.y))) {
        rightX++;
    }
    var x = (leftX + rightX) / 2;
    var topY = Math.round(p.y);
    while (matrix.get(Math.round(x), topY)) {
        topY--;
    }
    var bottomY = Math.round(p.y);
    while (matrix.get(Math.round(x), bottomY)) {
        bottomY++;
    }
    var y = (topY + bottomY) / 2;
    return { x: x, y: y };
}
function locate(matrix) {
    var finderPatternQuads = [];
    var activeFinderPatternQuads = [];
    var alignmentPatternQuads = [];
    var activeAlignmentPatternQuads = [];
    var _loop_1 = function (y) {
        var length_1 = 0;
        var lastBit = false;
        var scans = [0, 0, 0, 0, 0];
        var _loop_2 = function (x) {
            var v = matrix.get(x, y);
            if (v === lastBit) {
                length_1++;
            }
            else {
                scans = [scans[1], scans[2], scans[3], scans[4], length_1];
                length_1 = 1;
                lastBit = v;
                // Do the last 5 color changes ~ match the expected ratio for a finder pattern? 1:1:3:1:1 of b:w:b:w:b
                var averageFinderPatternBlocksize = sum(scans) / 7;
                var validFinderPattern = Math.abs(scans[0] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize &&
                    Math.abs(scans[1] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize &&
                    Math.abs(scans[2] - 3 * averageFinderPatternBlocksize) < 3 * averageFinderPatternBlocksize &&
                    Math.abs(scans[3] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize &&
                    Math.abs(scans[4] - averageFinderPatternBlocksize) < averageFinderPatternBlocksize &&
                    !v; // And make sure the current pixel is white since finder patterns are bordered in white
                // Do the last 3 color changes ~ match the expected ratio for an alignment pattern? 1:1:1 of w:b:w
                var averageAlignmentPatternBlocksize = sum(scans.slice(-3)) / 3;
                var validAlignmentPattern = Math.abs(scans[2] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize &&
                    Math.abs(scans[3] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize &&
                    Math.abs(scans[4] - averageAlignmentPatternBlocksize) < averageAlignmentPatternBlocksize &&
                    v; // Is the current pixel black since alignment patterns are bordered in black
                if (validFinderPattern) {
                    // Compute the start and end x values of the large center black square
                    var endX_1 = x - scans[3] - scans[4];
                    var startX_1 = endX_1 - scans[2];
                    var line = { startX: startX_1, endX: endX_1, y: y };
                    // Is there a quad directly above the current spot? If so, extend it with the new line. Otherwise, create a new quad with
                    // that line as the starting point.
                    var matchingQuads = activeFinderPatternQuads.filter(function (q) {
                        return (startX_1 >= q.bottom.startX && startX_1 <= q.bottom.endX) ||
                            (endX_1 >= q.bottom.startX && startX_1 <= q.bottom.endX) ||
                            (startX_1 <= q.bottom.startX && endX_1 >= q.bottom.endX && ((scans[2] / (q.bottom.endX - q.bottom.startX)) < MAX_QUAD_RATIO &&
                                (scans[2] / (q.bottom.endX - q.bottom.startX)) > MIN_QUAD_RATIO));
                    });
                    if (matchingQuads.length > 0) {
                        matchingQuads[0].bottom = line;
                    }
                    else {
                        activeFinderPatternQuads.push({ top: line, bottom: line });
                    }
                }
                if (validAlignmentPattern) {
                    // Compute the start and end x values of the center black square
                    var endX_2 = x - scans[4];
                    var startX_2 = endX_2 - scans[3];
                    var line = { startX: startX_2, y: y, endX: endX_2 };
                    // Is there a quad directly above the current spot? If so, extend it with the new line. Otherwise, create a new quad with
                    // that line as the starting point.
                    var matchingQuads = activeAlignmentPatternQuads.filter(function (q) {
                        return (startX_2 >= q.bottom.startX && startX_2 <= q.bottom.endX) ||
                            (endX_2 >= q.bottom.startX && startX_2 <= q.bottom.endX) ||
                            (startX_2 <= q.bottom.startX && endX_2 >= q.bottom.endX && ((scans[2] / (q.bottom.endX - q.bottom.startX)) < MAX_QUAD_RATIO &&
                                (scans[2] / (q.bottom.endX - q.bottom.startX)) > MIN_QUAD_RATIO));
                    });
                    if (matchingQuads.length > 0) {
                        matchingQuads[0].bottom = line;
                    }
                    else {
                        activeAlignmentPatternQuads.push({ top: line, bottom: line });
                    }
                }
            }
        };
        for (var x = -1; x <= matrix.width; x++) {
            _loop_2(x);
        }
        finderPatternQuads.push.apply(finderPatternQuads, activeFinderPatternQuads.filter(function (q) { return q.bottom.y !== y && q.bottom.y - q.top.y >= 2; }));
        activeFinderPatternQuads = activeFinderPatternQuads.filter(function (q) { return q.bottom.y === y; });
        alignmentPatternQuads.push.apply(alignmentPatternQuads, activeAlignmentPatternQuads.filter(function (q) { return q.bottom.y !== y; }));
        activeAlignmentPatternQuads = activeAlignmentPatternQuads.filter(function (q) { return q.bottom.y === y; });
    };
    for (var y = 0; y <= matrix.height; y++) {
        _loop_1(y);
    }
    finderPatternQuads.push.apply(finderPatternQuads, activeFinderPatternQuads.filter(function (q) { return q.bottom.y - q.top.y >= 2; }));
    alignmentPatternQuads.push.apply(alignmentPatternQuads, activeAlignmentPatternQuads);
    var finderPatternGroups = finderPatternQuads
        .filter(function (q) { return q.bottom.y - q.top.y >= 2; }) // All quads must be at least 2px tall since the center square is larger than a block
        .map(function (q) {
        var x = (q.top.startX + q.top.endX + q.bottom.startX + q.bottom.endX) / 4;
        var y = (q.top.y + q.bottom.y + 1) / 2;
        if (!matrix.get(Math.round(x), Math.round(y))) {
            return;
        }
        var lengths = [q.top.endX - q.top.startX, q.bottom.endX - q.bottom.startX, q.bottom.y - q.top.y + 1];
        var size = sum(lengths) / lengths.length;
        var score = scorePattern({ x: Math.round(x), y: Math.round(y) }, [1, 1, 3, 1, 1], matrix);
        return { score: score, x: x, y: y, size: size };
    })
        .filter(function (q) { return !!q; }) // Filter out any rejected quads from above
        .sort(function (a, b) { return a.score - b.score; })
        // Now take the top finder pattern options and try to find 2 other options with a similar size.
        .map(function (point, i, finderPatterns) {
        if (i > MAX_FINDERPATTERNS_TO_SEARCH) {
            return null;
        }
        var otherPoints = finderPatterns
            .filter(function (p, ii) { return i !== ii; })
            .map(function (p) { return ({ x: p.x, y: p.y, score: p.score + (Math.pow((p.size - point.size), 2)) / point.size, size: p.size }); })
            .sort(function (a, b) { return a.score - b.score; });
        if (otherPoints.length < 2) {
            return null;
        }
        var score = point.score + otherPoints[0].score + otherPoints[1].score;
        return { points: [point].concat(otherPoints.slice(0, 2)), score: score };
    })
        .filter(function (q) { return !!q; }) // Filter out any rejected finder patterns from above
        .sort(function (a, b) { return a.score - b.score; });
    if (finderPatternGroups.length === 0) {
        return null;
    }
    var _a = reorderFinderPatterns(finderPatternGroups[0].points[0], finderPatternGroups[0].points[1], finderPatternGroups[0].points[2]), topRight = _a.topRight, topLeft = _a.topLeft, bottomLeft = _a.bottomLeft;
    var alignment = findAlignmentPattern(matrix, alignmentPatternQuads, topRight, topLeft, bottomLeft);
    var result = [];
    if (alignment) {
        result.push({
            alignmentPattern: { x: alignment.alignmentPattern.x, y: alignment.alignmentPattern.y },
            bottomLeft: { x: bottomLeft.x, y: bottomLeft.y },
            dimension: alignment.dimension,
            topLeft: { x: topLeft.x, y: topLeft.y },
            topRight: { x: topRight.x, y: topRight.y },
        });
    }
    // We normally use the center of the quads as the location of the tracking points, which is optimal for most cases and will account
    // for a skew in the image. However, In some cases, a slight skew might not be real and instead be caused by image compression
    // errors and/or low resolution. For those cases, we'd be better off centering the point exactly in the middle of the black area. We
    // compute and return the location data for the naively centered points as it is little additional work and allows for multiple
    // attempts at decoding harder images.
    var midTopRight = recenterLocation(matrix, topRight);
    var midTopLeft = recenterLocation(matrix, topLeft);
    var midBottomLeft = recenterLocation(matrix, bottomLeft);
    var centeredAlignment = findAlignmentPattern(matrix, alignmentPatternQuads, midTopRight, midTopLeft, midBottomLeft);
    if (centeredAlignment) {
        result.push({
            alignmentPattern: { x: centeredAlignment.alignmentPattern.x, y: centeredAlignment.alignmentPattern.y },
            bottomLeft: { x: midBottomLeft.x, y: midBottomLeft.y },
            topLeft: { x: midTopLeft.x, y: midTopLeft.y },
            topRight: { x: midTopRight.x, y: midTopRight.y },
            dimension: centeredAlignment.dimension,
        });
    }
    if (result.length === 0) {
        return null;
    }
    return result;
}
exports.locate = locate;
function findAlignmentPattern(matrix, alignmentPatternQuads, topRight, topLeft, bottomLeft) {
    var _a;
    // Now that we've found the three finder patterns we can determine the blockSize and the size of the QR code.
    // We'll use these to help find the alignment pattern but also later when we do the extraction.
    var dimension;
    var moduleSize;
    try {
        (_a = computeDimension(topLeft, topRight, bottomLeft, matrix), dimension = _a.dimension, moduleSize = _a.moduleSize);
    }
    catch (e) {
        return null;
    }
    // Now find the alignment pattern
    var bottomRightFinderPattern = {
        x: topRight.x - topLeft.x + bottomLeft.x,
        y: topRight.y - topLeft.y + bottomLeft.y,
    };
    var modulesBetweenFinderPatterns = ((distance(topLeft, bottomLeft) + distance(topLeft, topRight)) / 2 / moduleSize);
    var correctionToTopLeft = 1 - (3 / modulesBetweenFinderPatterns);
    var expectedAlignmentPattern = {
        x: topLeft.x + correctionToTopLeft * (bottomRightFinderPattern.x - topLeft.x),
        y: topLeft.y + correctionToTopLeft * (bottomRightFinderPattern.y - topLeft.y),
    };
    var alignmentPatterns = alignmentPatternQuads
        .map(function (q) {
        var x = (q.top.startX + q.top.endX + q.bottom.startX + q.bottom.endX) / 4;
        var y = (q.top.y + q.bottom.y + 1) / 2;
        if (!matrix.get(Math.floor(x), Math.floor(y))) {
            return;
        }
        var lengths = [q.top.endX - q.top.startX, q.bottom.endX - q.bottom.startX, (q.bottom.y - q.top.y + 1)];
        var size = sum(lengths) / lengths.length;
        var sizeScore = scorePattern({ x: Math.floor(x), y: Math.floor(y) }, [1, 1, 1], matrix);
        var score = sizeScore + distance({ x: x, y: y }, expectedAlignmentPattern);
        return { x: x, y: y, score: score };
    })
        .filter(function (v) { return !!v; })
        .sort(function (a, b) { return a.score - b.score; });
    // If there are less than 15 modules between finder patterns it's a version 1 QR code and as such has no alignmemnt pattern
    // so we can only use our best guess.
    var alignmentPattern = modulesBetweenFinderPatterns >= 15 && alignmentPatterns.length ? alignmentPatterns[0] : expectedAlignmentPattern;
    return { alignmentPattern: alignmentPattern, dimension: dimension };
}


/***/ })
/******/ ])["default"];
});

/***/ }),

/***/ "./node_modules/node-gost-crypto/index.js":
/*!************************************************!*\
  !*** ./node_modules/node-gost-crypto/index.js ***!
  \************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

module.exports = __webpack_require__(/*! ./lib */ "./node_modules/node-gost-crypto/lib/index.js");


/***/ }),

/***/ "./node_modules/node-gost-crypto/lib/gostASN1.js":
/*!*******************************************************!*\
  !*** ./node_modules/node-gost-crypto/lib/gostASN1.js ***!
  \*******************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

/**
 * @file PKCS ASN.1 message syntax and converters
 * @version 1.76
 * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *    
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice, this 
 *    list of conditions and the following disclaimer.
 *    
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *    
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

const gostCrypto = __webpack_require__(/*! ./gostCrypto */ "./node_modules/node-gost-crypto/lib/gostCrypto.js");

    /*
     * Service functions
     * 
     */

    var root = __webpack_require__.g;
    var CryptoOperationData = root.ArrayBuffer;
    var Date = root.Date;

    // Security parameters
    var algorithms = gostCrypto.security.algorithms;

    var names = gostCrypto.security.names;

    var identifiers = gostCrypto.security.identifiers;

    var attributes = gostCrypto.security.attributes;

    var parameters = gostCrypto.security.parameters;

    // BER coding
    var BER = gostCrypto.coding.BER;

    // PEM coding
    var PEM = gostCrypto.coding.PEM;

    // Chars coding
    var Chars = gostCrypto.coding.Chars;

    // Hex coding;
    var Hex = gostCrypto.coding.Hex;

    // Hex coding;
    var Int16 = gostCrypto.coding.Int16;

    // Expand javascript object
    function expand() {
        var r = {};
        for (var i = 0, n = arguments.length; i < n; i++) {
            var item = arguments[i];
            if (typeof item === 'object')
                for (var name in item)
                    r[name] = item[name];
        }
        return r;
    }

    // Swap bytes in buffer
    function swapBytes(src) {
        if (src instanceof CryptoOperationData)
            src = new Uint8Array(src);
        var dst = new Uint8Array(src.length);
        for (var i = 0, n = src.length; i < n; i++)
            dst[n - i - 1] = src[i];
        return dst.buffer;
    }

    function isBinary(value) {
        return value instanceof CryptoOperationData || value.buffer instanceof CryptoOperationData;
    }

    // Left pad zero
    function lpad(n, width) {
        return n.length >= width ? n : new Array(width - n.length + 1).join('0') + n;
    }

    // Nearest power 2
    function npw2(n) {
        return n <= 2 ? n : n <= 4 ? 4 : n <= 8 ? 8 : n <= 16 ? 16 :
                n <= 32 ? 32 : n <= 64 ? 64 : n <= 128 ? 128 : n <= 256 ? 256 :
                n < 512 ? 512 : n < 1024 ? 1024 : undefined;
    }

    // String int encode/decode to buffer
    var SInt = {
        encode: function (value, endian) {
            return '0x' + Hex.encode(value, endian);
        },
        decode: function (value, endian, len) {
            if (typeof value === 'number')
                value = value.toString(16);
            var s = value.replace('0x', '');
            len = len || npw2(s.length);
            return Hex.decode(lpad(s, len), endian);
        }
    };

    // Assert invalid message
    function assert(value) {
        if (value)
            throw Error('Invalid format');
    }

    function defineProperty(object, name, descriptor, enumerable) {
        if (typeof descriptor !== 'object')
            descriptor = {value: descriptor};
        if (enumerable !== undefined)
            descriptor.enumerable = enumerable;
        Object.defineProperty(object, name, descriptor);
    }

    function defineProperties(object, properties, enumerable) {
        for (var name in properties)
            defineProperty(object, name, properties[name], enumerable);
    }

    function getOwnPropertyDescriptor(object, name) {
        return  Object.getOwnPropertyDescriptor(object, name);
    }



    /*
     * Base ASN.1 types and definitions
     * 
     */

    // Encode object primitive
    function encode(format, object, tagNumber, tagClass, tagConstructed, uniformTitle) {
        assert(object === undefined);
        var source = {
            tagNumber: tagNumber,
            tagClass: tagClass || 0x00,
            tagConstructed: tagConstructed || false,
            object: object
        };
        // Output format
        format = format || 'DER';
        if (format === 'DER' || format === 'CER')
            source = BER.encode(source, format);
        if (format === 'PEM')
            source = PEM.encode(source, uniformTitle);
        return source;
    }

    // Decode object primitive
    function decode(source, tagNumber, tagClass, tagConstructed, uniformTitle) {
        assert(source === undefined);

        // Decode PEM
        if (typeof source === 'string')
            source = PEM.decode(source, uniformTitle, false);
        // Decode binary data
        if (source instanceof CryptoOperationData) {
            try {
                source = PEM.decode(Chars.encode(source), uniformTitle, true);
            } catch (e) {
                source = BER.decode(source);
            }
        }

        tagClass = tagClass || 0;
        tagConstructed = tagConstructed || false;
        // Restore context implicit formats
        if (source.tagNumber === undefined) {
            source = encode(true, source.object, tagNumber, tagClass,
                    source.object instanceof Array);
            source = BER.decode(source);
        }

        // Check format
        assert(source.tagClass !== tagClass ||
                source.tagNumber !== tagNumber ||
                source.tagConstructed !== tagConstructed);
        // Clone value define from redefine original
        if (tagClass === 0 && tagNumber === 0x05)
            return null;
        else
            return source.object;
    }

    // Create class based on super
    function extend(Super, Class, propertiesObject, propertiesClass) {
        // If constructor not defined
        if (typeof Class !== 'function') {
            propertiesClass = propertiesObject;
            propertiesObject = Class;
            Class = function () {
                Super.apply(this, arguments);
            };
        }
        // Create prototype properties
        Class.prototype = Object.create(Super.prototype, {
            constructor: {
                value: Class
            },
            superclass: {
                value: Super.prototype
            }
        });
        if (propertiesObject)
            defineProperties(Class.prototype, propertiesObject);
        // Inherites super class properties
        if (Super !== Object)
            for (var name in Super)
                Class[name] = Super[name];
        Class.super = Super;
        if (propertiesClass)
            defineProperties(Class, propertiesClass, true);
        return Class;
    }

    // Base class 
    var ASN1Object = extend(Object, function (object) {
        this.object = object;
    }, {
        // Call set method for a class property
        _set: function (Class, propName, value) {
            Class.property(propName).set.call(this, value);
        },
        // Call get method for a class property
        _get: function (Class, propName) {
            return Class.property(propName).get.call(this);
        },
        // Call method for a class
        _call: function (Class, methodName, args) {
            return Class.method(methodName).apply(this, args);
        },
        hasProperty: function (propName) {
            return this.hasOwnProperty(propName) ||
                    !!this.constructor.property(propName);
        },
        encode: function () {
            return this.object;
        }
    }, {
        decode: function (source) {
            return new this(source);
        },
        // Find ingerited property
        property: function (propName) {
            var proto = this.prototype;
            while (proto) {
                var descriptor = getOwnPropertyDescriptor(proto, propName);
                if (descriptor)
                    return descriptor;
                else
                    proto = proto.superclass;
            }
        },
        // Find method 
        method: function (methodName) {
            var proto = this.prototype;
            while (proto) {
                if (proto[methodName])
                    return proto[methodName];
                else
                    proto = proto.superclass;
            }
        }
    });

    // Primitive metaclass
    var PRIMITIVE = function (tagNumber) {
        return extend(ASN1Object, {
            encode: function (format) {
                return encode(format, this.object, tagNumber);
            }
        }, {
            decode: function (source) {
                return new this(decode(source, tagNumber));
            }
        });
    };

    var ANY = ASN1Object;

    var BOOLEAN = PRIMITIVE(0x01);

    var IA5String = PRIMITIVE(0x16);

    var NumericString = PRIMITIVE(0x12);

    var PrintableString = PRIMITIVE(0x13);

    var TeletexString = PRIMITIVE(0x14);

    var UTF8String = PRIMITIVE(0x0c);

    var UTCTime = PRIMITIVE(0x17);

    var GeneralizedTime = PRIMITIVE(0x18);

    var UniversalString = PRIMITIVE(0x1C);

    var BMPString = PRIMITIVE(0x1e);

    var NULL = extend(PRIMITIVE(0x05), {
        object: {
            get: function () {
                return null;
            },
            set: function (object) {
                assert(object !== null);
            }
        }
    });

// Primitive class with value coding
    var PRIMITIVE_CODE = function (tagNumber) {

        // Base class primitive
        var Class = extend(PRIMITIVE(tagNumber), function (object) {
            if (this instanceof Class)
                Class.super.apply(this, arguments);
            else
                return CODE(object);
        });

        // Create Class with encoded
        function CODE(structure) {
            // Structured class
            return extend(PRIMITIVE(tagNumber), function (object) {
                Class.super.call(this, object);
            }, {
                // Transformation to code values
                encode: function (format) {
                    return encode(format, structure[this.object], tagNumber);
                }
            }, {
                decode: function (source) {
                    var id = decode(source, tagNumber);
                    for (var name in structure)
                        if (id === structure[name])
                            return new this(name);
                    assert(true);
                }
            });
        }
        return Class;
    };

    var INTEGER = PRIMITIVE_CODE(0x02);

    var ENUMERATED = PRIMITIVE_CODE(0x0a);

    var OCTET_STRING = (function () {
        // Base class primitive
        var Class = extend(PRIMITIVE(0x04), function (object) {
            if (this instanceof Class)
                Class.super.apply(this, arguments);
            else
                return WRAPPING(object);
        });
        // Wrapping class
        function WRAPPING(WrappedClass) {
            if (WrappedClass) {
                return extend(WrappedClass, {
                    encode: function (format) {
                        return encode(format, WrappedClass.method('encode').call(this, true), 0x04);
                    }
                }, {
                    decode: function (source) {
                        return WrappedClass.decode.call(this, decode(source, 0x04));
                    }
                });
            } else
                return Class;
        }
        return Class;
    })();

    var BIT_STRING = (function () {
        // Base class primitive
        var Class = extend(PRIMITIVE(0x03), function (object) {
            if (this instanceof Class)
                Class.super.apply(this, arguments);
            else if (typeof object === 'object')
                return MASK(object);
            else
                return WRAPPING(object);
        });

        // Wrapping class
        function WRAPPING(WrappedClass) {
            if (WrappedClass) {
                return extend(WrappedClass, {
                    encode: function (format) {
                        return encode(format, WrappedClass.method('encode').call(this, true), 0x03);
                    }
                }, {
                    decode: function (source) {
                        return WrappedClass.decode.call(this, decode(source, 0x03));
                    }
                });
            } else
                return Class;
        }

        // Create new class for a mask
        function MASK(structure) {
            // Bit string masked class
            return extend(ASN1Object, function (object, numbits) {
                ASN1Object.call(this, object);
                this.numbits = numbits || 0;
            }, {
                encode: function (format) {
                    var object = this.object, data = [];
                    if (object instanceof Array) {
                        for (var i = 0, n = object.length; i < n; i++) {
                            var j = structure[object[i]];
                            if (j !== undefined)
                                data[j] = '1';
                        }
                        for (var i = 0, n = Math.max(data.length, this.numbits); i < n; i++)
                            if (!data[i])
                                data[i] = '0';
                        data = data.join('');
                    } else
                        data = '0';
                    return encode(format, data, 0x03);
                }
            }, {
                // Transformation to array of values
                decode: function (source) {
                    var data = decode(source, 0x03), object = [];
                    for (var name in structure) {
                        var i = structure[name];
                        if (data.charAt(i) === '1')
                            object.push(name);
                    }
                    return new this(object, data.length);
                }
            });
        }

        return Class;
    })();

    // Combine sequence object properties with owner object
    var COMBINE = function (Class) {
        Class.combine = function (owner, valueName) {
            for (var name in Class.prototype) {
                if (Class.prototype.hasOwnProperty(name) && !owner.hasProperty(name)) {
                    defineProperty(owner, name, (function (name) {
                        return {
                            get: function () {
                                // Get object property
                                return this[valueName] && this[valueName][name];
                            },
                            set: function (object) {
                                // Set object property
                                if (!this[valueName])
                                    this[valueName] = {};
                                this[valueName][name] = object;
                            },
                            configurable: false,
                            enumerable: true
                        };
                    })(name));
                }
            }
        };
        return Class;
    };

    var SEQUENCE = function (structure, uniformTitle) {

        /**
         * Create SEQUENCE ASN.1 metaclass
         * 
         * @class GostASN1.Sequence
         * @param {(Object|FormatedData)} object Initialization object
         * @param {boolean} check Check structure after initialization
         */
        var Class = extend(ASN1Object, function (object, check) {
            // Define hidden properties
            defineProperty(this, 'items', {
                writable: true,
                value: {}
            });
            if (typeof object === 'string' || object instanceof CryptoOperationData)
                this.decode(object);
            else if (object !== undefined) {
                this.object = object;
                // Check structure
                if (check)
                    this.check();
            }
        }, {
            object: {
                get: function () {
                    return this;
                },
                set: function (object) {
                    if (object instanceof Class) {
                        // Set the same sequence class
                        this.items = object.items;
                        for (var name in structure) {
                            var ItemClass = this.getItemClass(name, this.items);
                            if (ItemClass.combine)
                                ItemClass.combine(this, name);
                        }
                    } else {
                        // Set other object structure
                        var data = {};
                        for (var name in structure) {
                            var item = object[name];
                            var ItemClass = this.getItemClass(name, data);
                            if (item !== undefined) {
                                data[name] = new ItemClass(item);
                            } else if (ItemClass.combine) {
                                // Create combined object
                                data[name] = new ItemClass(object);
                            }
                            if (ItemClass.combine)
                                ItemClass.combine(this, name);
                        }
                        this.items = data;
                    }
                }
            },
            getItemClass: function (name, items) {
                return structure[name];
            },
            /**
             * Encode the object
             * 
             * @memberOf GostASN1.Sequence
             * @instance
             * @param {string} format Encoding format 'DER', 'CER' or 'PEM'
             * @returns {FormatedData} 
             */
            encode: function (format) {
                var source = [], items = this.items;
                // Encode objects in structure
                for (var name in structure) {
                    // console.log(name, 'encoding...', items[name]);
                    if (items[name]) {
                        var encoded = items[name].encode(true);// Source from object
                        if (encoded !== undefined) // Can be optional
                            source.push(encoded);

                    }
                }
                return encode(format, source, 0x10, 0, true, uniformTitle);
            },
            /**
             * Decode the source to self object
             * 
             * @memberOf GostASN1.Sequence
             * @instance
             * @param {FormatedData} source Encoded data
             */
            decode: function (source) {
                this.object = this.constructor.decode(source);
            },
            /**
             * Check the object structure
             * 
             * @memberOf GostASN1.Sequence
             * @instance
             */
            check: function () {
                this.constructor.decode(this.encode(true));
            }
        }, {
            /**
             * Encode data values with creating object
             * 
             * @memberOf GostASN1.Sequence
             * @static
             * @param {Object} object Javascript object to encoding
             * @param {string} format Encoding format 'DER', 'CER' or 'PEM'
             * @returns {FormatedData} 
             */
            encode: function (object, format) {
                return new this(object).encode(format);
            },
            /**
             * Decode source and create object
             * 
             * @memberOf GostASN1.Sequence
             * @static
             * @param {FormatedData} source Encoded data
             * @returns {GostASN1.Sequence}
             * 
             */
            decode: function (source) {
                // Decode structure
                source = decode(source, 0x10, 0, true, uniformTitle);
                var i = 0, result = new this(), data = result.items = {};
                for (var name in structure) {
                    // console.log(name, 'decoding...');
                    // try to create and decode object
                    var ItemClass = result.getItemClass(name, data);
                    var item = ItemClass.decode(source[i]);
                    // success? item can be optional
                    if (item !== undefined) {
                        data[name] = item;
                        if (ItemClass.combine)
                            ItemClass.combine(result, name);
                        i++;
                    }
                }
                return result;
            }
        });

        // Append structure items
        for (var name in structure) {
            defineProperty(Class.prototype, name, (function (name) {
                return {
                    get: function () {
                        // Get object property
                        return this.items[name] && this.items[name].object;
                    },
                    set: function (object) {
                        // Set object property
                        if (object !== undefined) {
                            var ItemClass = this.getItemClass(name, this.items);
                            this.items[name] = new ItemClass(object);
                        } else
                            delete this.items[name];
                    },
                    configurable: false,
                    enumerable: !structure[name].combine
                };
            })(name));
            if (structure[name].combine)
                structure[name].combine(Class.prototype, name);
        }
        return Class;
    };

    var ATTRIBUTE = function (structure, typeName, valueName, ownerDafaultType, uniformName) {

        var BaseClass = SEQUENCE(structure, uniformName);

        // Define attribute sequence
        var DEFINE = function (typeSet, defaultType) {

            typeName = typeName || 'type';
            valueName = valueName || 'value';
            defaultType = defaultType || ownerDafaultType || ANY;

            var Class = extend(BaseClass, function (object) {
                // Constructor - "matrioshka"
                if (this instanceof Class) {
                    // Call super
                    BaseClass.apply(this, arguments);
                } else
                    return DEFINE.apply(this, arguments);
            }, {
                getItemClass: function (name, items) {
                    var ItemClass = structure[name];
                    if (valueName === name) {
                        // Define type of value attribute based on type attribute
                        var type, typeId = items && items[typeName];
                        if (typeId) {
                            var id = typeId.object;
                            if (typeSet) {
                                if (typeof typeSet === 'function')
                                    type = typeSet(id);
                                else
                                    type = typeSet[id];
                            }
                        }
                        type = type || defaultType || ANY;
                        ItemClass = ItemClass === ANY ? type :
                                ItemClass(type);
                    }
                    return ItemClass;
                }
            });

            // Redefine type property
            defineProperty(Class.prototype, typeName, {
                get: function () {
                    // Get value property of object
                    return this.items[typeName] && this.items[typeName].object;
                },
                set: function () {
                    // Can't set type definition property separatery
                    assert(true);
                },
                configurable: false,
                enumerable: true
            });

            return Class;
        };

        return DEFINE();
    };


    var OBJECT_IDENTIFIER = extend(ASN1Object, {
        encode: function (format) {
            var object = this.object;
            object = /^(\d+\.)+\d+$/.test(object) ? object : identifiers[object];
            assert(!object);
            return encode(format, object, 0x06);
        }
    }, {
        decode: function (source) {
            var object = decode(source, 0x06);
            return new this(names[object] || object);
        }
    });

    var IMPLICIT = function (Class) {
        Class = Class || ANY;
        // Add constracted tag
        return extend(Class, {
            encode: function (format) {
                // Format encoding without CTX header
                var source = Class.method('encode').call(this, format);
                if (typeof source === 'string' || source instanceof CryptoOperationData)
                    return source;
                if (source.tagNumber !== 0x04 && source.tagClass === 0 &&
                        !(source.object instanceof Array))
                    // Encode primitive source
                    return {object: BER.encode(source, 'DER', true)};
                else
                    return {object: source.object};
            }
        }, {
            decode: function (source) {
                if (typeof source === 'string' || source instanceof CryptoOperationData) {
                    return Class.decode.call(this, source);
                } else {
                    source = {
                        object: source.object,
                        header: source.header,
                        content: source.content
                    };
                    return Class.decode.call(this, source);
                }
            }
        });
    };

    var EXPLICIT = function (Class) {
        Class = Class || ANY;
        // Add constracted tag
        return extend(Class, {
            encode: function (format) {
                // Format encoding without CTX header
                var source = Class.method('encode').call(this, format);
                if (typeof source === 'string' || source instanceof CryptoOperationData)
                    return source;
                return {object: [source]};
            }
        }, {
            decode: function (source) {
                if (typeof source === 'string' || source instanceof CryptoOperationData) {
                    return Class.decode.call(this, source);
                } else
                    return Class.decode.call(this, source.object[0]);
            }
        });
    };

    var CTX = function (number, ContentClass) {
        function CTX() {
            ContentClass.apply(this, arguments);
        }
        // Create CTX number class with wrapped content class
        return extend(ContentClass, CTX, {
            encode: function (format) {
                var source = ContentClass.method('encode').call(this, format);
                if (typeof source === 'string' || source instanceof CryptoOperationData)
                    return source;
                source.tagNumber = number;
                source.tagClass = 0x02;
                source.tagConstructed = source.object instanceof Array;
                return source;
            }
        }, {
            decode: function (source) {
                // Format decoding without CTX
                assert(source.tagNumber !== undefined &&
                        (source.tagClass !== 0x02 || source.tagNumber !== number));
                return ContentClass.decode.call(this, source);
            }
        });
    };

    var ARRAY_OF = function (tagNumber) {

        return function (ItemClassDef, typeAndValue) {
            // Difininition of item class
            ItemClassDef = ItemClassDef || ANY;

            // Metaclass definition 
            var DEFINE = function (typeSet, defaultType) {

                // Define item class
                var ItemClass = typeof ItemClassDef === 'function' &&
                        typeSet !== undefined ?
                        ItemClassDef(typeSet, defaultType) : ItemClassDef;

                if (typeAndValue) {
                    /**
                     * Create class with type and value structure<br><br>
                     * 
                     * SET OF attribute and SEQUENCE OF attribute metaclass
                     * 
                     * @class GostASN1.Set
                     * @param {Object} object object value
                     */
                    var Class = extend(ASN1Object, function (object) {
                        // Constructor - "matrioshka"
                        if (this instanceof Class) {
                            // Define hidden items property
                            defineProperty(this, 'items', {
                                writable: true,
                                value: {}
                            });
                            // Call super
                            ASN1Object.call(this, object || {});
                        } else
                            return DEFINE.apply(this, arguments);
                    }, {
                        object: {
                            get: function () {
                                // refresh items from object properties
                                this.read();
                                return this;
                            },
                            set: function (object) {
                                if (object instanceof Class) {
                                    object.read();
                                    this.items = object.items;
                                } else {
                                    // Set other object structure
                                    var data = {};
                                    for (var id in object) {
                                        var item = object[id];
                                        data[id] = this.createItem(item, id);
                                    }
                                    this.items = data;
                                }
                                // refresh object properties to items
                                this.reset();
                            }
                        },
                        createItem: function (value, type) {
                            if (typeAndValue) {
                                var object = {};
                                object[typeAndValue.typeName] = type;
                                object[typeAndValue.valueName] = value;
                            } else
                                object = value;
                            return new ItemClass(object);
                        },
                        getItemValue: function (id) {
                            var item = this.items[id];
                            return typeAndValue ? item.object[typeAndValue.valueName] : item.object;
                        },
                        setItemValue: function (id, value) {
                            var item = this.items[id];
                            if (typeAndValue)
                                item.object[typeAndValue.valueName] = value;
                            else
                                item.object = value;
                        },
                        isItemType: function (id) {
                            return typeAndValue ? identifiers[id] : !isNaN(parseInt(id));
                        },
                        reset: function () {
                            // remove unused properties
                            var items = this.items;
                            for (var id in this)
                                if (this.hasOwnProperty(id) && !this.items[id] &&
                                        this.isItemType(id))
                                    delete this[id];
                            // add new properties
                            for (var id in items)
                                this[id] = this.getItemValue(id);
                        },
                        read: function () {
                            var items = this.items;
                            for (var id in this) {
                                if (this.isItemType(id)) {
                                    if (!this.items[id]) {
                                        items[id] = this.createItem(this[id], id);
                                        this[id] = this.getItemValue(id);
                                    } else if (this.getItemValue(id) !== this[id]) {
                                        this.setItemValue(id, this[id]);
                                    }
                                }
                            }
                        },
                        /**
                         * Encode the object
                         * 
                         * @memberOf GostASN1.Set
                         * @instance
                         * @param {string} format Encoding format 'DER', 'CER' or 'PEM'
                         * @returns {FormatedData} 
                         */
                        encode: function (format) {
                            // refresh items from object properties
                            this.read();
                            // repare source
                            var object = this.items, source = [];
                            for (var id in object) {
                                // console.log(id, object[id], 'encoding...');
                                var encoded = object[id].encode(true);
                                if (encoded !== undefined)
                                    source.push(encoded);
                            }
                            return encode(format, source, tagNumber, 0, true);
                        },
                        /**
                         * Decode the source to self object
                         * 
                         * @memberOf GostASN1.Set
                         * @instance
                         * @param {FormatedData} source Encoded data
                         */
                        decode: function (source) {
                            this.object = this.constructor.decode(source);
                        },
                        /**
                         * Check the object structure
                         * 
                         * @memberOf GostASN1.Set
                         * @instance
                         */
                        check: function () {
                            this.constructor.decode(this.encode(true));
                        }
                    }, {
                        /**
                         * Encode data values with creating object
                         * 
                         * @memberOf GostASN1.Set
                         * @static
                         * @param {Object} object Javascript object to encoding
                         * @param {string} format Encoding format 'DER', 'CER' or 'PEM'
                         * @returns {FormatedData} 
                         */
                        encode: function (object, format) {
                            return new this(object).encode(format);
                        },
                        /**
                         * Decode source and create object
                         * 
                         * @memberOf GostASN1.Set
                         * @static
                         * @param {FormatedData} source Encoded data
                         * @returns {GostASN1.Sequence}
                         * 
                         */
                        decode: function (source) {
                            // Decode structure
                            source = decode(source, tagNumber, 0, true);
                            var result = new this(), data = result.items = {};
                            for (var i = 0, n = source.length; i < n; i++) {
                                var item = ItemClass.decode(source[i]);
                                var id = typeAndValue ? item.object[typeAndValue.typeName] : i;
                                data[id] = item;
                            }
                            result.reset();
                            return result;
                        }
                    });

                    return Class;
                } else {
                    // Create array class
                    var ArrayClass = extend(ASN1Object, function (object) {
                        // Constructor - "matrioshka"
                        if (this instanceof ArrayClass) {
                            // Define hidden items property
                            defineProperties(this, {
                                items: {
                                    writable: true,
                                    value: []
                                },
                                values: {
                                    writable: true,
                                    value: []
                                }
                            });
                            // Call super
                            ASN1Object.call(this, object || []);
                        } else
                            return DEFINE.apply(this, arguments);
                    }, {
                        object: {
                            get: function () {
                                // refresh items from object properties
                                this.read();
                                return this.values;
                            },
                            set: function (object) {
                                if (object instanceof ArrayClass) {
                                    object.read();
                                    this.items = object.items;
                                } else {
                                    // Set other object structure
                                    var data = [];
                                    for (var i = 0, n = object.length; i < n; i++)
                                        data[i] = new ItemClass(object[i]);
                                    this.items = data;
                                }
                                // refresh object properties to items
                                this.reset();
                            }
                        },
                        encode: function (format) {
                            // refresh items from object properties
                            this.read();
                            // repare source
                            var data = this.items, source = [];
                            for (var i = 0, n = data.length; i < n; i++) {
                                var encoded = data[i].encode(true);
                                if (encoded !== undefined)
                                    source.push(encoded);
                            }
                            return encode(format, source, tagNumber, 0, true);
                        },
                        decode: function (source) {
                            this.object = this.constructor.decode(source);
                        },
                        check: function () {
                            this.constructor.decode(this.encode(true));
                        },
                        reset: function () {
                            // remove unused properties
                            for (var i = 0, n = this.items.length; i < n; i++)
                                this.values.push(this.items[i].object);
                        },
                        read: function () {
                            var items = this.items, values = this.values;
                            for (var i = 0, n = values.length; i < n; i++) {
                                if (!this.items[i]) {
                                    items[i] = new ItemClass(values[i]);
                                    values[i] = items[i].object;
                                } else if (items[i].object !== values[i])
                                    items[i].object = values[i];
                            }
                        }
                    }, {
                        encode: function (object, format) {
                            return new this(object).encode(format);
                        },
                        decode: function (source) {
                            source = decode(source, tagNumber, 0, true);
                            var result = new this();
                            result.items = [];
                            for (var i = 0, n = source.length; i < n; i++)
                                result.items.push(ItemClass.decode(source[i]));
                            result.reset();
                            return result;
                        }
                    });

                    return ArrayClass;
                }
            };
            return DEFINE(); // Create simple class w/o any parameters
        };
    };

    var SEQUENCE_OF = ARRAY_OF(0x10);

    var SET_OF = ARRAY_OF(0x11);

    var ENCLOSURE = function (BaseClass, modifier) {
        if (modifier) {
            var Class = extend(ASN1Object, {
                object: {
                    get: function () {
                        if (this.item)
                            return modifier.decode(this.item.object);
                        else
                            return undefined;
                    },
                    set: function (object) {
                        if (object !== undefined)
                            this.item = new BaseClass(modifier.encode(object));
                        else
                            delete this.item;
                    }
                },
                encode: function (format) {
                    return this.item.encode(format);
                }
            }, {
                decode: function (source) {
                    var result = new this();
                    result.item = BaseClass.decode(source);
                    return result;
                }
            });
            for (var name in BaseClass)
                if (!Class[name])
                    Class[name] = BaseClass[name];
            return Class;
        } else
            return BaseClass;
    };

    var SET_OF_SINGLE = function (ItemClass) {

        var Class = ENCLOSURE(SET_OF(ItemClass), {
            encode: function (item) {
                return [item];
            },
            decode: function (item) {
                return item[0];
            }
        });
        return Class;
    };

    var CHOICE = function (structure, define) {

        return extend(ASN1Object, {
            object: {
                get: function () {
                    return this.item && this.item.object;
                },
                set: function (object) {
                    // Try to find appropriate type in structure
                    if (object instanceof ASN1Object) {
                        for (var name in structure)
                            if (object instanceof structure[name]) {
                                this.item = object;
                                return;
                            }
                    }
                    // Define class
                    var name = typeof define === 'function' ? define(object) : define;
                    assert(!name || !structure[name]);
                    object = new structure[name](object);
                    this.item = object;
                }
            },
            encode: function (format) {
                // Already in class
                return this.item.encode(format);
            }
        }, {
            decode: function (source) {
                // Try to find class structure
                for (var name in structure) {
                    try {
                        var item = structure[name].decode(source);
                        if (item !== undefined)
                            return new this(item);
                    } catch (e) {
                    }
                }
                assert(true);
            }
        });
    };

    var ENCAPSULATES = function (WrappedClass) {
        WrappedClass = WrappedClass || ANY;
        // BER Encode/Decode values
        return extend(WrappedClass, {
            encode: function () {
                return BER.encode(WrappedClass.method('encode').call(this, true));
            }
        }, {
            encode: function (object, format) {
                return new this(object).encode(format);
            },
            decode: function (source) {
                return WrappedClass.decode.call(this, BER.decode(source));
            }
        });
    };

    var DEFAULT = function (Class, optional) {
        Class = Class || ANY;
        return extend(Class, {
            encode: function (format) {
                if (this.object === optional)
                    return undefined;
                return Class.method('encode').call(this, format);
            }
        }, {
            decode: function (source) {
                if (source === undefined)
                    return new this(optional);
                else
                    try {
                        return Class.decode.call(this, source);
                    } catch (e) {
                        return undefined;
                    }
            }
        });
    };

    var OPTIONAL = function (Class) {
        Class = Class || ANY;
        return extend(Class, {}, {
            decode: function (source) {
                if (source === undefined)
                    return undefined;
                else
                    try {
                        return Class.decode.call(this, source);
                    } catch (e) {
                        return undefined;
                    }
            }
        });
    };

    var DEFAULT_NULL = function (Class, optional) {
        Class = Class || ANY;
        return extend(Class, {
            encode: function (format) {
                if (this.object === optional)
                    return new NULL(null).encode(format);
                return Class.method('encode').call(this, format);
            }
        }, {
            decode: function (source) {
                if (source === undefined)
                    return undefined;
                else if (source === null ||
                        (source.tagNumber === 0x05 && source.tagClass === 0))
                    return new this(optional);
                else
                    try {
                        return Class.decode.call(this, source);
                    } catch (e) {
                        return undefined;
                    }
            }
        });
    };



    /*
     * Certificate Version, Name, Attributes, Validity
     * 
     * http://tools.ietf.org/html/rfc5280
     * 
     */

    var DirectoryString = CHOICE({
        teletexString: TeletexString,
        printableString: PrintableString,
        universalString: UniversalString,
        utf8String: UTF8String,
        bmpString: BMPString,
        numericString: NumericString
    }, function (value) {
        // PrintableString - for characters and symbols with no spaces, overrise UTF8String
        return /^[A-Za-z0-9\.@\+\-\:\=\\\/\?\!\#\$\%\^\&\*\(\)\[\]\{\}\>\<\|\~]*$/.test(value) ? 'printableString' : 'utf8String';
    });

    var Time = CHOICE({
        utcTime: UTCTime,
        generalTime: GeneralizedTime
    }, function (value) {
        return value.getYear() >= 2050 ? 'generalTime' : 'utcTime';
    });

    // Attribute
    var AttributeType = OBJECT_IDENTIFIER;

    var AttributeValue = ANY;

    var AttributeTypeAndValue = ATTRIBUTE({
        type: AttributeType,
        value: AttributeValue
    });

    var typeAndValue = {
        typeName: 'type',
        valueName: 'value'
    };

    /**
     * X.501 type Name
     * The Name describes a hierarchical name composed of attributes, such
     * as country name, and corresponding values, such as US.  The type of
     * the component AttributeValue is determined by the AttributeType; in
     * general it will be a DirectoryString.
     
     * The DirectoryString type is defined as a choice of PrintableString,
     * TeletexString, BMPString, UTF8String, and UniversalString.  The
     * UTF8String encoding [RFC 2279] is the preferred encoding, and all
     * certificates issued after December 31, 2003 MUST use the UTF8String
     * encoding of DirectoryString.
     * 
     * Standard sets of attributes have been defined in the X.500 series of
     * specifications [X.520].  Implementations of this specification MUST
     * be prepared to receive the following standard attribute types in
     * issuer and subject (section 4.1.2.6) names:
     *  <ul>
     *      <li>country,</li>
     *      <li>organization,</li>
     *      <li>organizational-unit,</li>
     *      <li>distinguished name qualifier,</li>
     *      <li>state or province name,</li>
     *      <li>common name (e.g., "Susan Housley"), and</li>
     *      <li>serial number.</li>
     *  </ul>
     * In addition, implementations of this specification SHOULD be prepared
     * to receive the following standard attribute types in issuer and
     * subject names:
     *  <ul>
     *      <li>locality,</li>
     *      <li>title,</li>
     *      <li>surname,</li>
     *      <li>given name,</li>
     *      <li>initials,</li>
     *      <li>pseudonym, and</li>
     *      <li>generation qualifier (e.g., "Jr.", "3rd", or "IV").</li>
     *  </ul>
     The syntax for type Name:
     *  <pre>
     *  Name ::= CHOICE {
     *    rdnSequence RDNSequence }
     *
     *  RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
     *
     *  RelativeDistinguishedName ::=
     *    SET OF AttributeTypeAndValue
     *
     *  AttributeTypeAndValue ::= SEQUENCE {
     *    type     AttributeType,
     *    value    AttributeValue }
     *
     *  AttributeType ::= OBJECT IDENTIFIER
     *
     *  AttributeValue ::= ANY DEFINED BY AttributeType
     *
     *  DirectoryString ::= CHOICE {
     *        teletexString           TeletexString (SIZE (1..MAX)),
     *        printableString         PrintableString (SIZE (1..MAX)),
     *        universalString         UniversalString (SIZE (1..MAX)),
     *        utf8String              UTF8String (SIZE (1..MAX)),
     *        bmpString               BMPString (SIZE (1..MAX)) }
     *  </pre>
     * @class GostASN1.Name
     */
    var RelativeDistinguishedName = SET_OF_SINGLE(AttributeTypeAndValue({
        serialName: PrintableString,
        countryName: PrintableString,
        dnQualifier: PrintableString,
        emailAddress: IA5String,
        domainComponent: IA5String,
        SNILS: NumericString,
        OGRN: NumericString,
        INN: NumericString
    }, DirectoryString));

    var RDNSequence = SEQUENCE_OF(RelativeDistinguishedName, typeAndValue)();

    var Name = CHOICE({
        // only one possibility for now
        rdnSequence: RDNSequence}, 'rdnSequence');

    /**
     * Validity
     * @class GostASN1.Validity
     * @extends GostASN1.Sequence
     */
    var Validity = COMBINE(SEQUENCE({
        notBefore: Time,
        notAfter: Time}));

    var Version = INTEGER;

    var Attribute = ATTRIBUTE({
        type: OBJECT_IDENTIFIER,
        value: ANY
    });

    /**
     * Type and Value Attributes <br>
     * 
     * Suggested naming attributes: Definition of the following 
     * information object set may be augmented to meet local 
     * requirements.  Note that deleting members of the set may 
     * prevent interoperability with conforming implementations.
     * presented in pairs: the AttributeType followed by the type 
     * definition for the corresponding AttributeValue
     * 
     * @class GostASN1.Attributes
     * @extends GostASN1.Set
     */
    var Attributes = SET_OF(Attribute, typeAndValue);

    var AttributeSequence = SEQUENCE_OF(Attribute, typeAndValue);


    /*
     * Algorithm identifiers
     * 
     * http://tools.ietf.org/html/rfc3279
     * http://tools.ietf.org/html/rfc4357
     * http://tools.ietf.org/html/rfc2898
     * 
     */

    var FieldElement = INTEGER;
    var Curve = SEQUENCE({
        a: FieldElement,
        b: FieldElement,
        seed: OPTIONAL(BIT_STRING)});

    var ECPoint = OCTET_STRING(extend(ASN1Object, {
        encode: function () {
            var value = this.object;
            var len = Math.max(npw2(value.x.length - 2), npw2(value.y.length - 2)) / 2,
                    r = new Uint8Array(2 * len + 1);
            r[0] = 0x04;
            r.set(new Uint8Array(SInt.decode(value.x, false, len)), 1); // x
            r.set(new Uint8Array(SInt.decode(value.y, false, len)), len + 1); // y
            return r.buffer;
        }
    }, {
        decode: function (value) {
            var len = (value.byteLength - 1) / 2;
            return new this({
                x: SInt.encode(new Uint8Array(value, 1, len)),
                y: SInt.encode(new Uint8Array(value, len + 1, len))
            });
        }
    }));

    var FieldID = SEQUENCE({
        fieldType: OBJECT_IDENTIFIER,
        parameters: INTEGER});

    var ECParameters = SEQUENCE({
        version: Version, // version is always 1         
        fieldID: FieldID, // identifies the finite field over which the curve is defined 
        curve: Curve, // coefficients a and b of the elliptic curve         
        base: ECPoint, // specifies the base point P on the elliptic curve         
        order: INTEGER, // the order n of the base point         
        cofactor: OPTIONAL(INTEGER)}); // The integer h = #E(Fq)/n  

    var GostR3410Parameters = SEQUENCE({
        publicKeyParamSet: OBJECT_IDENTIFIER,
        digestParamSet: OBJECT_IDENTIFIER,
        encryptionParamSet: OPTIONAL(OBJECT_IDENTIFIER)});

    var GostR3411Parameters = DEFAULT_NULL(OBJECT_IDENTIFIER, 'id-GostR3411-94-CryptoProParamSet');

    var ECDHParameters = CHOICE({
        namedParameters: OBJECT_IDENTIFIER,
        ecParameters: ECParameters,
        implicitly: OPTIONAL(NULL)}, function (value) {
        return typeof value === 'string' || value instanceof String ?
                'namedParameters' : 'ecParameters';
    });

    var Algorithm = function (paramType, modifier) {
        return ENCLOSURE(SEQUENCE({
            algorithm: OBJECT_IDENTIFIER,
            parameters: OPTIONAL(paramType)}), modifier);
    };

    var AlgorithmIdentifier = (function () {

        var DefaultAlgorithm = Algorithm(ANY),
                Class = extend(ASN1Object, function (object) {
                    if (this instanceof Class)
                        Class.super.apply(this, arguments);
                    else
                        return DEFINE(object);
                }, {
                    encode: function (format) {
                        return new DefaultAlgorithm(this.object).encode(format);
                    }
                }, {
                    decode: function (source) {
                        return new this(DefaultAlgorithm.decode(source).object);
                    }
                });

        var DEFINE = function (algorithmSet) {

            return extend(ASN1Object, {
                object: {
                    get: function () {
                        if (this.item)
                            return this.item.object;
                        else
                            return undefined;
                    },
                    set: function (object) {
                        if (object) {
                            var ItemClass = algorithmSet[object.id];
                            if (!ItemClass)
                                throw new Error('Algorithm not supported');
                            this.item = new ItemClass(object);
                        } else
                            delete this.item;
                    }
                },
                encode: function (format) {
                    return this.item.encode(format);
                }
            }, {
                decode: function (source) {
                    // Decode PEM
                    if (typeof source === 'string')
                        source = PEM.decode(source, undefined, false);
                    // Decode binary data
                    if (source instanceof CryptoOperationData)
                        source = BER.decode(source);
                    var ItemClass = algorithmSet[names[source.object[0].object]];
                    if (ItemClass) {
                        var result = new this();
                        result.item = ItemClass.decode(source);
                        return result;
                    } else
                        throw new Error('Algorithm not supported');
                }
            });
        };

        return Class;
    })();

    var ECDHKeyAlgorithm = Algorithm(ECDHParameters, {
        encode: function (value) {
            var params;
            if (typeof value.namedCurve === 'string')
                params = attributes['namedCurve'][value.namedCurve];
            else
                params = {
                    version: 1,
                    fieldID: {
                        fieldType: 'id-prime-Field',
                        parameters: value.curve.p
                    },
                    curve: {
                        a: value.curve.a,
                        b: value.curve.b
                    },
                    base: {
                        x: value.curve.x,
                        y: value.curve.y
                    },
                    order: value.curve.q,
                    cofactor: 1
                };
            return {
                algorithm: value.id,
                parameters: params
            };
        },
        decode: function (value) {
            var params = value.parameters,
                    result = algorithms[value.algorithm];
            if (typeof params === 'string' || params instanceof String) {
                result = expand(result, parameters[params]);
            } else if (typeof params === 'object') {
                result = expand(result, {
                    curve: {
                        p: params.fieldID.parameters,
                        a: params.curve.a,
                        b: params.curve.b,
                        x: params.base.x,
                        y: params.base.y,
                        q: params.order
                    }
                });
            } else
                throw new DataError('Invalid key paramters');
            return result;
        }
    });

    var GostKeyAlgorithm = Algorithm(GostR3410Parameters, {
        encode: function (value) {
            var paramName = value.namedCurve ? 'namedCurve' : 'namedParam',
                    sBox = (value.name.indexOf('-94') >= 0 || value.name.indexOf('-2001') >= 0 ||
                            value.version === 1994 || value.version === 2001) ? value.sBox || 'D-A' :
                    (value.name.indexOf('-512') >= 0 || value.length === 512) ? 'D-512' : 'D-256';
            return {
                algorithm: value.id,
                parameters: {
                    publicKeyParamSet: attributes[paramName][value[paramName]],
                    digestParamSet: attributes['sBox'][sBox],
                    encryptionParamSet: value.encParams && value.encParams.sBox ?
                            attributes['sBox'][value.encParams.sBox] : undefined
                }
            };
        },
        decode: function (value) {
            var params = value.parameters,
                    algorithm = expand(algorithms[value.algorithm],
                            parameters[params.publicKeyParamSet],
                            parameters[params.digestParamSet]);
            if (params.encryptionParamSet)
                algorithm.encParams = parameters[params.encryptionParamSet];
            return algorithm;
        }
    });

    var AlgorithmWithNoParam = Algorithm(ANY, {
        encode: function (value) {
            return {algorithm: value.id};
        },
        decode: function (value) {
            return algorithms[value.algorithm];
        }
    });

    var AlgorithmWithNullParam = Algorithm(NULL, {
        encode: function (value) {
            return {
                algorithm: value.id,
                parameters: null
            };
        },
        decode: function (value) {
            return algorithms[value.algorithm];
        }
    });

    var Gost341194DigestAlgorithm = Algorithm(GostR3411Parameters, {
        encode: function (value) {
            return {
                algorithm: value.id,
                parameters: attributes['sBox'][value.sBox || (value.hash && value.hash.sBox) || 'D-A']
            };
        },
        decode: function (value) {
            var algorithm = expand(algorithms[value.algorithm]),
                    parameter = parameters[value.parameters];
            if (algorithm.hash)
                algorithm.hash = expand(algorithm.hash, parameter);
            else
                algorithm = expand(algorithm, parameter);
            return algorithm;
        }
    });

    var KeyAlgorithmIdentifier = AlgorithmIdentifier({
        ecdsa: ECDHKeyAlgorithm,
        noSignature: AlgorithmWithNullParam,
        rsaEncryption: AlgorithmWithNullParam,
        'id-sc-gostR3410-2001': ECDHKeyAlgorithm,
        'id-GostR3410-2001': GostKeyAlgorithm,
        'id-GostR3410-94': GostKeyAlgorithm,
        'id-GostR3410-2001DH': GostKeyAlgorithm,
        'id-GostR3410-94DH': GostKeyAlgorithm,
        'id-tc26-gost3410-12-256': GostKeyAlgorithm,
        'id-tc26-gost3410-12-512': GostKeyAlgorithm,
        'id-tc26-agreement-gost-3410-12-256': GostKeyAlgorithm,
        'id-tc26-agreement-gost-3410-12-512': GostKeyAlgorithm,
        'id-sc-gost28147-gfb': AlgorithmWithNoParam,
        'id-Gost28147-89': AlgorithmWithNoParam
    });

    var SignatureAlgorithmIdentifier = AlgorithmIdentifier({
        noSignature: AlgorithmWithNullParam,
        rsaEncryption: AlgorithmWithNullParam,
        sha1withRSAEncryption: AlgorithmWithNullParam,
        sha256withRSAEncryption: AlgorithmWithNullParam,
        sha384withRSAEncryption: AlgorithmWithNullParam,
        sha512withRSAEncryption: AlgorithmWithNullParam,
        'ecdsa': AlgorithmWithNoParam,
        'ecdsa-with-SHA1': AlgorithmWithNoParam,
        'ecdsa-with-SHA256': AlgorithmWithNoParam,
        'ecdsa-with-SHA384': AlgorithmWithNoParam,
        'ecdsa-with-SHA512': AlgorithmWithNoParam,
        'id-GostR3410-94': AlgorithmWithNullParam,
        'id-GostR3410-2001': AlgorithmWithNullParam,
        'id-GostR3411-94-with-GostR3410-2001': AlgorithmWithNoParam,
        'id-GostR3411-94-with-GostR3410-94': AlgorithmWithNoParam,
        'id-tc26-gost3410-12-256': AlgorithmWithNullParam,
        'id-tc26-gost3410-12-512': AlgorithmWithNullParam,
        'id-tc26-signwithdigest-gost3410-12-94': AlgorithmWithNoParam,
        'id-tc26-signwithdigest-gost3410-12-256': AlgorithmWithNoParam,
        'id-tc26-signwithdigest-gost3410-12-512': AlgorithmWithNoParam,
        'id-sc-gostR3410-94': AlgorithmWithNullParam,
        'id-sc-gostR3410-2001': AlgorithmWithNullParam,
        'id-sc-gostR3411-94-with-gostR3410-94': AlgorithmWithNullParam,
        'id-sc-gostR3411-94-with-gostR3410-2001': AlgorithmWithNullParam
    });

    var DigestAlgorithmIdentifier = AlgorithmIdentifier({
        sha1: AlgorithmWithNoParam,
        sha256: AlgorithmWithNullParam,
        sha384: AlgorithmWithNullParam,
        sha512: AlgorithmWithNullParam,
        'id-GostR3411-94': Gost341194DigestAlgorithm,
        'id-tc26-gost3411-94': Gost341194DigestAlgorithm,
        'id-tc26-gost3411-12-256': AlgorithmWithNullParam,
        'id-tc26-gost3411-12-512': AlgorithmWithNullParam,
        'id-sc-gostR3411-94': AlgorithmWithNoParam});

    var Gost2814789Key = OCTET_STRING; //(SIZE (32))

    var Gost2814789MAC = OCTET_STRING; // (SIZE (1..4))

    var Gost2814789ParamSet = OBJECT_IDENTIFIER;

    var Gost2814789IV = OCTET_STRING; // (SIZE (8))

    var Gost2814789Parameters = SEQUENCE({
        iv: Gost2814789IV,
        encryptionParamSet: Gost2814789ParamSet});

    var Gost2814789KeyWrapParameters = SEQUENCE({
        encryptionParamSet: Gost2814789ParamSet,
        ukm: OPTIONAL(OCTET_STRING)}); // (SIZE (8)) must be absent in key agreement

    var Gost2814789Algorithm = Algorithm(Gost2814789Parameters, {
        encode: function (value) {
            return {
                algorithm: value.id,
                parameters: {
                    iv: value.iv,
                    encryptionParamSet: attributes['sBox'][value.sBox || 'E-A']
                }
            };
        },
        decode: function (value) {
            var algorithm = expand(algorithms[value.algorithm],
                    parameters[value.parameters.encryptionParamSet]);
            algorithm.iv = value.parameters.iv;
            return algorithm;
        }
    });

    var SCGostAlgorithm = Algorithm(Gost2814789IV, {
        encode: function (value) {
            return {
                algorithm: value.id,
                parameters: value.iv
            };
        },
        decode: function (value) {
            var algorithm = expand(algorithms[value.algorithm]);
            algorithm.iv = value.parameters || new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0]);
            return algorithm;
        }
    });

    var GostKeyWrapAlgorithm = Algorithm(Gost2814789KeyWrapParameters, {
        encode: function (value) {
            return {
                algorithm: value.id,
                parameters: {
                    encryptionParamSet: attributes['sBox'][value.sBox || 'E-A'],
                    ukm: value.ukm
                }
            };
        },
        decode: function (value) {
            var algorithm = expand(algorithms[value.algorithm],
                    parameters[value.parameters.encryptionParamSet]);
            if (value.parameters.ukm)
                algorithm.ukm = value.parameters.ukm;
            return algorithm;
        }
    });

    var KeyWrapAlgorithmIdentifier = AlgorithmIdentifier({
        'id-Gost28147-89-None-KeyWrap': GostKeyWrapAlgorithm,
        'id-Gost28147-89-CryptoPro-KeyWrap': GostKeyWrapAlgorithm});

    var GostKeyAgreementAlgorithm = Algorithm(KeyWrapAlgorithmIdentifier, {
        encode: function (value) {
            return {
                algorithm: value.id,
                parameters: value.wrapping
            };
        },
        decode: function (value) {
            var algorithm = expand(algorithms[value.algorithm]);
            algorithm.wrapping = value.parameters;
            return algorithm;
        }
    });

    var BaseEncryptionAlgorithmIdentifier = AlgorithmIdentifier({
        'id-sc-gost28147-gfb': SCGostAlgorithm,
        'id-Gost28147-89': Gost2814789Algorithm});

    var MessageAuthenticationCodeAlgorithm = AlgorithmIdentifier({
        'id-Gost28147-89-MAC': Gost2814789Parameters,
        'id-HMACGostR3411-94': Gost341194DigestAlgorithm,
        'id-tc26-hmac-gost-3411-12-256': Gost341194DigestAlgorithm,
        'id-tc26-hmac-gost-3411-12-512': Gost341194DigestAlgorithm,
        'hmacWithSHA1': AlgorithmWithNoParam,
        'hmacWithSHA224': AlgorithmWithNoParam,
        'hmacWithSHA256': AlgorithmWithNoParam,
        'hmacWithSHA384': AlgorithmWithNoParam,
        'hmacWithSHA512': AlgorithmWithNoParam,
        'id-sc-gost28147-mac': AlgorithmWithNoParam,
        'id-sc-hmacWithGostR3411': AlgorithmWithNoParam});

    // rfc2898 PKCS #5: Password-Based Cryptography Specification
    // PBKDF2
    var PBKDF2params = SEQUENCE({
        salt: CHOICE({
            specified: OCTET_STRING,
            otherSource: AlgorithmIdentifier
        }, function (value) {
            return isBinary(value) ? 'specified' : 'otherSource';
        }),
        iterationCount: INTEGER,
        keyLength: OPTIONAL(INTEGER),
        prf: MessageAuthenticationCodeAlgorithm});

    var PBKDF2Algorithm = Algorithm(PBKDF2params, {
        encode: function (value) {
            return {
                algorithm: value.id,
                parameters: {
                    salt: value.salt,
                    iterationCount: value.iterations,
                    prf: value.hmac
                }
            };
        },
        decode: function (value) {
            var algorithm = expand(algorithms[value.algorithm]);
            algorithm.salt = value.parameters.salt;
            algorithm.iterations = value.parameters.iterationCount;
            algorithm.hmac = value.parameters.prf;
            algorithm.hash = algorithm.hmac.hash;
            return algorithm;
        }
    });

    var KeyDerivationAlgorithmIdentifier = AlgorithmIdentifier({
        'PBKDF2': PBKDF2Algorithm});

    var PBEParameter = SEQUENCE({
        salt: OCTET_STRING,
        iterationCount: INTEGER});

    var PBES1Algorithm = Algorithm(PBEParameter, {
        paramType: PBEParameter,
        encode: function (value) {
            return {
                algorithm: value.id,
                parameters: {
                    salt: value.derivation.salt,
                    iterationCount: value.derivation.iterations
                }
            };
        },
        decode: function (value) {
            var algorithm = expand(algorithms[value.algorithm]);
            algorithm.derivation = expand(algorithm.derivation,
                    {salt: value.parameters.salt, iterations: value.parameters.iterationCount});
            return algorithm;
        }
    });

    // PBES2
    var PBES2params = SEQUENCE({
        keyDerivationFunc: KeyDerivationAlgorithmIdentifier, // {{PBES2-KDFs}},
        encryptionScheme: BaseEncryptionAlgorithmIdentifier}); // {{PBES2-Encs}}

    var PBES2Algorithm = Algorithm(PBES2params, {
        encode: function (value) {
            return {
                algorithm: value.id,
                parameters: {
                    keyDerivationFunc: value.derivation,
                    encryptionScheme: value.encryption
                }
            };
        },
        decode: function (value) {
            var algorithm = expand(algorithms[value.algorithm]);
            algorithm.derivation = value.parameters.keyDerivationFunc;
            algorithm.encryption = value.parameters.encryptionScheme;
            return algorithm;
        }
    });

    var PasswordEncryptionAlgorithmIndentifier = AlgorithmIdentifier({
        // PBES1
        'pbeWithSHAAndAES128-CBC': PBES1Algorithm,
        'pbeWithSHAAndAES192-CBC': PBES1Algorithm,
        'pbeWithSHAAndAES256-CBC': PBES1Algorithm,
        'pbeWithSHA256AndAES128-CBC': PBES1Algorithm,
        'pbeWithSHA256AndAES192-CBC': PBES1Algorithm,
        'pbeWithSHA256AndAES256-CBC': PBES1Algorithm,
        'id-sc-pbeWithGost3411AndGost28147': PBES1Algorithm,
        'id-sc-pbeWithGost3411AndGost28147CFB': PBES1Algorithm,
        // PKCS12 PBES1 
        'pbeWithSHAAnd3-KeyTripleDES-CBC': PBES1Algorithm,
        'pbeWithSHAAnd2-KeyTripleDES-CBC': PBES1Algorithm,
        'pbeWithSHAAnd128BitRC2-CBC': PBES1Algorithm,
        'pbeWithSHAAnd40BitRC2-CBC': PBES1Algorithm,
        'pbeUnknownGost': PBES1Algorithm,
        // PBES2
        'PBES2': PBES2Algorithm});

    var KeyEncryptionAlgorithmIdentifier = AlgorithmIdentifier({
        ecdsa: ECDHKeyAlgorithm,
        rsaEncryption: AlgorithmWithNullParam,
        // Base encryption
        'id-sc-gost28147-gfb': SCGostAlgorithm,
        'id-Gost28147-89': Gost2814789Algorithm,
        // Key transport algorithms
        'id-sc-gostR3410-2001': ECDHKeyAlgorithm,
        'id-GostR3410-2001': GostKeyAlgorithm,
        'id-GostR3410-94': GostKeyAlgorithm,
        'id-tc26-gost3410-12-256': GostKeyAlgorithm,
        'id-tc26-gost3410-12-512': GostKeyAlgorithm,
        // Key agreement algorithms
        'id-GostR3410-94-CryptoPro-ESDH': GostKeyAgreementAlgorithm,
        'id-GostR3410-2001-CryptoPro-ESDH': GostKeyAgreementAlgorithm,
        'id-tc26-agreement-gost-3410-12-256': GostKeyAgreementAlgorithm,
        'id-tc26-agreement-gost-3410-12-512': GostKeyAgreementAlgorithm,
        'id-sc-r3410-ESDH-r3411kdf': AlgorithmWithNullParam,
        // Key encryption key algorithms
        'id-Gost28147-89-None-KeyWrap': GostKeyWrapAlgorithm, // Add ukm to algorithm
        'id-Gost28147-89-CryptoPro-KeyWrap': GostKeyWrapAlgorithm,
        'id-sc-cmsGostWrap': AlgorithmWithNoParam, // SC don't use ukm
        'id-sc-cmsGost28147Wrap': AlgorithmWithNoParam,
        // Password based encryption
        'pbeWithSHAAndAES128-CBC': PBES1Algorithm,
        'pbeWithSHAAndAES192-CBC': PBES1Algorithm,
        'pbeWithSHAAndAES256-CBC': PBES1Algorithm,
        'pbeWithSHA256AndAES128-CBC': PBES1Algorithm,
        'pbeWithSHA256AndAES192-CBC': PBES1Algorithm,
        'pbeWithSHA256AndAES256-CBC': PBES1Algorithm,
        'id-sc-pbeWithGost3411AndGost28147': PBES1Algorithm,
        'id-sc-pbeWithGost3411AndGost28147CFB': PBES1Algorithm,
        // PKCS12 PBES1 
        'pbeWithSHAAnd3-KeyTripleDES-CBC': PBES1Algorithm,
        'pbeWithSHAAnd2-KeyTripleDES-CBC': PBES1Algorithm,
        'pbeWithSHAAnd128BitRC2-CBC': PBES1Algorithm,
        'pbeWithSHAAnd40BitRC2-CBC': PBES1Algorithm,
        'pbeUnknownGost': PBES1Algorithm,
        // PBES2
        'PBES2': PBES2Algorithm
    });

    var PBMAC1params = SEQUENCE({
        keyDerivationFunc: KeyDerivationAlgorithmIdentifier, // {{PBMAC1-KDFs}},
        messageAuthScheme: MessageAuthenticationCodeAlgorithm}); // {{PBMAC1-MACs}}

    var PasswordMACAlgorithm = Algorithm(PBMAC1params, {
        encode: function (value) {
            return {
                algorithm: value.id,
                parameters: {
                    keyDerivationFunc: value.derivation,
                    messageAuthScheme: value.hmac}};
        },
        decode: function (value) {
            var algorithm = expand(algorithms[value.algorithm]);
            algorithm.derivation = value.parameters.keyDerivationFunc;
            algorithm.hmac = value.parameters.messageAuthScheme;
            return algorithm;
        }
    });

    var PasswordMACAlgorithmIdentifier = AlgorithmIdentifier({
        'PBMAC1': PasswordMACAlgorithm
    });

    var ContentEncryptionAlgorithmIdentifier = AlgorithmIdentifier({
        // Base encryption
        'id-sc-gost28147-gfb': SCGostAlgorithm,
        'id-Gost28147-89': Gost2814789Algorithm,
        // Password based encryption
        'pbeWithSHAAndAES128-CBC': PBES1Algorithm,
        'pbeWithSHAAndAES192-CBC': PBES1Algorithm,
        'pbeWithSHAAndAES256-CBC': PBES1Algorithm,
        'pbeWithSHA256AndAES128-CBC': PBES1Algorithm,
        'pbeWithSHA256AndAES192-CBC': PBES1Algorithm,
        'pbeWithSHA256AndAES256-CBC': PBES1Algorithm,
        'id-sc-pbeWithGost3411AndGost28147': PBES1Algorithm,
        'id-sc-pbeWithGost3411AndGost28147CFB': PBES1Algorithm,
        // PKCS12 PBES1 
        'pbeWithSHAAnd3-KeyTripleDES-CBC': PBES1Algorithm,
        'pbeWithSHAAnd2-KeyTripleDES-CBC': PBES1Algorithm,
        'pbeWithSHAAnd128BitRC2-CBC': PBES1Algorithm,
        'pbeWithSHAAnd40BitRC2-CBC': PBES1Algorithm,
        'pbeUnknownGost': PBES1Algorithm,
        // PBES2
        'PBES2': PBES2Algorithm
    });



    /*
     * Public Key Info 
     * 
     * http://tools.ietf.org/html/rfc5280
     * 
     */

    var KeyData = ENCLOSURE;

    var DHPublicKey = KeyData(BIT_STRING(ENCAPSULATES(INTEGER)), {
        encode: function (value) {
            return Int16.encode(swapBytes(value));
        },
        decode: function (value) {
            return swapBytes(Int16.decode(value));
        }
    });

    var ECDHPublicKey = KeyData(BIT_STRING(ENCAPSULATES(OCTET_STRING)), {
        encode: function (value) {
            var r = new Uint8Array(value.byteLength + 1),
                    d = swapBytes(value),
                    len = value.byteLength / 2;
            r[0] = 0x04; // type hex;
            r.set(new Uint8Array(d, len, len), 1); // x
            r.set(new Uint8Array(d, 0, len), len + 1); // y
            return r.buffer;
        },
        decode: function (value) {
            assert((value.byteLength & 1) === 0);
            var d = new Uint8Array(value.byteLength - 1),
                    len = d.byteLength / 2;
            d.set(new Uint8Array(value, len + 1, len), 0); // y
            d.set(new Uint8Array(value, 1, len), len); // x
            return swapBytes(d);
        }
    });

    var GostR3410PublicKey = BIT_STRING(ENCAPSULATES(OCTET_STRING));

    /**
     * Subject Public Key Info Syntax X.509
     * <pre>
     *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
     *      algorithm            AlgorithmIdentifier,
     *      subjectPublicKey     BIT STRING  }
     *  
     *  AlgorithmIdentifier  ::=  SEQUENCE  {
     *      algorithm               OBJECT IDENTIFIER,
     *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
     -- contains a value of the type
     -- registered for use with the
     -- algorithm object identifier value     
     * </pre>
     * RFC 5280 references {@link http://tools.ietf.org/html/rfc5280} 
     * @class GostASN1.SubjectPublicKeyInfo
     * @extends GostASN1.Sequence
     * @property {AlgorithmIdentifier} algorithm Identifies the public-key algorithm.
     * @property {CryptoOperationData} subjectPublicKey An binary data whose contents are the value of the public key
     */
    var SubjectPublicKeyInfo = SEQUENCE({
        algorithm: KeyAlgorithmIdentifier,
        subjectPublicKey: BIT_STRING}, 'PUBLIC KEY');

    var GostSubjectPublicKeyInfo = (function (PKTypes) {

        /**
         * Coding methods for {@link Algorithm} and {@link GostASN1.SubjectPublicKeyInfo}
         * Supported types for GOST algorithms:
         * <pre>
         *  {
         *      'id-sc-gostR3410-2001': ECDHPublicKey,
         *      'id-sc-gostR3410-94': DHPublicKey,
         *      'id-GostR3410-2001': GostR3410PublicKey,
         *      'id-GostR3410-94': GostR3410PublicKey,
         *      'id-tc26-gost3410-12-256': GostR3410PublicKey,
         *      'id-tc26-gost3410-12-512': GostR3410PublicKey
         *  }
         * </pre>
         * 
         * @class GostASN1.GostSubjectPublicKeyInfo
         * @extends GostASN1.SubjectPublicKeyInfo
         * @extends Key
         */
        return ENCLOSURE(ATTRIBUTE({
            algorithm: KeyAlgorithmIdentifier,
            subjectPublicKey: ANY},
        'algorithm', 'subjectPublicKey')(function (algorithm) {
            return PKTypes[algorithm.id];
        }), {
            encode: function (value) {
                return {
                    algorithm: value.algorithm,
                    subjectPublicKey: value.buffer
                };
            },
            decode: function (value) {
                return {
                    algorithm: value.algorithm,
                    type: 'public',
                    extractable: true,
                    usages: ['verify', 'deriveKey', 'deriveBits'],
                    buffer: value.subjectPublicKey
                };
            }
        });
    })({
        'id-sc-gostR3410-2001': ECDHPublicKey,
        'id-sc-gostR3410-94': DHPublicKey,
        'id-GostR3410-2001': GostR3410PublicKey,
        'id-GostR3410-94': GostR3410PublicKey,
        'id-tc26-gost3410-12-256': GostR3410PublicKey,
        'id-tc26-gost3410-12-512': GostR3410PublicKey
    });


    /*
     * Private Key Info PKCS#8
     * 
     * http://tools.ietf.org/html/rfc5208
     * 
     */

    var PrivateKey = OCTET_STRING;

    var DHPrivateKey = KeyData(PrivateKey(ENCAPSULATES(INTEGER)), {
        encode: function (value) { // for SignalCom INTEGER d
            return SInt.encode(value, true);
        },
        decode: function (value) {
            return SInt.decode(value, true);
        }
    });

    var GostR3410KeyValueMask = OCTET_STRING;

    var GostR3410KeyValueInfo = SEQUENCE({
        keyValueMask: GostR3410KeyValueMask,
        keyValyePublicKey: OCTET_STRING});

    var GostR3410PrivateKey = CHOICE({
        privateKey: PrivateKey(ENCAPSULATES(CHOICE({
            keyValueMask: GostR3410KeyValueMask,
            keyValueInfo: GostR3410KeyValueInfo
        }, function (value) {
            if (isBinary(value))
                return 'keyValueMask';
            else
                return 'keyValueInfo';
        }))),
        keyValueMask: GostR3410KeyValueMask
    }, function (value) {
        return value.enclosed ? 'keyValueMask' : 'privateKey';
    });

    var GostWrappedPrivateKey = (function (PKTypes) {

        /**
         * Gost Wrapped Private Key for SignalCom key container
         * 
         * @class GostASN1.GostWrappedPrivateKey
         * @extends GostASN1.PrivateKeyInfo
         */
        return ATTRIBUTE({
            version: Version,
            privateKeyAlgorithm: KeyAlgorithmIdentifier,
            privateKeyWrapped: KeyData(PrivateKey(ENCAPSULATES(SEQUENCE({
                keyData: INTEGER,
                keyMac: INTEGER
            }))), {
                encode: function (value) {
                    var size = value.byteLength - 4;
                    return {
                        keyData: SInt.encode(new Uint8Array(value, 0, size)),
                        keyMac: SInt.encode(new Uint8Array(value, size, 4))
                    };
                },
                decode: function (value) {
                    var data = SInt.decode(value.keyData),
                            mac = SInt.decode(value.keyMac),
                            result = new Uint8Array(data.byteLength + mac.byteLength);
                    result.set(new Uint8Array(data));
                    result.set(new Uint8Array(mac), data.byteLength);
                    return result;
                }
            }),
            attributes: ANY
        }, 'privateKeyAlgorithm', 'attributes')(function (algorithm) {
            return OPTIONAL(CTX(0, IMPLICIT(Attributes({
                'id-sc-gostR3410-2001-publicKey': SET_OF_SINGLE(PKTypes[algorithm.id])
            }))));
        });
    })({
        // Signature keys
        'id-sc-gostR3410-2001': ECDHPublicKey,
        'id-sc-gostR3410-94': DHPublicKey,
        'id-GostR3410-2001': GostR3410PublicKey,
        'id-GostR3410-94': GostR3410PublicKey,
        'id-GostR3410-2001DH': GostR3410PublicKey,
        'id-GostR3410-94DH': GostR3410PublicKey,
        'id-tc26-gost3410-12-256': GostR3410PublicKey,
        'id-tc26-gost3410-12-512': GostR3410PublicKey,
        'id-tc26-agreement-gost-3410-12-256': GostR3410PublicKey,
        'id-tc26-agreement-gost-3410-12-512': GostR3410PublicKey
    });

    /**
     * Private-Key Information Syntax PKSC#8
     * <pre>
     *  -- Private-key information syntax
     *
     *  PrivateKeyInfo ::= SEQUENCE {
     *      version Version,
     *      privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
     *      privateKey PrivateKey,
     *      attributes [0] Attributes OPTIONAL }
     *
     *  Version ::= INTEGER {v1(0)} (v1,...)
     *
     *  PrivateKey ::= OCTET STRING
     *
     *  Attributes ::= SET OF Attribute
     * </pre>
     * RFC 5208 references {@link http://tools.ietf.org/html/rfc5208} 
     * @class GostASN1.PrivateKeyInfo
     * @extends GostASN1.Sequence
     * @property {number} version The syntax version number. Should be 0
     * @property {AlgorithmIndentifier} privateKeyAlgorithm Identifies the private-key algorithm
     * @property {CryptoOperationData} privateKey Is an binary data whose contents are the value of the private key.  
     * @property {GostASN1.Attributes} attributes A set of attributes
     */
    var PrivateKeyInfo = SEQUENCE({
        version: Version,
        privateKeyAlgorithm: KeyAlgorithmIdentifier,
        privateKey: PrivateKey,
        attributes: OPTIONAL(CTX(0, IMPLICIT(Attributes)))}, 'PRIVATE KEY');

    var PrivateKeyAlgorithmIdentifier = KeyAlgorithmIdentifier;

    var PublicKey = BIT_STRING;

    var OneAsymmetricKey = SEQUENCE({
        version: Version,
        privateKeyAlgorithm: PrivateKeyAlgorithmIdentifier,
        privateKey: PrivateKey,
        attributes: OPTIONAL(CTX(0, IMPLICIT(Attributes))),
        publicKey: OPTIONAL(CTX(1, IMPLICIT(PublicKey)))});

    var AsymmetricKeyPackage = SEQUENCE_OF(OneAsymmetricKey);

    var GostPrivateKeyInfo = (function (PKTypes) {

        /**
         * Coding methods for {@link Algorithm} and {@link GostASN1.PrivateKeyInfo}
         * Supported types for GOST algorithms:
         * <pre>
         *  {
         *      'id-sc-gostR3410-2001': DHPrivateKey,
         *      'id-sc-gostR3410-94': DHPrivateKey,
         *      'id-GostR3410-2001': GostR3410PrivateKey,
         *      'id-GostR3410-94': GostR3410PrivateKey,
         *      'id-tc26-gost3410-12-256': GostR3410PrivateKey,
         *      'id-tc26-gost3410-12-512': GostR3410PrivateKey
         *  }
         * </pre>
         * 
         * @class GostASN1.GostPrivateKeyInfo
         * @extends GostASN1.PrivateKeyInfo
         * @extends Key
         */
        return ENCLOSURE(ATTRIBUTE({
            version: Version,
            privateKeyAlgorithm: KeyAlgorithmIdentifier,
            privateKey: ANY,
            attributes: OPTIONAL(CTX(0, IMPLICIT(Attributes)))},
        'privateKeyAlgorithm', 'privateKey')(function (algorithm) {
            return PKTypes[algorithm.id];
        }), {
            encode: function (value) {
                return {
                    version: 0,
                    privateKeyAlgorithm: value.algorithm,
                    privateKey: value.buffer
                };
            },
            decode: function (value) {
                return {
                    algorithm: value.privateKeyAlgorithm,
                    type: 'private',
                    extractable: true,
                    usages: ['sign', 'deriveKey', 'deriveBits'],
                    buffer: isBinary(value.privateKey) ? value.privateKey :
                            value.privateKey.keyValueMask
                };
            }
        });
    })({
        // Signature keys
        'id-sc-gostR3410-2001': DHPrivateKey,
        'id-sc-gostR3410-94': DHPrivateKey,
        'id-GostR3410-2001': GostR3410PrivateKey,
        'id-GostR3410-94': GostR3410PrivateKey,
        'id-GostR3410-2001DH': GostR3410PrivateKey,
        'id-GostR3410-94DH': GostR3410PrivateKey,
        'id-tc26-gost3410-12-256': GostR3410PrivateKey,
        'id-tc26-gost3410-12-512': GostR3410PrivateKey,
        'id-tc26-agreement-gost-3410-12-256': GostR3410PrivateKey,
        'id-tc26-agreement-gost-3410-12-512': GostR3410PrivateKey
    });

    var KeyEncryptedData = OCTET_STRING;
    /**
     * Encrypted Private-Key Information Syntax
     * <pre>
     *  -- Encrypted private-key information syntax
     *
     *  EncryptedPrivateKeyInfo ::= SEQUENCE {
     *      encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}},
     *      encryptedData KeyEncryptedData
     *  }
     *
     *  KeyEncryptedData ::= OCTET STRING
     *
     *  PrivateKeyAlgorithms ALGORITHM-IDENTIFIER ::= {
     *      ... -- For local profiles
     *  }
     *
     *  KeyEncryptionAlgorithms ALGORITHM-IDENTIFIER ::= {
     *      ... -- For local profiles
     *  }
     * </pre>
     * RFC 5208 references {@link http://tools.ietf.org/html/rfc5208} 
     * @class GostASN1.EncryptedPrivateKeyInfo
     * @extends GostASN1.Sequence
     * @property {AlgorithmIdentifier} encryptionAlgorithm Identifies key encryption algorithm
     * @property {CryptoOperationData} encryptedData Encrypted {@link GostASN1.PrivateKeyInfo}
     */
    var EncryptedPrivateKeyInfo = SEQUENCE({
        encryptionAlgorithm: KeyEncryptionAlgorithmIdentifier,
        encryptedData: KeyEncryptedData}, 'ENCRYPTED PRIVATE KEY');


    /*
     * Certificate Extensions
     * 
     * http://tools.ietf.org/html/rfc5280
     * 
     */
    var UniqueIdentifier = BIT_STRING;

    var CertificateSerialNumber = INTEGER;

    var BasicConstraints = SEQUENCE({
        cA: DEFAULT(BOOLEAN, false),
        pathLenConstraint: OPTIONAL(INTEGER)
    });

    var KeyUsage = BIT_STRING({
        digitalSignature: 0,
        nonRepudiation: 1,
        keyEncipherment: 2,
        dataEncipherment: 3,
        keyAgreement: 4,
        keyCertSign: 5,
        cRLSign: 6,
        encipherOnly: 7,
        decipherOnly: 8});
    var KeyPurposeId = OBJECT_IDENTIFIER,
            ExtKeyUsageSyntax = SEQUENCE_OF(KeyPurposeId);

    var KeyIdentifier = OCTET_STRING;

    var OtherName = SEQUENCE({
        type: OBJECT_IDENTIFIER,
        value: CTX(0, EXPLICIT(ANY))});

    var EDIPartyName = SEQUENCE({
        nameAssigner: OPTIONAL(CTX(0, IMPLICIT(DirectoryString))),
        partyName: OPTIONAL(CTX(1, IMPLICIT(DirectoryString)))});

    var ORAddress = SEQUENCE({});

    var GeneralName = CHOICE({
        otherName: CTX(0, IMPLICIT(OtherName)),
        rfc822Name: CTX(1, IMPLICIT(DirectoryString)),
        dNSName: CTX(2, IMPLICIT(DirectoryString)),
        x400Address: CTX(3, IMPLICIT(ORAddress)),
        directoryName: CTX(4, EXPLICIT(Name)), // Name is CHOICE(RDNSequence)
        ediPartyName: CTX(5, IMPLICIT(EDIPartyName)),
        uniformResourceIdentifier: CTX(6, IMPLICIT(DirectoryString)),
        iPAddress: CTX(7, IMPLICIT(OCTET_STRING)),
        registeredID: CTX(8, IMPLICIT(OBJECT_IDENTIFIER))}, function (value) {
        return typeof value === 'string' || value instanceof String ?
                (value.indexOf('@') >= 0 ? 'rfc822Name' : 'dNSName') :
                isBinary(value) ? 'iPAddress' : 'directoryName';
    });

    var GeneralNames = SEQUENCE_OF(GeneralName);

    var AuthorityKeyIdentifier = SEQUENCE({
        keyIdentifier: OPTIONAL(CTX(0, IMPLICIT(KeyIdentifier))),
        authorityCertIssuer: OPTIONAL(CTX(1, IMPLICIT(GeneralNames))),
        authorityCertSerialNumber: OPTIONAL(CTX(2, IMPLICIT(CertificateSerialNumber)))});

    var PrivateKeyUsagePeriod = SEQUENCE({
        notBefore: OPTIONAL(CTX(0, IMPLICIT(GeneralizedTime))),
        notAfter: OPTIONAL(CTX(1, IMPLICIT(GeneralizedTime)))});

    var CertPolicyId = OBJECT_IDENTIFIER,
            PolicyQualifierId = OBJECT_IDENTIFIER;

    var PolicyQualifierInfo = SEQUENCE({
        policyQualifierId: PolicyQualifierId,
        qualifier: ANY});

    var PolicyInformation = SEQUENCE({
        policyIdentifier: CertPolicyId,
        policyQualifiers: OPTIONAL(SEQUENCE_OF(PolicyQualifierInfo))});

    var PolicyMapping = SEQUENCE({
        issuerDomainPolicy: CertPolicyId,
        subjectDomainPolicy: CertPolicyId});

    var BaseDistance = INTEGER;

    var GeneralSubtree = SEQUENCE({
        base: GeneralName,
        minimum: DEFAULT(CTX(0, IMPLICIT(BaseDistance)), 0),
        maximum: OPTIONAL(CTX(1, IMPLICIT(BaseDistance)))});

    var GeneralSubtrees = SEQUENCE_OF(GeneralSubtree);

    var NameConstraints = SEQUENCE({
        permittedSubtrees: OPTIONAL(CTX(0, IMPLICIT(GeneralSubtrees))),
        excludedSubtrees: OPTIONAL(CTX(1, IMPLICIT(GeneralSubtrees)))});

    var SkipCerts = INTEGER;

    var PolicyConstraints = SEQUENCE({
        requireExplicitPolicy: OPTIONAL(CTX(0, IMPLICIT(SkipCerts))),
        inhibitPolicyMapping: OPTIONAL(CTX(1, IMPLICIT(SkipCerts)))});

    var ReasonFlags = BIT_STRING({
        unused: 0,
        keyCompromise: 1,
        cACompromise: 2,
        affiliationChanged: 3,
        superseded: 4,
        cessationOfOperation: 5,
        certificateHold: 6,
        privilegeWithdrawn: 7,
        aACompromise: 8});

    var DistributionPointName = CHOICE({
        fullName: CTX(0, IMPLICIT(GeneralNames)),
        nameRelativeToCRLIssuer: CTX(1, IMPLICIT(RelativeDistinguishedName))}, function (value) {
        return value instanceof Array ? 'fullName' : 'nameRelativeToCRLIssuer';
    });

    var DistributionPoint = SEQUENCE({
        distributionPoint: OPTIONAL(CTX(0, EXPLICIT(DistributionPointName))), // DistributionPointName CHOICE
        reasons: OPTIONAL(CTX(1, IMPLICIT(ReasonFlags))),
        cRLIssuer: OPTIONAL(CTX(2, IMPLICIT(GeneralNames)))});

    var CRLDistributionPoints = SEQUENCE_OF(DistributionPoint);

    var FreshestCRL = CRLDistributionPoints;

    var AccessDescription = SEQUENCE({
        accessMethod: OBJECT_IDENTIFIER,
        accessLocation: GeneralName});

    var Extension = function (typeSet, defaultCritical) {

        var Attribute = ATTRIBUTE({
            extnID: OBJECT_IDENTIFIER,
            critical: DEFAULT(BOOLEAN, false),
            extnValue: function (type) {
                return OCTET_STRING(ENCAPSULATES(type));
            }
        }, 'extnID', 'extnValue');

        var Class = extend(Attribute(typeSet), {
            object: {
                get: function () {
                    var value = this._get(Class.super, 'object');
                    if (value && typeof value.extnValue === 'object')
                        this.defineValue(value.extnValue);
                    return value;
                },
                set: function (object) {
                    this._set(Class.super, 'object', object);
                    // Define critical
                    if (object && object.extnValue)
                        if (object.extnValue.critical !== undefined)
                            this.critical = object.extnValue.critical;
                        else if (this.critical === undefined && defaultCritical)
                            this.critical = defaultCritical(this.extnID, object.extnValue);
                }
            },
            extnValue: {
                get: function () {
                    // Get value property of object
                    var value = this._get(Class.super, 'extnValue');
                    if (typeof value === 'object')
                        this.defineValue(value);
                    return value;
                },
                set: function (object) {
                    // Set value property of object
                    this._set(Class.super, 'extnValue', object);
                    // Define critical
                    if (object) {
                        if (object.critical !== undefined)
                            this.critical = object.critical;
                        else if (this.critical === undefined && defaultCritical)
                            this.critical = defaultCritical(this.extnID, object);
                    }
                }
            },
            defineValue: function (value) {
                if (typeof value === 'object')
                    if (!getOwnPropertyDescriptor(value, 'critical')) {
                        var self = __webpack_require__.g;
                        defineProperty(value, 'critical', {
                            get: function () {
                                return self.critical;
                            },
                            set: function (value) {
                                self.critical = value;
                            },
                            enumerable: true,
                            configurable: false
                        });
                    }
            }
        });
        return Class;
    };

    // http://base.garant.ru/70133464/#ixzz4KaOTGI1l
    var IssuerSignTool = SEQUENCE({
        signTool: UTF8String,
        cATool: UTF8String,
        signToolCert: UTF8String,
        cAToolCert: UTF8String});

    /**
     * Extensions is a base class for extension attributes of certificates, CRLs, requests and etc.
     * 
     * @class GostASN1.Extensions
     * @extends GostASN1.Set
     */
    var Extensions = SEQUENCE_OF(Extension, {
        typeName: 'extnID',
        valueName: 'extnValue'
    });

    var CertExtensions = Extensions({
        authorityKeyIdentifier: AuthorityKeyIdentifier,
        subjectKeyIdentifier: KeyIdentifier,
        keyUsage: KeyUsage,
        privateKeyUsagePeriod: PrivateKeyUsagePeriod,
        certificatePolicies: SEQUENCE_OF(PolicyInformation),
        policyMappings: SEQUENCE_OF(PolicyMapping),
        subjectAltName: GeneralNames,
        issuerAltName: GeneralNames,
        subjectDirectoryAttributes: AttributeSequence,
        basicConstraints: BasicConstraints,
        nameConstraints: NameConstraints,
        policyConstraints: PolicyConstraints,
        extKeyUsage: ExtKeyUsageSyntax,
        cRLDistributionPoints: CRLDistributionPoints,
        inhibitAnyPolicy: SkipCerts,
        freshestCRL: FreshestCRL,
        authorityInfoAccess: SEQUENCE_OF(AccessDescription),
        subjectInfoAccess: SEQUENCE_OF(AccessDescription),
        subjectSignTool: UTF8String,
        issuerSignTool: IssuerSignTool
    }, function (id, value) {
        return id === 'keyUsage' ||
                (id === 'basicConstraints' && value.pathLenConstraint === undefined);
    });


    /*
     * Signature Values
     * 
     * http://tools.ietf.org/html/rfc5280
     * http://tools.ietf.org/html/rfc4491
     * 
     */

    /**
     * Gost Signature encode signature values for different GOST signatures
     * Support algorithms:
     * <pre>
     *  {
     *      'id-GostR3410-94': GostR3410Signature,
     *      'id-GostR3410-2001': GostR3410Signature,
     *      'id-tc26-gost3410-12-256': GostR3410Signature,
     *      'id-tc26-gost3410-12-512': GostR3410Signature,
     *      'id-GostR3411-94-with-GostR3410-2001': GostR3410Signature,
     *      'id-GostR3411-94-with-GostR3410-94': GostR3410Signature,
     *      'id-tc26-signwithdigest-gost3410-12-94': GostR3410Signature,
     *      'id-tc26-signwithdigest-gost3410-12-256': GostR3410Signature,
     *      'id-tc26-signwithdigest-gost3410-12-512': GostR3410Signature,
     *      'id-sc-gostR3410-94': ECDHSignature,
     *      'id-sc-gostR3410-2001': ECDHSignature,
     *      'id-sc-gostR3411-94-with-gostR3410-94': ECDHSignature,
     *      'id-sc-gostR3411-94-with-gostR3410-2001': ECDHSignature
     *  }
     * </pre>
     * 
     * @class GostASN1.GostSignature
     * @extends GostASN1.Sequence
     */

    // SignalCom signature
    var ECDHSignature = SEQUENCE({
        r: INTEGER,
        s: INTEGER});

    var GostR3410Signature = ANY;

    // Signature value (only need for CryptoPro
//    var GostSignature = extend(CHOICE({
//        ecdhSignature: ECDHSignature}, 'ecdhSignature'));
    var GostSignature = ECDHSignature;



    /*
     * Certificate
     * 
     * http://tools.ietf.org/html/rfc5280
     * 
     */

    /**
     * The sequence TBSCertificate contains information associated with the
     * subject of the certificate and the CA who issued it.  Every
     * TBSCertificate contains the names of the subject and issuer, a public
     * key associated with the subject, a validity period, a version number,
     * and a serial number; some MAY contain optional unique identifier
     * fields.  The remainder of this section describes the syntax and
     * semantics of these fields.  A TBSCertificate usually includes
     * extensions. 
     * <pre>
     *  TBSCertificate  ::=  SEQUENCE  {
     *       version         [0]  EXPLICIT Version DEFAULT v1,
     *       serialNumber         CertificateSerialNumber,
     *       signature            AlgorithmIdentifier,
     *       issuer               Name,
     *       validity             Validity,
     *       subject              Name,
     *       subjectPublicKeyInfo SubjectPublicKeyInfo,
     *       issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
     *                            -- If present, version MUST be v2 or v3
     *       subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
     *                            -- If present, version MUST be v2 or v3
     *       extensions      [3]  EXPLICIT Extensions OPTIONAL
     *                            -- If present, version MUST be v3
     *       }
     *
     *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
     *
     *  CertificateSerialNumber  ::=  INTEGER
     *
     *  Validity ::= SEQUENCE {
     *       notBefore      Time,
     *       notAfter       Time }
     *
     *  Time ::= CHOICE {
     *       utcTime        UTCTime,
     *       generalTime    GeneralizedTime }
     *
     *  UniqueIdentifier  ::=  BIT STRING
     *
     *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
     *       algorithm            AlgorithmIdentifier,
     *       subjectPublicKey     BIT STRING  }
     *
     *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
     *
     *  Extension  ::=  SEQUENCE  {
     *       extnID      OBJECT IDENTIFIER,
     *       critical    BOOLEAN DEFAULT FALSE,
     *       extnValue   OCTET STRING  }
     * </pre>
     * See {@link GostASN1.Certificate} and {@link GostASN1.SubjectPublicKeyInfo}<br><br>
     * RFC 5280 references {@link http://tools.ietf.org/html/rfc5280} 
     * 
     * @class GostASN1.TBSCertificate
     * @extends GostASN1.Sequence
     * @extends GostASN1.Validity
     * @property {number} version The version of the encoded certificate
     * @property {(number|string)} serialNumber The serial number MUST be a positive integer assigned by the CA to each certificate.
     * @property {AlgorithmIdentifier} signature The algorithm identifier for the algorithm used by the CA to sign the certificate.
     * @property {GostASN1.Name} issuer The issuer field identifies the entity that has signed and issued the certificate.
     * @property {GostASN1.Validity} validity The certificate validity period
     * @property {GostASN1.Name} subject The subject field identifies the entity associated with the public key stored in the subject public key field.
     * @property {GostASN1.SubjectPublicKeyInfo} subject The public key and identify the algorithm with which the key is used
     * @property {CryptoOperationData} issuerUniqueID The issuer unique identifier
     * @property {CryptoOperationData} subjectUniqueID The subject unique identifier
     * @property {GostASN1.Extensions} extensions The extensions defined for X.509 v3 certificates
     */
    var TBSCertificate = COMBINE(SEQUENCE({
        version: CTX(0, EXPLICIT(Version)),
        serialNumber: CertificateSerialNumber,
        signature: SignatureAlgorithmIdentifier,
        issuer: Name,
        validity: Validity,
        subject: Name,
        subjectPublicKeyInfo: SubjectPublicKeyInfo,
        issuerUniqueID: OPTIONAL(CTX(1, IMPLICIT(UniqueIdentifier))), // If present, version MUST be v2 or v3        
        subjectUniqueID: OPTIONAL(CTX(2, IMPLICIT(UniqueIdentifier))), // If present, version MUST be v2 or v3
        extensions: OPTIONAL(CTX(3, EXPLICIT(CertExtensions)))})); // If present, version MUST be v3        

    /**
     * The X.509 v3 certificate basic syntax is as follows.  For signature
     * calculation, the data that is to be signed is encoded using the ASN.1
     * distinguished encoding rules (DER) [X.690].  ASN.1 DER encoding is a
     * tag, length, value encoding system for each element.
     * <pre>
     *  Certificate  ::=  SEQUENCE  {
     *       tbsCertificate       TBSCertificate,
     *       signatureAlgorithm   AlgorithmIdentifier,
     *       signatureValue       BIT STRING  }
     * </pre>
     * See {@link GostASN1.TBSCertificate}<br><br>
     * RFC 5280 references {@link http://tools.ietf.org/html/rfc5280} 
     * 
     * @class GostASN1.Certificate
     * @extends GostASN1.TBSCertificate
     * @property {GostASN1.TBSCertificate} tbsCertificate The sequence TBSCertificate
     * @property {AlgorithmIndentifier} signatureAlgorithm Identifies signature algorithm
     * @property {CryptoOperationData} signatureValue Signature value
     */
    var Certificate = SEQUENCE({
        tbsCertificate: TBSCertificate,
        signatureAlgorithm: SignatureAlgorithmIdentifier,
        signatureValue: BIT_STRING}, 'CERTIFICATE');


    /*
     * Certification Request
     * 
     * http://tools.ietf.org/html/rfc2986
     * 
     */

    var ExtensionRequest = CertExtensions;

    var CRIAttributes = Attributes({
        challengePassword: SET_OF_SINGLE(DirectoryString),
        extensionRequest: SET_OF_SINGLE(ExtensionRequest),
        msCertExtensions: SET_OF_SINGLE(CertExtensions),
        extendedCertificateAttributes: SET_OF_SINGLE(Attributes)});

    /**
     * Certification request information shall have ASN.1 type CertificationRequestInfo:
     * <pre>
     *  CertificationRequestInfo ::= SEQUENCE {
     *       version       INTEGER { v1(0) } (v1,...),
     *       subject       Name,
     *       subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
     *       attributes    [0] Attributes{{ CRIAttributes }}
     *  }
     *
     *  SubjectPublicKeyInfo { ALGORITHM : IOSet} ::= SEQUENCE {
     *       algorithm        AlgorithmIdentifier {{IOSet}},
     *       subjectPublicKey BIT STRING
     *  }
     *
     *  PKInfoAlgorithms ALGORITHM ::= {
     *       ...  -- add any locally defined algorithms here -- }
     *
     *  Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
     *
     *  CRIAttributes  ATTRIBUTE  ::= {
     *       ... -- add any locally defined attributes here -- }
     *
     *  Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
     *       type   ATTRIBUTE.&id({IOSet}),
     *       values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
     *  }
     * </pre>
     * See {@link GostASN1.CertificationRequest} and {@link GostASN1.SubjectPublicKeyInfo}<br><br>
     * RFC 2986 references {@link http://tools.ietf.org/html/rfc2986} 
     * 
     * @class GostASN1.CertificationRequestInfo
     * @extends GostASN1.Sequence
     * @property {number} version The version of the encoded request
     * @property {GostASN1.Name} subject The subject field identifies the entity associated with the public key stored in the subject public key field.
     * @property {GostASN1.SubjectPublicKeyInfo} subject The public key and identify the algorithm with which the key is used
     * @property {GostASN1.Attributes} attributes The request attributes
     */
    var CertificationRequestInfo = COMBINE(SEQUENCE({
        version: INTEGER,
        subject: Name,
        subjectPublicKeyInfo: SubjectPublicKeyInfo,
        attributes: CTX(0, IMPLICIT(CRIAttributes))}));

    /**
     * A certification request consists of three parts: "certification
     * request information," a signature algorithm identifier, and a digital
     * signature on the certification request information.  The
     * certification request information consists of the entity's
     * distinguished name, the entity's public key, and a set of attributes
     * providing other information about the entity.
     * <pre>
     *  A certification request shall have ASN.1 type CertificationRequest:
     *
     *  CertificationRequest ::= SEQUENCE {
     *       certificationRequestInfo CertificationRequestInfo,
     *       signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
     *       signature          BIT STRING
     *  }
     *
     *  AlgorithmIdentifier {ALGORITHM:IOSet } ::= SEQUENCE {
     *       algorithm          ALGORITHM.&id({IOSet}),
     *       parameters         ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL
     *  }
     *
     *  SignatureAlgorithms ALGORITHM ::= {
     *       ... -- add any locally defined algorithms here -- }
     * </pre>
     * See {@link GostASN1.CertificationRequestInfo}
     * RFC 2986 references {@link http://tools.ietf.org/html/rfc2986} 
     * 
     * @class GostASN1.CertificationRequest
     * @extends GostASN1.CertificationRequestInfo
     * @property {GostASN1.CertificationRequestInfo} requestInfo Request information
     * @property {AlgorithmIndentifier} signatureAlgorithm Identifies signature algorithm
     * @property {CryptoOperationData} signatureValue Signature value
     */
    var CertificationRequest = SEQUENCE({
        requestInfo: CertificationRequestInfo,
        signatureAlgorithm: SignatureAlgorithmIdentifier,
        signatureValue: BIT_STRING}, 'CERTIFICATE REQUEST');


    /*
     * Certificate Revocation List
     * 
     * http://tools.ietf.org/html/rfc5280
     * 
     */

    var CRLNumber = INTEGER;

    var CRLReason = ENUMERATED({
        unspecified: 0,
        keyCompromise: 1,
        cACompromise: 2,
        affiliationChanged: 3,
        superseded: 4,
        cessationOfOperation: 5,
        certificateHold: 6,
        removeFromCRL: 8,
        privilegeWithdrawn: 9,
        aACompromise: 10});

    var IssuingDistributionPoint = SEQUENCE({
        distributionPoint: OPTIONAL(CTX(0, EXPLICIT(DistributionPointName))), // DistributionPointName is CHOICE
        onlyContainsUserCerts: DEFAULT(CTX(1, IMPLICIT(BOOLEAN)), false),
        onlyContainsCACerts: DEFAULT(CTX(2, IMPLICIT(BOOLEAN)), false),
        onlySomeReasons: OPTIONAL(CTX(3, IMPLICIT(ReasonFlags))),
        indirectCRL: DEFAULT(CTX(4, IMPLICIT(BOOLEAN)), false),
        onlyContainsAttributeCerts: DEFAULT(CTX(5, IMPLICIT(BOOLEAN)), false)});

    var CLRExtensions = Extensions({
        authorityKeyIdentifier: AuthorityKeyIdentifier,
        issuerAltName: GeneralNames,
        cRLNumber: CRLNumber,
        deltaCRLIndicator: CRLNumber,
        issuingDistributionPoint: IssuingDistributionPoint,
        freshestCRL: FreshestCRL
    }, function (id) {
        return id === 'cRLNumber';
    });

    var CLREntryExtensions = Extensions({
        cRLReason: CRLReason,
        instructionCode: OBJECT_IDENTIFIER,
        invalidityDate: GeneralizedTime,
        certificateIssuer: GeneralNames});

    /**
     * This field is itself a sequence containing the name of the issuer, 
     * issue date, issue date of the next list, the optional list of revoked
     * certificates, and optional CRL extensions.  When there are no revoked
     * certificates, the revoked certificates list is absent.  When one or
     * more certificates are revoked, each entry on the revoked certificate
     * list is defined by a sequence of user certificate serial number,
     * revocation date, and optional CRL entry extensions.
     * <pre>
     *  TBSCertList  ::=  SEQUENCE  {
     *       version                 Version OPTIONAL,
     *                                    -- if present, MUST be v2
     *       signature               AlgorithmIdentifier,
     *       issuer                  Name,
     *       thisUpdate              Time,
     *       nextUpdate              Time OPTIONAL,
     *       revokedCertificates     SEQUENCE OF SEQUENCE  {
     *            userCertificate         CertificateSerialNumber,
     *            revocationDate          Time,
     *            crlEntryExtensions      Extensions OPTIONAL
     *                                          -- if present, MUST be v2
     *                                 }  OPTIONAL,
     *       crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
     *                                          -- if present, MUST be v2
     *                                 }
     * </pre>
     * See {@link GostASN1.CertificateList}<br><br>
     * RFC 5280 references {@link http://tools.ietf.org/html/rfc5280} 
     * 
     * @class GostASN1.TBSCertList
     * @extends GostASN1.Sequence
     * @property {number} version The version of the encoded CRL
     * @property {AlgorithmIdentifier} signature The algorithm identifier for the algorithm used to sign the CRL
     * @property {Name} issuer The issuer name identifies the entity that has signed and issued the CRL
     * @property {Date} thisUpdate The issue date of this CRL
     * @property {Date} nextUpdate The date by which the next CRL will be issued
     * @property {Array} revokedCertificates The revoked certificates are listed by their serial numbers
     * @property {Extensions} crlExtensions The CRL extensions
     */
    var TBSCertList = COMBINE(SEQUENCE({
        version: OPTIONAL(Version), // if present, MUST be v2
        signature: SignatureAlgorithmIdentifier,
        issuer: Name,
        thisUpdate: Time,
        nextUpdate: OPTIONAL(Time),
        revokedCertificates: OPTIONAL(SEQUENCE_OF(SEQUENCE({
            userCertificate: CertificateSerialNumber,
            revocationDate: Time,
            crlEntryExtensions: OPTIONAL(CLREntryExtensions) // if present, MUST be v2
        }))),
        crlExtensions: OPTIONAL(CTX(0, EXPLICIT(CLRExtensions)))})); // if present, MUST be v2

    /**
     * The X.509 v2 CRL syntax is as follows.  For signature calculation,
     * the data that is to be signed is ASN.1 DER encoded.  ASN.1 DER
     * encoding is a tag, length, value encoding system for each element.
     * <pre>
     *  CertificateList  ::=  SEQUENCE  {
     *       tbsCertList          TBSCertList,
     *       signatureAlgorithm   AlgorithmIdentifier,
     *       signatureValue       BIT STRING  }
     * </pre>
     * See {@link GostASN1.TBSCertList}<br><br>
     * RFC 5280 references {@link http://tools.ietf.org/html/rfc5280} 
     * 
     * @class GostASN1.CertificateList
     * @extends GostASN1.TBSCertList
     * @property {GostASN1.TBSCertList} tbsCertList The tbsCertList
     * @property {AlgorithmIndentifier} signatureAlgorithm Identifies signature algorithm
     * @property {CryptoOperationData} signatureValue Signature value
     */
    var CertificateList = SEQUENCE({
        tbsCertList: TBSCertList,
        signatureAlgorithm: SignatureAlgorithmIdentifier,
        signatureValue: BIT_STRING}, 'CRL');


    /*
     * Attribute Certificate Definision
     * http://tools.ietf.org/html/rfc5755
     * 
     */

    var AttCertVersion = INTEGER;

    var ObjectDigestInfo = SEQUENCE({
        digestedObjectType: ENUMERATED({
            publicKey: 0,
            publicKeyCert: 1,
            otherObjectTypes: 2
        }), // otherObjectTypes MUST NOT be used in this profile
        otherObjectTypeID: OPTIONAL(OBJECT_IDENTIFIER),
        digestAlgorithm: DigestAlgorithmIdentifier,
        objectDigest: BIT_STRING});

    var IssuerSerial = SEQUENCE({
        issuer: GeneralNames,
        serial: CertificateSerialNumber,
        issuerUID: OPTIONAL(UniqueIdentifier)});

    var V2Form = SEQUENCE({
        issuerName: OPTIONAL(GeneralNames),
        baseCertificateID: OPTIONAL(CTX(0, IMPLICIT(IssuerSerial))),
        // issuerName MUST be present in this profile baseCertificateID and 
        // objectDigestInfo MUST NOT be present in this profile
        objectDigestInfo: OPTIONAL(CTX(1, IMPLICIT(ObjectDigestInfo)))});

    var TargetCert = SEQUENCE({
        targetCertificate: IssuerSerial,
        targetName: OPTIONAL(GeneralName),
        certDigestInfo: OPTIONAL(ObjectDigestInfo)});

    var Target = CHOICE({
        targetName: CTX(0, EXPLICIT(GeneralName)), // GeneralName is CHOICE
        targetGroup: CTX(1, EXPLICIT(GeneralName)),
        targetCert: CTX(2, IMPLICIT(TargetCert))});

    var Targets = SEQUENCE_OF(Target);

    var AttCertExtensions = Extensions({
        auditIdentity: OCTET_STRING,
        targetInformation: Targets,
        authorityKeyIdentifier: AuthorityKeyIdentifier,
        authorityInfoAccess: SEQUENCE_OF(AccessDescription),
        cRLDistributionPoints: CRLDistributionPoints,
        noRevAvail: NULL
    }, function (id) {
        return id === 'auditIdentity' || id === 'targetInformation';
    });

    var Holder = SEQUENCE({
        // the issuer and serial number of the holder's Public Key Certificate
        baseCertificateID: OPTIONAL(CTX(0, IMPLICIT(IssuerSerial))),
        // the name of the claimant or role
        entityName: OPTIONAL(CTX(1, IMPLICIT(GeneralNames))),
        // used to directly authenticate the holder, for example, an executable
        objectDigestInfo: OPTIONAL(CTX(2, IMPLICIT(ObjectDigestInfo)))});

    var AttCertIssuer = CHOICE({
        v1Form: GeneralNames, // MUST NOT be used in this profile
        v2Form: CTX(0, IMPLICIT(V2Form))}, 'v2Form');     // v2 only

    var AttCertValidityPeriod = SEQUENCE({
        notBeforeTime: GeneralizedTime,
        notAfterTime: GeneralizedTime});

    var SvceAuthInfo = SEQUENCE({
        service: GeneralName,
        ident: GeneralName,
        authInfo: OPTIONAL(OCTET_STRING)});

    var RoleSyntax = SEQUENCE({
        roleAuthority: OPTIONAL(CTX(0, IMPLICIT(GeneralNames))),
        roleName: CTX(1, EXPLICIT(GeneralName))}); // GeneralName is CHOICE

    var ClassList = BIT_STRING({
        unmarked: 0,
        unclassified: 1,
        restricted: 2,
        confidential: 3,
        secret: 4,
        topSecret: 5});

    var SecurityCategory = SEQUENCE({
        type: CTX(0, IMPLICIT(OBJECT_IDENTIFIER)),
        value: CTX(1, IMPLICIT(ANY))});

    var Clearance = SEQUENCE({
        policyId: CTX(0, IMPLICIT(OBJECT_IDENTIFIER)),
        classList: DEFAULT(CTX(1, IMPLICIT(ClassList)), ['unclassified']),
        securityCategories: OPTIONAL(CTX(2, IMPLICIT(SET_OF(SecurityCategory))))});

    var IetfAttrSyntax = SEQUENCE({
        policyAuthority: OPTIONAL(CTX(0, IMPLICIT(GeneralNames))),
        values: SEQUENCE_OF(CHOICE({
            octets: OCTET_STRING,
            oid: OBJECT_IDENTIFIER,
            string: UTF8String}, function (value) {
            return isBinary ? 'octets' : getIdentifier(value) ? 'oid' : 'string';
        }))});

    /**
     * X.509 Attribute Certificate Definition<br><br>
     * 
     * X.509 contains the definition of an AC given below.  All types that
     * are not defined in this document can be found in [PKIXPROF].
     * <pre>
     *           AttributeCertificateInfo ::= SEQUENCE {
     *                version              AttCertVersion -- version is v2,
     *                holder               Holder,
     *                issuer               AttCertIssuer,
     *                signature            AlgorithmIdentifier,
     *                serialNumber         CertificateSerialNumber,
     *                attrCertValidityPeriod   AttCertValidityPeriod,
     *                attributes           SEQUENCE OF Attribute,
     *                issuerUniqueID       UniqueIdentifier OPTIONAL,
     *                extensions           Extensions OPTIONAL
     *           }
     * <pre>
     * RFC 3281 references {@link http://tools.ietf.org/html/rfc3281} 
     * 
     * @class GostASN1.AttributeCertificateInfo
     * @extends GostASN1.Sequence
     * @property {number} version The version of the encoded certificate
     * @property {GostASN1.Name} holder Identifies the holder.
     * @property {GostASN1.Name} issuer Identifies the issuer.
     * @property {AlgorithmIdentifier} signature The algorithm identifier for the algorithm used by the CA to sign the certificate.
     * @property {(number|string)} serialNumber The serial number MUST be a positive integer assigned by the CA to each certificate.
     * @property {GostASN1.Validity} attrCertValidityPeriod The certificate validity period
     * @property {GostASN1.Attributes} attributes The certificate attributes
     * @property {CryptoOperationData} issuerUniqueID The issuer unique identifier
     * @property {GostASN1.Extensions} extensions The certificate extensions
     */
    var AttributeCertificateInfo = COMBINE(SEQUENCE({
        version: AttCertVersion, // version is v2,
        holder: Holder,
        issuer: AttCertIssuer,
        signature: SignatureAlgorithmIdentifier,
        serialNumber: CertificateSerialNumber,
        attrCertValidityPeriod: AttCertValidityPeriod,
        attributes: AttributeSequence({
            authenticationInfo: SET_OF(SvceAuthInfo),
            accessIdentity: SET_OF(SvceAuthInfo),
            chargingIdentity: SET_OF_SINGLE(IetfAttrSyntax),
            group: SET_OF_SINGLE(IetfAttrSyntax),
            role: SET_OF(RoleSyntax),
            clearance: SET_OF(Clearance)
        }),
        issuerUniqueID: OPTIONAL(UniqueIdentifier),
        extensions: OPTIONAL(AttCertExtensions)
    }));

    /**
     * Attribute Certificate Profile<br></br>
     *
     * ACs may be used in a wide range of applications and environments
     * covering a broad spectrum of interoperability goals and a broader
     * spectrum of operational and assurance requirements.  The goal of this
     * document is to establish a common baseline for generic applications
     * requiring broad interoperability and limited special purpose
     * requirements.  In particular, the emphasis will be on supporting the
     * use of attribute certificates for informal Internet electronic mail,
     * IPSec, and WWW applications.
     * <pre>
     *           AttributeCertificate ::= SEQUENCE {
     *                acinfo               AttributeCertificateInfo,
     *                signatureAlgorithm   AlgorithmIdentifier,
     *                signatureValue       BIT STRING
     *           }
     * </pre>
     * See {@link GostASN1.AttributeCertificateInfo}<br><br>
     * RFC 3281 references {@link http://tools.ietf.org/html/rfc3281} 
     * 
     * @class GostASN1.AttributeCertificate
     * @extends GostASN1.AttributeCertificateInfo
     * @property {GostASN1.AttributeCertificateInfo} acinfo Attribute certificate information
     * @property {AlgorithmIndentifier} signatureAlgorithm Identifies signature algorithm
     * @property {CryptoOperationData} signatureValue Signature value
     */
    var AttributeCertificate = SEQUENCE({
        acinfo: AttributeCertificateInfo,
        signatureAlgorithm: SignatureAlgorithmIdentifier,
        signatureValue: BIT_STRING}, 'ATTRIBUTE CERTIFICATE');


    /*
     * Encrypted Key with CMS
     * 
     * http://tools.ietf.org/html/rfc5652
     * http://tools.ietf.org/html/rfc4490
     * 
     */

    // RecipientInfo
    var EncryptedKey = OCTET_STRING;

    var EncryptedContent = OCTET_STRING;

    var SubjectKeyIdentifier = OCTET_STRING;

    var UserKeyingMaterial = OCTET_STRING;

    var ECCCMSSharedInfo = SEQUENCE({
        keyInfo: KeyWrapAlgorithmIdentifier,
        entityUInfo: OPTIONAL(CTX(0, EXPLICIT(OCTET_STRING))),
        suppPubInfo: CTX(2, EXPLICIT(OCTET_STRING))
    });

    // GOST Key Transport & Key agreement rfc4490
    var Gost2814789EncryptedKey = ENCLOSURE(SEQUENCE({
        encryptedKey: Gost2814789Key,
        maskKey: OPTIONAL(CTX(0, IMPLICIT(Gost2814789Key))),
        macKey: Gost2814789MAC
    }), {
        encode: function (value) {
            // wrappedKey: (CEK_ENC(32) | CEK_MAC(4))
            var encryptedKey = new Uint8Array(new Uint8Array(value, 0, 32)).buffer,
                    macKey = new Uint8Array(new Uint8Array(value, 32, 4)).buffer;
            return {// from wrapped key
                encryptedKey: encryptedKey,
                macKey: macKey
            };
        },
        decode: function (value) {
            var encryptedKey = value.encryptedKey,
                    maskKey = value.maskKey,
                    macKey = value.macKey;
            if (maskKey) {
                var m = new Int32Array(maskKey), k = new Int32Array(encryptedKey);
                for (var i = 0, n = m.length / k.length; i < n; i++) {
                    for (var j = 0, l = k.length; j < l; j++)
                        k[j] = (k[j] + m[l * i + j]) & 0xffffffff;
                }
            }
            var result = new Uint8Array(encryptedKey.byteLength + macKey.byteLength);
            result.set(new Uint8Array(encryptedKey), 0);
            result.set(new Uint8Array(macKey), 32);
            return result.buffer;
        }
    });


    var GostR3410TransportParameters = SEQUENCE({
        encryptionParamSet: Gost2814789ParamSet,
        ephemeralPublicKey: OPTIONAL(CTX(0, IMPLICIT(GostSubjectPublicKeyInfo))),
        ukm: OCTET_STRING}); // ( SIZE(8) )

    var GostR3410KeyTransport = ENCLOSURE(SEQUENCE({
        sessionEncryptedKey: Gost2814789EncryptedKey,
        transportParameters: OPTIONAL(CTX(0, IMPLICIT(GostR3410TransportParameters)))
    }), {
        encode: function (value) {
            var algorithm = value.algorithm;
            return {
                sessionEncryptedKey: value.sessionEncryptedKey,
                transportParameters: {
                    encryptionParamSet: attributes['sBox'][algorithm.wrapping.sBox || 'E-A'],
                    ephemeralPublicKey: algorithm['public'],
                    ukm: algorithm.ukm
                }
            };
        },
        decode: function (value) {
            return {
                algorithm: {
                    wrapping: parameters[value.transportParameters.encryptionParamSet],
                    ukm: value.transportParameters.ukm,
                    'public': value.transportParameters.ephemeralPublicKey
                },
                sessionEncryptedKey: value.sessionEncryptedKey
            };
        }
    });

    var SCGostKeyTransport = ENCLOSURE(SEQUENCE({
        sessionEncryptedKey: Gost2814789EncryptedKey,
        ukm: SEQUENCE({
            ephemeralPublicKey: GostSubjectPublicKeyInfo,
            addedukm: OPTIONAL(CTX(0, EXPLICIT(UserKeyingMaterial)))})
    }), {
        encode: function (value) {
            var algorithm = value.algorithm;
            return {
                sessionEncryptedKey: value.sessionEncryptedKey,
                ukm: {
                    ephemeralPublicKey: algorithm['public'],
                    addedukm: algorithm.ukm
                }
            };
        },
        decode: function (value) {
            return {
                algorithm: {
                    ukm: value.ukm.addedukm,
                    'public': value.ukm.ephemeralPublicKey
                },
                sessionEncryptedKey: value.sessionEncryptedKey
            };
        }
    });

    var GostEncryptedKey = (function (typeSet) {
        /**
         * Gost Encrypted key encoder for CMS
         * 
         * @class GostASN1.GostEncryptedKey
         * @extends GostASN1.Sequence
         * @param {AlgorithmIdentifier} algorithm
         */
        return function (algorithm) {
            var type = typeSet[algorithm.id];
            return type ? ENCAPSULATES(type) : ANY;
        };
    })({
        // Key transport algorithms
        'id-sc-gostR3410-2001': SCGostKeyTransport,
        'id-sc-gostR3410-94': SCGostKeyTransport,
        'id-GostR3410-2001': GostR3410KeyTransport,
        'id-GostR3410-94': GostR3410KeyTransport,
        'id-tc26-gost3410-12-256': GostR3410KeyTransport,
        'id-tc26-gost3410-12-512': GostR3410KeyTransport,
        // Key agreement algorithms
        'id-GostR3410-94-CryptoPro-ESDH': Gost2814789EncryptedKey,
        'id-GostR3410-2001-CryptoPro-ESDH': Gost2814789EncryptedKey,
        'id-tc26-agreement-gost-3410-12-256': Gost2814789EncryptedKey,
        'id-tc26-agreement-gost-3410-12-512': Gost2814789EncryptedKey,
        'id-sc-r3410-ESDH-r3411kdf': Gost2814789EncryptedKey,
        // Key encryption key algorithms
        'id-Gost28147-89-None-KeyWrap': Gost2814789EncryptedKey,
        'id-Gost28147-89-CryptoPro-KeyWrap': Gost2814789EncryptedKey,
        'id-sc-cmsGostWrap': Gost2814789EncryptedKey,
        'id-sc-cmsGost28147Wrap': Gost2814789EncryptedKey});



    /*
     * CryptoPro Gost Private Key Store
     */

    var GostKeyContainerContentAttributes = BIT_STRING({
        kccaSoftPassword: 0,
        kccaReservePrimary: 1,
        kccaPrimaryKeyAbsent: 2,
        kccaFKCShared: 3});

    var GostPrivateKeyAttributes = BIT_STRING({
        pkaExportable: 0,
        pkaUserProtect: 1,
        pkaExchange: 2,
        pkaEphemeral: 3,
        pkaNonCachable: 4,
        pkaDhAllowed: 5
    });

    var GostPrivateKeyParameters = SEQUENCE({
        attributes: OPTIONAL(GostPrivateKeyAttributes),
        privateKeyAlgorithm: OPTIONAL(CTX(0, IMPLICIT(KeyAlgorithmIdentifier)))
    });

    var CertificateLink = SEQUENCE({
        path: IA5String,
        hmac: Gost2814789MAC
    });

    var PasswordPolicy = AlgorithmIdentifier;

    var GostKeyContainerContent = SEQUENCE({
        containerAlgoritmIdentifier: OPTIONAL(CTX(0, IMPLICIT(AlgorithmIdentifier))),
        containerName: OPTIONAL(IA5String),
        attributes: GostKeyContainerContentAttributes,
        primaryPrivateKeyParameters: GostPrivateKeyParameters,
        hmacPassword: OPTIONAL(CTX(2, IMPLICIT(Gost2814789MAC))),
        secondaryEncryptedPrivateKey: OPTIONAL(CTX(3, IMPLICIT(Gost2814789EncryptedKey))),
        secondaryPrivateKeyParameters: OPTIONAL(CTX(4, IMPLICIT(GostPrivateKeyParameters))),
        primaryCertificate: OPTIONAL(CTX(5, IMPLICIT(OCTET_STRING(ENCAPSULATES(Certificate))))),
        secondaryCertificate: OPTIONAL(CTX(6, IMPLICIT(OCTET_STRING(ENCAPSULATES(Certificate))))),
        encryptionContainerName: OPTIONAL(CTX(7, IMPLICIT(IA5String))),
        primaryCertificateLink: OPTIONAL(CTX(8, IMPLICIT(CertificateLink))),
        secondaryCertificateLink: OPTIONAL(CTX(9, IMPLICIT(CertificateLink))),
        primaryFP: OPTIONAL(CTX(10, IMPLICIT(OCTET_STRING))),
        secondaryFP: OPTIONAL(CTX(11, IMPLICIT(OCTET_STRING))),
        passwordPolicy: OPTIONAL(PasswordPolicy),
        containerSecurityLevel: OPTIONAL(INTEGER),
        extensions: OPTIONAL(CTX(12, IMPLICIT(Extensions({
            keyValidity: SEQUENCE({
                notBefore: OPTIONAL(CTX(0, IMPLICIT(GeneralizedTime))),
                notAfter: OPTIONAL(CTX(1, IMPLICIT(GeneralizedTime)))})
        })))),
        secondaryEncryptionContainerName: OPTIONAL(CTX(13, IMPLICIT(IA5String)))
    });

    /**
     * CryptoPro key container header
     * 
     * @class GostASN1.GostKeyContainer
     * @extends GostASN1.Sequence
     */
    var GostKeyContainer = SEQUENCE({
        keyContainerContent: GostKeyContainerContent,
        hmacKeyContainerContent: Gost2814789MAC
    });

    /**
     * CryptoPro key container name
     * 
     * @class GostASN1.GostKeyContainerName
     * @extends GostASN1.Sequence
     */
    var GostKeyContainerName = SEQUENCE({
        containerName: IA5String,
        extElem1: OPTIONAL(ANY)
    });

    /**
     * PrivateKey encrypted content for CryptoPro key containers
     * 
     * @class GostASN1.GostPrivateKeys
     * @extends GostASN1.Sequence
     */
    var GostPrivateKeys = SEQUENCE({
        primaryKey: Gost2814789Key,
        secondaryKey: OPTIONAL(Gost2814789Key),
        hmacKey: OPTIONAL(Gost2814789MAC)
    });

    /**
     * PrivateKey masks for CryptoPro key containers
     * 
     * @class GostASN1.GostPrivateMasks
     * @extends GostASN1.Sequence
     */
    var GostPrivateMasks = SEQUENCE({
        mask: Gost2814789Key,
        randomStatus: OCTET_STRING,
        hmacRandom: Gost2814789MAC
    });



    /*
     * ViPNet Gost Private Key Store
     */

    var ViPNetKeyInfo = SEQUENCE({
        keyClass: INTEGER,
        keyType: INTEGER,
        algorithm: OPTIONAL(CTX(0, EXPLICIT(KeyAlgorithmIdentifier))),
        serialNumber: OPTIONAL(CTX(1, EXPLICIT(OCTET_STRING))),
        addSerialNumber: OPTIONAL(CTX(2, EXPLICIT(OCTET_STRING))),
        certSerialNumber: OPTIONAL(CTX(3, EXPLICIT(OCTET_STRING))),
        subjectUID: OPTIONAL(CTX(4, EXPLICIT(OCTET_STRING))),
        recipientUID: OPTIONAL(CTX(5, EXPLICIT(OCTET_STRING))),
        validity: OPTIONAL(CTX(6, EXPLICIT(CHOICE({
            validity: Validity,
            keyValidity: SEQUENCE({
                notBefore: OPTIONAL(CTX(0, IMPLICIT(GeneralizedTime))),
                notAfter: OPTIONAL(CTX(1, IMPLICIT(GeneralizedTime)))})
        }, function () {
            return 'keyValidity';
        })))),
        keyUID: OPTIONAL(CTX(7, EXPLICIT(BIT_STRING))),
        flags: OPTIONAL(CTX(10, EXPLICIT(INTEGER)))
    });

    /**
     * ViPNet key container info
     * 
     * @class GostASN1.ViPNetInfo
     * @extends GostASN1.Sequence
     */
    var ViPNetInfo = SEQUENCE({
        version: INTEGER,
        keyInfo: ViPNetKeyInfo,
        defenceKeyInfo: ViPNetKeyInfo,
        certificate: OPTIONAL(CTX(0, EXPLICIT(Certificate))),
        publicKey: OPTIONAL(CTX(1, EXPLICIT(OCTET_STRING)))
    });



    /*
     * Cryptographic Message Syntax
     * 
     * http://tools.ietf.org/html/rfc5652
     * 
     */

    // CMS signed data
    var CMSVersion = INTEGER;

    var ContentType = OBJECT_IDENTIFIER;

    var SigningTime = Time;

    var SubjectKeyIdentifier = OCTET_STRING;

    var Digest = OCTET_STRING;

    var MessageAuthenticationCode = OCTET_STRING;

    var BodyPartID = INTEGER;

    var BodyPartPath = SEQUENCE_OF(BodyPartID);

    var CMCUnsignedData = SEQUENCE({
        bodyPartPath: BodyPartPath,
        identifier: OBJECT_IDENTIFIER,
        content: ANY}); // DEFINED BY identifier
    /**
     * SignedAttributes is a collection of attributes that are signed.  The
     * field is optional, but it MUST be present if the content type of
     * the EncapsulatedContentInfo value being signed is not id-data.
     * SignedAttributes MUST be DER encoded, even if the rest of the
     * structure is BER encoded.  Useful attribute types, such as signing
     * time, are defined in Section 11.  If the field is present, it MUST
     * contain, at a minimum, the following two attributes: <br>
     *
     * A content-type attribute having as its value the content type
     * of the EncapsulatedContentInfo value being signed.  Section
     * 11.1 defines the content-type attribute.  However, the
     * content-type attribute MUST NOT be used as part of a
     * countersignature unsigned attribute as defined in Section 11.4.<br>
     *
     * A message-digest attribute, having as its value the message
     * digest of the content.  Section 11.2 defines the message-digest
     * attribute.
     * 
     * @class GostASN1.SignedAttributes
     * @extends GostASN1.Attributes
     */
    var SignedAttributes = Attributes({
        contentType: SET_OF_SINGLE(ContentType),
        signingTime: SET_OF_SINGLE(SigningTime),
        messageDigest: SET_OF_SINGLE(OCTET_STRING)});

    var UnsignedAttributes = Attributes(function (type) {
        /**
         * UnsignedAttributes is a collection of attributes that are not signed.
         * The field is optional.  Useful attribute types, such as
         * countersignatures.
         * 
         * @class GostASN1.UnsignedAttributes
         * @extends GostASN1.Attributes
         */
        //    var UnsignedAttributes = Attributes({
        //        countersignature: SET_OF(Countersignature), // -- check forward
        //        unsignedData: SET_OF(CMCUnsignedData)
        //    });
        return ({
            countersignature: SET_OF(Countersignature), // recursion
            unsignedData: SET_OF(CMCUnsignedData)
        })[type];
    });

    var AuthAttributes = SignedAttributes,
            UnauthAttributes = Attributes,
            UnprotectedAttributes = Attributes;

    var IssuerAndSerialNumber = SEQUENCE({
        issuer: Name,
        serialNumber: CertificateSerialNumber});

    var SignerIdentifier = CHOICE({
        issuerAndSerialNumber: IssuerAndSerialNumber,
        subjectKeyIdentifier: CTX(0, IMPLICIT(SubjectKeyIdentifier))}, function (value) {
        return isBinary(value) ? 'subjectKeyIdentifier' : 'issuerAndSerialNumber';
    });

    var SignerInfo = SEQUENCE({
        version: CMSVersion,
        sid: SignerIdentifier,
        digestAlgorithm: DigestAlgorithmIdentifier,
        signedAttrs: OPTIONAL(CTX(0, IMPLICIT(SignedAttributes))),
        signatureAlgorithm: SignatureAlgorithmIdentifier,
        signatureValue: OCTET_STRING,
        unsignedAttrs: OPTIONAL(CTX(1, IMPLICIT(UnsignedAttributes)))});

    var Countersignature = SignerInfo,
            SignerInfos = SET_OF(SignerInfo),
            DigestAlgorithmIdentifiers = SET_OF(DigestAlgorithmIdentifier),
            AttributeCertificateV2 = AttributeCertificate;

    var ExtendedCertificateInfo = COMBINE(SEQUENCE({
        version: CMSVersion,
        certificate: Certificate,
        attributes: UnauthAttributes}));

    var ExtendedCertificate = SEQUENCE({
        extendedCertificateInfo: ExtendedCertificateInfo,
        signatureAlgorithm: SignatureAlgorithmIdentifier,
        signatureValue: BIT_STRING});

    var OtherCertificateFormat = SEQUENCE({
        otherCertFormat: OBJECT_IDENTIFIER,
        otherCert: ANY});

    var AttributeCertificateInfoV1 = COMBINE(SEQUENCE({
        version: INTEGER,
        subject: CHOICE({
            baseCertificateID: CTX(0, IMPLICIT(IssuerSerial)), // associated with a Public Key Certificate
            subjectName: CTX(1, IMPLICIT(GeneralNames))}, function (value) {
            return value.issuer ? 'baseCertificateID' : 'subjectName';
        }), //associated with a name
        issuer: GeneralNames,
        signature: SignatureAlgorithmIdentifier,
        serialNumber: CertificateSerialNumber,
        attCertValidityPeriod: AttCertValidityPeriod,
        attributes: AttributeSequence,
        issuerUniqueID: OPTIONAL(UniqueIdentifier),
        extensions: OPTIONAL(CertExtensions)}));

    var AttributeCertificateV1 = SEQUENCE({
        acInfo: AttributeCertificateInfoV1,
        signatureAlgorithm: SignatureAlgorithmIdentifier,
        signatureValue: BIT_STRING});

    var EncapsulatedContentInfo = SEQUENCE({
        eContentType: ContentType,
        eContent: OPTIONAL(CTX(0, EXPLICIT(OCTET_STRING)))});

    var CertificateChoices = CHOICE({
        certificate: Certificate,
        extendedCertificate: CTX(0, IMPLICIT(ExtendedCertificate)), // Obsolete
        v1AttrCert: CTX(1, IMPLICIT(AttributeCertificateV1)), // Obsolete
        v2AttrCert: CTX(2, IMPLICIT(AttributeCertificateV2)),
        other: CTX(3, IMPLICIT(OtherCertificateFormat))}, function (value) {
        return value.holder ? 'AttributeCertificateV2' : value.certificate ?
                'ExtendedCertificate' : value.otherCertFormat ? 'other' :
                'certificate';
    });

    var OtherRevocationInfoFormat = SEQUENCE({
        otherRevInfoFormat: OBJECT_IDENTIFIER,
        otherRevInfo: ANY});

    var RevocationInfoChoice = CHOICE({
        crl: CertificateList,
        other: CTX(1, IMPLICIT(OtherRevocationInfoFormat))}, function (value) {
        return value.otherRevInfoFormat ? 'other' : 'crl';
    });

    var CertificateSet = SET_OF(CertificateChoices),
            RevocationInfoChoices = SET_OF(RevocationInfoChoice);

    /**
     * The signed-data content type consists of a content of any type and zero or more 
     * signature values.  Any number of signers in parallel can sign any type of content.<br><br>
     * 
     * The signed-data content type shall have ASN.1 type SignedData:<br><br>
     *<pre>
     *
     *      SignedData ::= SEQUENCE {
     *        version CMSVersion,
     *        digestAlgorithms DigestAlgorithmIdentifiers,
     *        encapContentInfo EncapsulatedContentInfo,
     *        certificates [0] IMPLICIT CertificateSet OPTIONAL,
     *        crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
     *        signerInfos SignerInfos }
     *
     *      DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
     *
     *      SignerInfos ::= SET OF SignerInfo
     *      
     *       EncapsulatedContentInfo ::= SEQUENCE {
     *        eContentType ContentType,
     *        eContent [0] EXPLICIT OCTET STRING OPTIONAL }
     *        
     *</pre>
     * Per-signer information is represented in the type SignerInfo:<br><br>
     *<pre>
     *
     *      SignerInfo ::= SEQUENCE {
     *        version CMSVersion,
     *        sid SignerIdentifier,
     *        digestAlgorithm DigestAlgorithmIdentifier,
     *        signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
     *        signatureAlgorithm SignatureAlgorithmIdentifier,
     *        signature SignatureValue,
     *        unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }
     *
     *      SignerIdentifier ::= CHOICE {
     *        issuerAndSerialNumber IssuerAndSerialNumber,
     *        subjectKeyIdentifier [0] SubjectKeyIdentifier }
     *
     *      SignedAttributes ::= SET SIZE (1..MAX) OF Attribute
     *
     *      UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute
     *
     *     SignatureValue ::= OCTET STRING
     *     
     *</pre>
     * See also {@link GostASN1.SignedAttributes} and {@link GostASN1.UnsignedAttributes}
     * @class GostASN1.SignedData
     * @extends GostASN1.Sequence
     * @property {number} version The syntax version number
     * @property {AlgorithmIdentifier[]} digestAlgorithms Collection of message digest algorithm identifiers
     * @property {GostASN1.Sequence} encapContentInfo The content is represented in the type EncapsulatedContentInfo
     * @property {GostASN1.Certificate[]} certificates Certificates
     * @property {GostASN1.CertificateList[]} crls Certificates
     * @property {GostASN1.Sequence[]} signerInfos The Signer information
     */
    var SignedData = SEQUENCE({
        version: CMSVersion,
        digestAlgorithms: DigestAlgorithmIdentifiers,
        encapContentInfo: EncapsulatedContentInfo,
        certificates: OPTIONAL(CTX(0, IMPLICIT(CertificateSet))),
        crls: OPTIONAL(CTX(1, IMPLICIT(RevocationInfoChoices))),
        signerInfos: SignerInfos});

    var RecipientIdentifier = CHOICE({
        issuerAndSerialNumber: IssuerAndSerialNumber,
        subjectKeyIdentifier: CTX(0, IMPLICIT(SubjectKeyIdentifier))}, function (value) {
        return isBinary(value) ? 'subjectKeyIdentifier' : 'issuerAndSerialNumber';
    });

    var KeyTransRecipientInfo = SEQUENCE({
        version: CMSVersion, // always set to 0 or 2
        rid: RecipientIdentifier,
        keyEncryptionAlgorithm: KeyEncryptionAlgorithmIdentifier,
        encryptedKey: EncryptedKey});

    var OtherKeyAttribute = SEQUENCE({
        keyAttrId: OBJECT_IDENTIFIER,
        keyAttr: OPTIONAL(ANY)});

    var RecipientKeyIdentifier = SEQUENCE({
        subjectKeyIdentifier: SubjectKeyIdentifier,
        date: OPTIONAL(GeneralizedTime),
        other: OPTIONAL(OtherKeyAttribute)});

    var KeyAgreeRecipientIdentifier = CHOICE({
        issuerAndSerialNumber: IssuerAndSerialNumber,
        rKeyId: CTX(0, IMPLICIT(RecipientKeyIdentifier))}, function (value) {
        return isBinary(value) ? 'rKeyId' : 'issuerAndSerialNumber';
    });

    var RecipientEncryptedKey = SEQUENCE({
        rid: KeyAgreeRecipientIdentifier,
        encryptedKey: EncryptedKey});

    var RecipientEncryptedKeys = SEQUENCE_OF(RecipientEncryptedKey);

    var OriginatorPublicKey = SEQUENCE({
        algorithm: KeyAlgorithmIdentifier,
        publicKey: BIT_STRING});

    var MQVuserKeyingMaterial = SEQUENCE({// ECC rfc5753 KeyAgreeRecipientInfo in ukm
        ephemeralPublicKey: OriginatorPublicKey,
        addedukm: OPTIONAL(CTX(0, EXPLICIT(UserKeyingMaterial)))
    });

    var OriginatorIdentifierOrKey = CHOICE({
        issuerAndSerialNumber: IssuerAndSerialNumber,
        subjectKeyIdentifier: CTX(0, IMPLICIT(SubjectKeyIdentifier)),
        originatorKey: CTX(1, IMPLICIT(OriginatorPublicKey))}, function (value) {
        return isBinary(value) ? 'subjectKeyIdentifier' : value.algorithm ?
                'originatorKey' : 'issuerAndSerialNumber';
    });

    var KeyAgreeRecipientInfo = SEQUENCE({
        version: CMSVersion, // always set to 3
        originator: CTX(0, EXPLICIT(OriginatorIdentifierOrKey)),
        ukm: OPTIONAL(CTX(1, EXPLICIT(UserKeyingMaterial))),
        keyEncryptionAlgorithm: KeyEncryptionAlgorithmIdentifier,
        recipientEncryptedKeys: RecipientEncryptedKeys});

    var KEKIdentifier = SEQUENCE({
        keyIdentifier: OCTET_STRING,
        date: OPTIONAL(GeneralizedTime),
        other: OPTIONAL(OtherKeyAttribute)});

    var KEKRecipientInfo = SEQUENCE({
        version: CMSVersion, // always set to 4
        kekid: KEKIdentifier,
        keyEncryptionAlgorithm: KeyEncryptionAlgorithmIdentifier,
        encryptedKey: EncryptedKey});

    var PasswordRecipientInfo = SEQUENCE({
        version: CMSVersion, // always set to 0
        friendlyName: OPTIONAL(CTX(0, IMPLICIT(KeyDerivationAlgorithmIdentifier))),
        keyEncryptionAlgorithm: KeyEncryptionAlgorithmIdentifier,
        encryptedKey: EncryptedKey});

    var OtherRecipientInfo = SEQUENCE({
        oriType: OBJECT_IDENTIFIER,
        oriValue: ANY});

    var RecipientInfo = CHOICE({
        ktri: KeyTransRecipientInfo,
        kari: CTX(1, IMPLICIT(KeyAgreeRecipientInfo)),
        kekri: CTX(2, IMPLICIT(KEKRecipientInfo)),
        pwri: CTX(3, IMPLICIT(PasswordRecipientInfo)),
        ori: CTX(4, IMPLICIT(OtherRecipientInfo))}, function (value) {
        return value.rid ? 'ktri' : value.originator ? 'kari' :
                value.kekid ? 'kekri' : value.oriType ? 'ori' : 'pwri';
    });

    var OriginatorInfo = SEQUENCE({
        certs: OPTIONAL(CTX(0, IMPLICIT(CertificateSet))),
        crls: OPTIONAL(CTX(1, IMPLICIT(RevocationInfoChoices)))});

    var RecipientInfos = SET_OF(RecipientInfo);

    // EncryptedContentInfo
    var EncryptedContentInfo = SEQUENCE({
        contentType: ContentType,
        contentEncryptionAlgorithm: ContentEncryptionAlgorithmIdentifier,
        encryptedContent: OPTIONAL(CTX(0, IMPLICIT(EncryptedContent)))});

    /**
     * The enveloped-data content type consists of an encrypted content of 
     * any type and encrypted content-encryption keys for one or more
     * recipients.  The combination of the encrypted content and one
     * encrypted content-encryption key for a recipient is a "digital
     * envelope" for that recipient.  Any type of content can be enveloped
     * for an arbitrary number of recipients using any of the supported key
     * management techniques for each recipient.<br><br>   
     * 
     * The typical application of the enveloped-data content type will
     * represent one or more recipients' digital envelopes on content of the
     * data or signed-data content types.<br><br>
     * <pre>
     * 
     *      EnvelopedData ::= SEQUENCE {
     *        version CMSVersion,
     *        originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
     *        recipientInfos RecipientInfos,
     *        encryptedContentInfo EncryptedContentInfo,
     *        unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
     * 
     *      OriginatorInfo ::= SEQUENCE {
     *        certs [0] IMPLICIT CertificateSet OPTIONAL,
     *        crls [1] IMPLICIT RevocationInfoChoices OPTIONAL }
     *
     *      RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo
     *
     *      EncryptedContentInfo ::= SEQUENCE {
     *        contentType ContentType,
     *        contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
     *        encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
     *
     *      EncryptedContent ::= OCTET STRING
     *
     *      UnprotectedAttributes ::= SET SIZE (1..MAX) OF Attribute
     *      
     * </pre>
     * @class GostASN1.EnvelopedData
     * @extends GostASN1.Sequence
     * @property {number} version The syntax version number
     * @property {GostASN1.Sequence} originatorInfo Optionally provides information about the originator.
     * @property {GostASN1.Sequence[]} recipientInfos Collection of per-recipient information. 
     * @property {GostASN1.Sequence} encryptedContentInfo The content is represented in the type EncryptedContentInfo
     * @property {Attributes} unprotectedAttrs The unprotected attributes
     */
    var EnvelopedData = SEQUENCE({
        version: CMSVersion,
        originatorInfo: OPTIONAL(CTX(0, IMPLICIT(OriginatorInfo))),
        recipientInfos: RecipientInfos,
        encryptedContentInfo: EncryptedContentInfo,
        unprotectedAttrs: OPTIONAL(CTX(1, IMPLICIT(UnprotectedAttributes)))});

    /**
     * The digested-data content type consists of content of any type and a
     * message digest of the content.<br><br>
     * Typically, the digested-data content type is used to provide content
     * integrity, and the result generally becomes an input to the
     * enveloped-data content type.<br><br>
     * <pre>
     * 
     *      DigestedData ::= SEQUENCE {
     *        version CMSVersion,
     *        digestAlgorithm DigestAlgorithmIdentifier,
     *        encapContentInfo EncapsulatedContentInfo,
     *        digest Digest }
     *
     *      Digest ::= OCTET STRING
     *      
     *</pre>
     * @class GostASN1.DigestedData
     * @extends GostASN1.Sequence
     * @property {number} version The syntax version number
     * @property {AlgorithmIdentifier} digestAlgorithm Message digest algorithm identifier
     * @property {GostASN1.Sequence} encapContentInfo The content is represented in the type EncapsulatedContentInfo
     * @property {CryptoOperationData} digest The degist
     */
    var DigestedData = SEQUENCE({
        version: CMSVersion,
        digestAlgorithm: DigestAlgorithmIdentifier,
        encapContentInfo: EncapsulatedContentInfo,
        digest: Digest});

    /**
     * The encrypted-data content type consists of encrypted content of any
     * type.  Unlike the enveloped-data content type, the encrypted-data
     * content type has neither recipients nor encrypted content-encryption
     * keys.  Keys MUST be managed by other means.<br><br>
     * 
     * The typical application of the encrypted-data content type will be to
     * encrypt the content of the data content type for local storage,
     * perhaps where the encryption key is derived from a password.<br><br>
     * <pre>
     * 
     *      EncryptedData ::= SEQUENCE {
     *        version CMSVersion,
     *        encryptedContentInfo EncryptedContentInfo,
     *        unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
     *        
     *      EncryptedContentInfo ::= SEQUENCE {
     *        contentType ContentType,
     *        contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
     *        encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
     *
     *      EncryptedContent ::= OCTET STRING
     *      
     * </pre>
     * @class GostASN1.EncryptedData
     * @extends GostASN1.Sequence
     * @property {number} version The syntax version number
     * @property {GostASN1.Sequence} encryptedContentInfo The content is represented in the type EncryptedContentInfo
     * @property {Attributes} unprotectedAttrs The unprotected attributes
     */
    var EncryptedData = SEQUENCE({
        version: CMSVersion,
        encryptedContentInfo: EncryptedContentInfo,
        unprotectedAttrs: OPTIONAL(CTX(1, IMPLICIT(UnprotectedAttributes)))});

    /**
     * The authenticated-data content type consists of content of any type, 
     * a message authentication code (MAC), and encrypted authentication   
     * keys for one or more recipients.  The combination of the MAC and one
     * encrypted authentication key for a recipient is necessary for that
     * recipient to verify the integrity of the content.  Any type of
     * content can be integrity protected for an arbitrary number of
     * recipients.<br><br>
     * <pre>
     * 
     *      AuthenticatedData ::= SEQUENCE {
     *        version CMSVersion,
     *        originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
     *        recipientInfos RecipientInfos,
     *        macAlgorithm MessageAuthenticationCodeAlgorithm,
     *        digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
     *        encapContentInfo EncapsulatedContentInfo,
     *        authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
     *        mac MessageAuthenticationCode,
     *        unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
     *
     *      AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
     *
     *      UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
     *
     *      MessageAuthenticationCode ::= OCTET STRING
     *
     * </pre>
     * @class GostASN1.AuthenticatedData
     * @extends GostASN1.Sequence
     * @property {number} version The syntax version number
     * @property {GostASN1.Sequence} originatorInfo Optionally provides information about the originator.
     * @property {GostASN1.Sequence[]} recipientInfos Collection of per-recipient information. 
     * @property {AlgorithmIdentifier} macAlgorithm Identifies the Message Authentication Code algorithm 
     * @property {AlgorithmIdentifier} digestAlgorithm Identifies the Digest algorithm 
     * @property {GostASN1.Sequence} encapContentInfo The content is represented in the type EncapsulatedContentInfo
     * @property {Attributes} authAttrs The autheniticated attributes
     * @property {CryptoOpertionData} mac The Message Authentication Code
     * @property {Attributes} unauthAttrs The unautheniticated attributes
     */
    var AuthenticatedData = SEQUENCE({
        version: CMSVersion,
        originatorInfo: OPTIONAL(CTX(0, IMPLICIT(OriginatorInfo))),
        recipientInfos: RecipientInfos,
        macAlgorithm: MessageAuthenticationCodeAlgorithm,
        digestAlgorithm: OPTIONAL(CTX(1, DigestAlgorithmIdentifier)),
        encapContentInfo: EncapsulatedContentInfo,
        authAttrs: OPTIONAL(CTX(2, IMPLICIT(AuthAttributes))),
        mac: MessageAuthenticationCode,
        unauthAttrs: OPTIONAL(CTX(3, IMPLICIT(UnauthAttributes)))});

    // AuthEnvelopedData RFC 5911
    var AuthEnvelopedData = SEQUENCE({
        version: CMSVersion,
        originatorInfo: OPTIONAL(CTX(0, IMPLICIT(OriginatorInfo))),
        recipientInfos: RecipientInfos,
        authEncryptedContentInfo: EncryptedContentInfo,
        authAttrs: OPTIONAL(CTX(1, IMPLICIT(AuthAttributes))),
        mac: MessageAuthenticationCode,
        unauthAttrs: OPTIONAL(CTX(2, IMPLICIT(UnauthAttributes)))});

    // EncryptedKeyPackage rfc6032
    var EncryptedKeyPackage = CHOICE({
        encrypted: EncryptedData,
        enveloped: CTX(0, IMPLICIT(EnvelopedData)),
        authEnveloped: CTX(1, IMPLICIT(AuthEnvelopedData))}, function (value) {
        return value.encryptedContentInfo ? (value.recipientInfos ?
                'enveloped' : 'encrypted') : 'authEnveloped';
    });

    /**
     * Cryptographic Message Syntax<br>
     * The CMS associates a content type identifier with a content. The syntax 
     * MUST have ASN.1 type ContentInfo:
     * <pre>
     * 
     *  ContentInfo ::= SEQUENCE {
     *    contentType ContentType,
     *    content [0] EXPLICIT ANY DEFINED BY contentType }
     *
     *  ContentType ::= OBJECT IDENTIFIER
     *  
     * </pre>
     * The fields of ContentInfo have the following meanings:
     * <ul>
     * <li>contentType indicates the type of the associated content.  It is
     * an object identifier; it is a unique string of integers assigned
     * by an authority that defines the content type.</li>
     * <li>content is the associated content.  The type of content can be
     * determined uniquely by contentType.  Content types for data,
     * signed-data, enveloped-data, digested-data, encrypted-data, and
     * authenticated-data are defined in this document.  If additional
     * content types are defined in other documents, the ASN.1 type
     * defined SHOULD NOT be a CHOICE type.</li>
     * </ul>
     * RFC 5652 references {@link http://tools.ietf.org/html/rfc5652} 
     * 
     * @class GostASN1.ContentInfo
     * @extends GostASN1.Sequence
     * @property {string} contentType The content type identifier
     * @property {(GostASN1.Sequence|CryptoOperationData)} content The content
     */
    var ContentType = OBJECT_IDENTIFIER;

    var ContentInfo = ATTRIBUTE({
        contentType: ContentType,
        content: function (type) {
            return CTX(0, EXPLICIT(type));
        }
    }, 'contentType', 'content', undefined, 'CMS')({
        data: OCTET_STRING,
        signedData: COMBINE(SignedData),
        envelopedData: COMBINE(EnvelopedData),
        digestedData: COMBINE(DigestedData),
        encryptedData: COMBINE(EncryptedData),
        authData: COMBINE(AuthenticatedData),
        encryptedKeyPkg: COMBINE(EncryptedKeyPackage),
        aKeyPackage: COMBINE(AsymmetricKeyPackage)});

    var DigestInfo = SEQUENCE({
        digestAlgorithm: DigestAlgorithmIdentifier,
        digest: Digest});


    /*
     * PFX format syntax PKCS#12
     * 
     * http://tools.ietf.org/html/rfc7292
     * 
     */

    var PKCS12Attributes = Attributes({
        friendlyName: SET_OF_SINGLE(BMPString),
        keyProviderNameAttr: SET_OF_SINGLE(BMPString),
        localKeyId: SET_OF_SINGLE(OCTET_STRING),
        certKeyIdentifierPropId: SET_OF_SINGLE(OCTET_STRING)});

    var SafeBagType = OBJECT_IDENTIFIER;

    var CertType = OBJECT_IDENTIFIER;

    var CRLType = OBJECT_IDENTIFIER;

    var SecretType = OBJECT_IDENTIFIER;

    var KeyBag = PrivateKeyInfo;

    var PKCS8ShroudedKeyBag = EncryptedPrivateKeyInfo;

    var CertBag = ATTRIBUTE({
        certId: CertType,
        certValue: function (type) {
            return CTX(0, EXPLICIT(type));
        }
    }, 'certId', 'certValue')({
        // DER-encoded X.509 certificate stored in OCTET STRING
        x509Certificate: OCTET_STRING(ENCAPSULATES(Certificate)),
        // Base64-encoded SDSI certificate stored in IA5String
        sdsiCertificate: IA5String
    }, OCTET_STRING);

    var CRLBag = ATTRIBUTE({
        crlId: CRLType,
        crlValue: function (type) {
            return CTX(0, EXPLICIT(type));
        }
    }, 'crlId', 'crlValue')({
        // DER-encoded X.509 certificate stored in OCTET STRING
        x509CRL: OCTET_STRING(ENCAPSULATES(CertificateList))
    }, OCTET_STRING);

    var SecretBag = ATTRIBUTE({
        secretTypeId: SecretType,
        secretValue: function (type) {
            return CTX(0, EXPLICIT(type));
        }
    }, 'secretTypeId', 'secretValue')({
        secret: OCTET_STRING
    }, OCTET_STRING);

    var SafeBag = ATTRIBUTE({
        bagId: SafeBagType,
        bagValue: function (type) {
            return CTX(0, EXPLICIT(type));
        },
        bagAttributes: OPTIONAL(PKCS12Attributes)
    }, 'bagId', 'bagValue')(function (type) {
        return ({
            keyBag: KeyBag,
            pkcs8ShroudedKeyBag: PKCS8ShroudedKeyBag,
            certBag: CertBag,
            crlBag: CRLBag,
            secretBag: SecretBag,
            safeContentsBag: SafeContents // recursion
        })[type];
    });

    /**
     * The SafeContents Type<br><br>
     * 
     * The sixth type of bag that can be held in a SafeBag is a
     * SafeContents. This recursive structure allows for arbitrary nesting
     * of multiple KeyBags, PKCS8ShroudedKeyBags, CertBags, CRLBags, and
     * SecretBags within the top-level SafeContents.
     * <pre>
     *  SafeContents ::= SEQUENCE OF SafeBag
     *   SafeBag ::= SEQUENCE {
     *       bagId BAG-TYPE.&id ({PKCS12BagSet})
     *       bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}),
     *       bagAttributes SET OF PKCS12Attribute OPTIONAL
     *   }
     *   
     *   PKCS12Attribute ::= SEQUENCE {
     *       attrId ATTRIBUTE.&id ({PKCS12AttrSet}),
     *       attrValues SET OF ATTRIBUTE.&Type ({PKCS12AttrSet}{@attrId})
     *   } -- This type is compatible with the X.500 type ’Attribute’
     *   
     *   PKCS12AttrSet ATTRIBUTE ::= {
     *       friendlyName | -- from PKCS #9 [23]
     *       localKeyId, -- from PKCS #9
     *       ... -- Other attributes are allowed
     *   }
     * </pre>
     * The SafeContents type is made up of SafeBags. Each SafeBag holds one
     * piece of information -- a key, a certificate, etc. -- which is
     * identified by an object identifier.<br><br>
     * 
     * See {@link GostASN1.ContentInfo} and {@link GostASN1.PFX}<br><br>
     * 
     * RFC 7292 references {@link http://tools.ietf.org/html/rfc7292} 
     * @class GostASN1.SafeContents
     */
    var SafeContents = SEQUENCE_OF(SafeBag);

    /**
     * The AuthenticatedSafe<br><br>
     * Each compliant platform shall be able to import and export
     * AuthenticatedSafe PDUs wrapped in PFX PDUs.<br>
     * For integrity, the AuthenticatedSafe is either signed (if public-key
     * integrity mode is used) or MACed (if password integrity mode is used)
     * to produce a PFX PDU.
     * <pre>
     *      AuthenticatedSafe ::= SEQUENCE OF ContentInfo
     * 
     *      -- Data if unencrypted
     *      -- EncryptedData if password-encrypted
     *      -- EnvelopedData if public key-encrypted
     * </pre>
     * As mentioned, the contentType field of authSafe shall be of type data
     * or signedData. The content field of the authSafe shall, either
     * directly (data case) or indirectly (signedData case), contain a BER-
     * encoded value of type AuthenticatedSafe.<br><br>
     * 
     * See {@link GostASN1.ContentInfo} and {@link GostASN1.PFX}<br><br>
     * 
     * RFC 7292 references {@link http://tools.ietf.org/html/rfc7292} 
     * 
     * @class GostASN1.AuthenticatedSafe
     */
    var AuthenticatedSafe = SEQUENCE_OF(ContentInfo);

    var MacData = SEQUENCE({
        mac: DigestInfo,
        macSalt: OCTET_STRING,
        // Note: The default is for historical reasons and its use is deprecated.
        iterations: DEFAULT(INTEGER, 1)});

    /**
     * PFX format syntax<br><br>
     * 
     * This format corresponds to the data model presented above, with
     * wrappers for privacy and integrity. This section makes free
     * reference to PKCS #7 {@link GostASN1.ContentInfo}<br>
     * All modes of direct exchange use the same PDU format.  ASN.1 and BER-
     * encoding ensure platform independence.<br>
     * This standard has one ASN.1 export: PFX.  This is the outer integrity
     * wrapper.<br><br>
     * Instances of PFX contain:
     *  <ol>
     *  <li>A version indicator.  The version shall be v3 for this version of
     *      this document.</li>
     *  <li>A PKCS #7 ContentInfo, whose contentType is signedData in public-
     *      key integrity mode and data in password integrity mode.</li>
     *  <li>An optional instance of MacData, present only in password
     *      integrity.  This object, if present, contains a PKCS #7
     *      DigestInfo, which holds the MAC value, a macSalt, and an
     *      iterationCount.  As described in Appendix B, the MAC key is
     *      derived from the password, the macSalt, and the iterationCount;
     *      the MAC is computed from the authSafe value and the MAC key via HMAC.  
     *      The password and the MAC key are not actually present anywhere in the PFX.  
     *      The salt and (to a certain extent) the iteration count thwarts dictionary
     *      attacks against the integrity password. </li>
     *  </ol>
     *  <pre>
     *  PFX ::= SEQUENCE {
     *      version     INTEGER {v3(3)}(v3,...),
     *      authSafe    ContentInfo,
     *      macData     MacData OPTIONAL
     *  }
     *
     *  MacData ::= SEQUENCE {
     *      mac         DigestInfo,
     *      macSalt     OCTET STRING,
     *      iterations  INTEGER DEFAULT 1
     *      -- Note: The default is for historical reasons and its
     *      --       use is deprecated.
     *  }
     *  </pre>
     * See {@link GostASN1.ContentInfo}<br><br>
     * 
     * RFC 7292 references {@link http://tools.ietf.org/html/rfc7292} 
     * @class GostASN1.PFX
     * @extends GostASN1.Sequence
     * @property {number} version Encoded version number
     * @property {GostASN1.ContentInfo} authSafe ContentInfo with {@link GostASN1.AuthenticatedSafe} content 
     */
    var PFX = SEQUENCE({
        version: INTEGER,
        authSafe: ContentInfo,
        macData: OPTIONAL(MacData)}, 'PFX');


    /*
     * Certificate Request Message Format 
     * 
     * http://tools.ietf.org/html/rfc4211
     * 
     */

    var RegToken = UTF8String;

    var Authenticator = UTF8String;

    var CertId = SEQUENCE({
        issuer: GeneralName,
        serialNumber: INTEGER});
    var OldCertId = CertId;

    var ProtocolEncrKey = SubjectPublicKeyInfo;

    var EncryptedValue = SEQUENCE({
        // the intended algorithm for which the value will be used
        intendedAlg: OPTIONAL(CTX(0, IMPLICIT(AlgorithmIdentifier))),
        // the symmetric algorithm used to encrypt the value
        symmAlg: OPTIONAL(CTX(1, IMPLICIT(AlgorithmIdentifier))),
        // the (encrypted) symmetric key used to encrypt the value
        encSymmKey: OPTIONAL(CTX(2, IMPLICIT(BIT_STRING))),
        // algorithm used to encrypt the symmetric key
        keyAlg: OPTIONAL(CTX(3, IMPLICIT(AlgorithmIdentifier))),
        valueHint: OPTIONAL(CTX(4, IMPLICIT(OCTET_STRING))),
        // a brief description or identifier of the encValue content
        // (may be meaningful only to the sending entity, and used only
        // if EncryptedValue might be re-examined by the sending entity
        // in the future)
        encValue: BIT_STRING});
    var KeyGenParameters = OCTET_STRING;

    // The encrypted private key MUST be placed in the envelopedData
    // encryptedContentInfo encryptedContent OCTET STRING.
    var EncryptedKey = CHOICE({
        encryptedValue: EncryptedValue, // Deprecated
        envelopedData: CTX(0, IMPLICIT(EnvelopedData))}, function (value) {
        return value.encryptedContentInfo ? 'envelopedData' : 'encryptedValue';
    });

    var PKIArchiveOptions = CHOICE({
        // the actual value of the private key
        encryptedPrivKey: CTX(0, EncryptedKey),
        // parameters that allow the private key to be re-generated
        keyGenParameters: CTX(1, IMPLICIT(KeyGenParameters)),
        // set to TRUE if sender wishes receiver to archive the private
        // key of a key pair that the receiver generates in response to
        // this request; set to FALSE if no archival is desired.
        archiveRemGenPrivKey: CTX(2, IMPLICIT(BOOLEAN))});

    var SinglePubInfo = SEQUENCE({
        pubMethod: INTEGER({
            dontCare: 0,
            x500: 1,
            web: 2,
            ldap: 3}),
        pubLocation: OPTIONAL(GeneralName)});

    // pubInfos MUST NOT be present if action is "dontPublish"
    // (if action is "pleasePublish" and pubInfos is omitted,
    // "dontCare" is assumed)
    var PKIPublicationInfo = SEQUENCE({
        action: INTEGER({
            dontPublish: 0,
            pleasePublish: 1}),
        pubInfos: OPTIONAL(SEQUENCE_OF(SinglePubInfo))});

    var SubsequentMessage = INTEGER({
        // requests that resulting certificate be encrypted for the
        // end entity (following which, POP will be proven in a
        // confirmation message)
        encrCert: 0,
        // requests that CA engage in challenge-response exchange with
        // end entity in order to prove private key possession
        challengeResp: 1});

    var POPOPrivKey = CHOICE({
        // possession is proven in this message (which contains the private
        // key itself (encrypted for the CA))
        thisMessage: CTX(0, IMPLICIT(BIT_STRING)), // Deprecated
        subsequentMessage: CTX(1, IMPLICIT(SubsequentMessage)),
        // possession will be proven in a subsequent message
        dhMAC: CTX(2, IMPLICIT(BIT_STRING)), // Deprecated
        agreeMAC: CTX(3, IMPLICIT(PKMACValue)),
        encryptedKey: CTX(4, IMPLICIT(EnvelopedData))});

    var PBMParameter = SEQUENCE({
        salt: OCTET_STRING,
        // AlgId for a One-Way Function (SHA-1 recommended)
        owf: AlgorithmIdentifier,
        // number of times the OWF is applied
        iterationCount: INTEGER,
        // the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11], or HMAC [HMAC, RFC2202])
        mac: AlgorithmIdentifier});

    var PKMACValue = SEQUENCE({
        // algorithm value shall be PasswordBasedMac {1 2 840 113533 7 66 13}
        // parameter value is PBMParameter
        algId: AlgorithmIdentifier,
        value: BIT_STRING});

    var POPOSigningKeyInput = SEQUENCE({
        authInfo: CHOICE({
            // used only if an authenticated identity has been
            // established for the sender (e.g., a DN from a
            // previously-issued and currently-valid certificate)
            sender: CTX(0, EXPLICIT(GeneralName)), // GeneralName choice - explicit
            // used if no authenticated GeneralName currently exists for
            // the sender; publicKeyMAC contains a password-based MAC
            // on the DER-encoded value of publicKey
            publicKeyMAC: PKMACValue}),
        publicKey: SubjectPublicKeyInfo});  // from CertTemplate

    var POPOSigningKey = SEQUENCE({
        poposkInput: OPTIONAL(CTX(0, POPOSigningKeyInput)),
        algorithmIdentifier: AlgorithmIdentifier,
        signature: BIT_STRING});

    var ProofOfPossession = CHOICE({
        // used if the RA has already verified that the requester is in
        // possession of the private key
        raVerified: CTX(0, IMPLICIT(NULL)),
        signature: CTX(1, IMPLICIT(POPOSigningKey)),
        keyEncipherment: CTX(2, IMPLICIT(POPOPrivKey)),
        keyAgreement: CTX(3, IMPLICIT(POPOPrivKey))});

    var Controls = SEQUENCE_OF(AttributeTypeAndValue({
        regToken: RegToken,
        authenticator: Authenticator,
        pkiPublicationInfo: PKIPublicationInfo,
        pkiArchiveOptions: PKIArchiveOptions,
        oldCertID: OldCertId,
        protocolEncrKey: ProtocolEncrKey}));

    var OptionalValidity = SEQUENCE({
        notBefore: OPTIONAL(CTX(0, IMPLICIT(Time))),
        notAfter: OPTIONAL(CTX(1, IMPLICIT(Time)))}); // at least one MUST be present

    var CertTemplate = SEQUENCE({
        version: OPTIONAL(CTX(0, IMPLICIT(Version))),
        serialNumber: OPTIONAL(CTX(1, IMPLICIT(INTEGER))),
        signingAlg: OPTIONAL(CTX(2, IMPLICIT(AlgorithmIdentifier))),
        issuer: OPTIONAL(CTX(3, IMPLICIT(Name))),
        validity: OPTIONAL(CTX(4, IMPLICIT(OptionalValidity))),
        subject: OPTIONAL(CTX(5, IMPLICIT(Name))),
        publicKey: OPTIONAL(CTX(6, IMPLICIT(SubjectPublicKeyInfo))),
        issuerUID: OPTIONAL(CTX(7, IMPLICIT(UniqueIdentifier))),
        subjectUID: OPTIONAL(CTX(8, IMPLICIT(UniqueIdentifier))),
        extensions: OPTIONAL(CTX(9, IMPLICIT(Extensions)))});

    var CertRequest = SEQUENCE({
        certReqId: INTEGER, // ID for matching request and reply
        certTemplate: CertTemplate, // Selected fields of cert to be issued
        controls: OPTIONAL(Controls)});   // Attributes affecting issuance

    var UTF8Pairs = UTF8String;

    var CertReq = CertRequest;

    var EncKeyWithID = SEQUENCE({
        privateKey: PrivateKeyInfo,
        identifier: OPTIONAL(CHOICE({
            string: UTF8String,
            generalName: GeneralName}, function (value) {
            return typeof value === 'string' || value instanceof String ?
                    'string' : 'generalName';
        }))});

    var CertReqMsg = SEQUENCE({
        certReq: CertRequest,
        popo: OPTIONAL(ProofOfPossession),
        // content depends upon key type
        regInfo: OPTIONAL(SEQUENCE_OF(AttributeTypeAndValue({
            utf8Pairs: UTF8Pairs,
            certReq: CertReq,
            encKeyWithID: EncKeyWithID})))});

    var CertReqMessages = SEQUENCE_OF(CertReqMsg);



    /*
     * Certificate Management over CMS
     * 
     * http://tools.ietf.org/html/rfc5272
     * 
     */

    var PendInfo = SEQUENCE({
        pendToken: OCTET_STRING,
        pendTime: GeneralizedTime});

    var CMCStatus = INTEGER({
        success: 0,
        failed: 2,
        pending: 3,
        noSupport: 4,
        confirmRequired: 5,
        popRequired: 6,
        partial: 7});

    var CMCFailInfo = INTEGER({
        badAlg: 0,
        badMessageCheck: 1,
        badRequest: 2,
        badTime: 3,
        badCertId: 4,
        unsupportedExt: 5,
        mustArchiveKeys: 6,
        badIdentity: 7,
        popRequired: 8,
        popFailed: 9,
        noKeyReuse: 10,
        internalCAError: 11,
        tryLater: 12,
        authDataFail: 13});

    var CMCStatusInfo = SEQUENCE({
        cMCStatus: CMCStatus,
        bodyList: SEQUENCE_OF(BodyPartID),
        statusString: OPTIONAL(UTF8String),
        otherInfo: OPTIONAL(CHOICE({
            failInfo: CMCFailInfo,
            pendInfo: PendInfo}))});

    var AddExtensions = SEQUENCE({
        pkiDataReference: BodyPartID,
        certReferences: SEQUENCE_OF(BodyPartID),
        extensions: SEQUENCE_OF(Extension)});

    var LraPopWitness = SEQUENCE({
        pkiDataBodyid: BodyPartID,
        bodyIds: SEQUENCE_OF(BodyPartID)});

    var GetCert = SEQUENCE({
        issuerName: GeneralName,
        serialNumber: INTEGER});

    var GetCRL = SEQUENCE({
        issuerName: Name,
        cRLName: OPTIONAL(GeneralName),
        time: OPTIONAL(GeneralizedTime),
        reasons: OPTIONAL(ReasonFlags)});

    var RevokeRequest = SEQUENCE({
        issuerName: Name,
        serialNumber: INTEGER,
        reason: CRLReason,
        invalidityDate: OPTIONAL(GeneralizedTime),
        passphrase: OPTIONAL(OCTET_STRING),
        comment: OPTIONAL(UTF8String)});

    var DecryptedPOP = SEQUENCE({
        bodyPartID: BodyPartID,
        thePOPAlgID: AlgorithmIdentifier,
        thePOP: OCTET_STRING});

    var CMCCertId = IssuerAndSerialNumber;

    var BodyPartReference = CHOICE({
        bodyPartID: BodyPartID,
        bodyPartPath: BodyPartPath});

    var CMCStatusInfoV2 = SEQUENCE({
        cMCStatus: CMCStatus,
        bodyList: SEQUENCE_OF(BodyPartReference),
        statusString: OPTIONAL(UTF8String),
        otherInfo: OPTIONAL(CHOICE({
            failInfo: CMCFailInfo,
            pendInfo: PendInfo,
            extendedFailInfo: SEQUENCE({
                failInfoOID: OBJECT_IDENTIFIER,
                failInfoValue: AttributeValue})}))});

    var PublishTrustAnchors = SEQUENCE({
        seqNumber: INTEGER,
        hashAlgorithm: AlgorithmIdentifier,
        anchorHashes: SEQUENCE_OF(OCTET_STRING)});

    var AuthPublish = BodyPartID;

    var BodyPartList = SEQUENCE_OF(BodyPartID);

    var CMCPublicationInfo = SEQUENCE({
        hashAlg: AlgorithmIdentifier,
        certHashes: SEQUENCE_OF(OCTET_STRING),
        pubInfo: PKIPublicationInfo});

    var ModCertTemplate = SEQUENCE({
        pkiDataReference: BodyPartPath,
        certReferences: BodyPartList,
        replace: DEFAULT(BOOLEAN, true),
        certTemplate: CertTemplate});

    var ControlsProcessed = SEQUENCE({
        bodyList: SEQUENCE_OF(BodyPartReference)});

    var IdentifyProofV2 = SEQUENCE({
        proofAlgID: AlgorithmIdentifier,
        macAlgId: AlgorithmIdentifier,
        witness: OCTET_STRING});

    var PopLinkWitnessV2 = SEQUENCE({
        keyGenAlgorithm: AlgorithmIdentifier,
        macAlgorithm: AlgorithmIdentifier,
        witness: OCTET_STRING});

    var TaggedCertificationRequest = SEQUENCE({
        bodyPartID: BodyPartID,
        certificationRequest: CertificationRequest});

    var TaggedContentInfo = SEQUENCE({
        bodyPartID: BodyPartID,
        contentInfo: ContentInfo});

    var OtherMsg = SEQUENCE({
        bodyPartID: BodyPartID,
        otherMsgType: OBJECT_IDENTIFIER,
        otherMsgValue: ANY}); //DEFINED BY otherMsgType 

    var TaggedRequest = CHOICE({
        tcr: CTX(0, IMPLICIT(TaggedCertificationRequest)),
        crm: CTX(1, IMPLICIT(CertReqMsg)),
        orm: CTX(2, IMPLICIT(SEQUENCE({
            bodyPartID: BodyPartID,
            requestMessageType: OBJECT_IDENTIFIER,
            requestMessageValue: ANY})))}); // DEFINED BY requestMessageType

    var EncryptedPOP = SEQUENCE({
        request: TaggedRequest,
        cms: ContentInfo,
        thePOPAlgID: AlgorithmIdentifier,
        witnessAlgID: AlgorithmIdentifier,
        witness: OCTET_STRING});

    var TaggedAttribute = ATTRIBUTE({
        bodyPartID: BodyPartID,
        attrType: OBJECT_IDENTIFIER,
        attrValues: function (type) {
            return SET_OF(type);
        }
    }, 'attrType', 'attrValues', AttributeValue)({
        statusInfo: CMCStatusInfo,
        identification: UTF8String,
        identityProof: OCTET_STRING,
        dataReturn: OCTET_STRING,
        transactionId: INTEGER,
        senderNonce: OCTET_STRING,
        recipientNonce: OCTET_STRING,
        addExtensions: AddExtensions,
        encryptedPOP: EncryptedPOP,
        decryptedPOP: DecryptedPOP,
        lraPOPWitness: LraPopWitness,
        getCert: GetCert,
        getCRL: GetCRL,
        revokeRequest: RevokeRequest,
        regInfo: OCTET_STRING,
        responseInfo: OCTET_STRING,
        queryPending: OCTET_STRING,
        popLinkRandom: OCTET_STRING,
        popLinkWitness: OCTET_STRING,
        confirmCertAcceptance: CMCCertId,
        statusInfoV2: CMCStatusInfoV2,
        trustedAnchors: PublishTrustAnchors,
        authPublish: AuthPublish,
        batchRequests: BodyPartList,
        batchResponses: BodyPartList,
        publishCert: CMCPublicationInfo,
        modCertTemplate: ModCertTemplate,
        controlProcessed: ControlsProcessed,
        popLinkWitnessV2: PopLinkWitnessV2,
        identityProofV2: IdentifyProofV2
    });
    /**
     * PKIData Content Type<br><br>
     *
     * The PKIData content type is used for the Full PKI Request.  A PKIData
     * content type is identified by:
     * <pre>
     *   id-cct-PKIData ::= {id-pkix id-cct(12) 2 }
     * </pre>
     * The ASN.1 structure corresponding to the PKIData content type is:
     * <pre>
     *   PKIData ::= SEQUENCE {
     *       controlSequence    SEQUENCE SIZE(0..MAX) OF TaggedAttribute,
     *       reqSequence        SEQUENCE SIZE(0..MAX) OF TaggedRequest,
     *       cmsSequence        SEQUENCE SIZE(0..MAX) OF TaggedContentInfo,
     *       otherMsgSequence   SEQUENCE SIZE(0..MAX) OF OtherMsg
     *   }
     * </pre>
     * All certification requests encoded into a single PKIData SHOULD be
     * for the same identity.  RAs that batch process (see Section 6.17) are
     * expected to place the PKI Requests received into the cmsSequence of a
     * PKIData. <br><br>
     * See {@link GostASN1.ContentInfo} and {@link GostASN1.PKIResponse}<br><br>
     * RFC 5272 references {@link http://tools.ietf.org/html/rfc5272} 
     * 
     * @class GostASN1.PKIData
     * @extends GostASN1.Sequence
     * @property {GostASN1.Attributes[]} controlSequence
     * @property {GostASN1.Sequence[]} reqSequence
     * @property {GostASN1.ContentInfo[]} cmsSequence
     * @property {GostASN1.Sequence[]} otherMsgSequence
     */
    var PKIData = SEQUENCE({
        controlSequence: SEQUENCE_OF(TaggedAttribute),
        reqSequence: SEQUENCE_OF(TaggedRequest),
        cmsSequence: SEQUENCE_OF(TaggedContentInfo),
        otherMsgSequence: SEQUENCE_OF(OtherMsg)}, 'PKI REQUEST');

    /**
     * PKIResponse Content Type<br><br>
     *
     * The PKIResponse content type is used for the Full PKI Response.  The
     * PKIResponse content type is identified by:
     * <pre>
     *   id-cct-PKIResponse ::= {id-pkix id-cct(12) 3  }
     * </pre>
     * The ASN.1 structure corresponding to the PKIResponse content type is:
     * <pre>
     *    PKIResponse ::= SEQUENCE {
     *        controlSequence   SEQUENCE SIZE(0..MAX) OF TaggedAttribute,
     *        cmsSequence       SEQUENCE SIZE(0..MAX) OF TaggedContentInfo,
     *        otherMsgSequence  SEQUENCE SIZE(0..MAX) OF OtherMsg
     *    }
     *    
     *    ReponseBody ::= PKIResponse
     * </pre>
     *
     * Note: In [RFC2797], this ASN.1 type was named ResponseBody.  It has
     * been renamed to PKIResponse for clarity and the old name kept as a
     * synonym.<br><br>
     *
     * See {@link GostASN1.ContentInfo} and {@link GostASN1.PKIData}<br><br>
     * 
     * RFC 5272 references {@link http://tools.ietf.org/html/rfc5272} 
     * 
     * @class GostASN1.PKIResponse
     * @extends GostASN1.Sequence
     * @property {GostASN1.Attributes[]} controlSequence
     * @property {GostASN1.ContentInfo[]} cmsSequence
     * @property {GostASN1.Sequence[]} otherMsgSequence
     */
    var PKIResponse = SEQUENCE({
        controlSequence: SEQUENCE_OF(TaggedAttribute),
        cmsSequence: SEQUENCE_OF(TaggedContentInfo),
        otherMsgSequence: SEQUENCE_OF(OtherMsg)}, 'PKI RESPONSE');



    /**
     * ASN.1 syntax definitions
     * 
     * @class GostASN1
     */
    function GostASN1() {
    }

    GostASN1.prototype = {
        /**
         * Gost PrivateKey info encoder
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.GostPrivateKeyInfo
         */
        GostPrivateKeyInfo: GostPrivateKeyInfo,
        /**
         * Gost subject PublicKey info encoder
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.GostSubjectPublicKeyInfo
         */
        GostSubjectPublicKeyInfo: GostSubjectPublicKeyInfo,
        /**
         * CryptoPro key container header
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.GostKeyContainer
         */
        GostKeyContainer: GostKeyContainer,
        /**
         * CryptoPro key container name
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.GostKeyContainerName
         */
        GostKeyContainerName: GostKeyContainerName,
        /**
         * CryptoPro encrypted PrivateKey for key containers
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.GostPrivateKeys
         */
        GostPrivateKeys: GostPrivateKeys,
        /**
         * CryptoPro PrivateKey masks for key containers
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.GostPrivateMasks
         */
        GostPrivateMasks: GostPrivateMasks,
        /**
         * ViPNet key container
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.ViPNetInfo
         */
        ViPNetInfo: ViPNetInfo,
        /**
         * Gost Signature encoders
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.GostSignature
         */
        GostSignature: GostSignature,
        /**
         * Gost Encrypted key encoder for CMS
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.GostEncryptedKey
         */
        GostEncryptedKey: GostEncryptedKey,
        /**
         * SignalCom wrapped PrivateKey
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.GostWrappedPrivateKey
         */
        GostWrappedPrivateKey: GostWrappedPrivateKey,
        /**
         * PKCS#8 PrivateKey info
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.PrivateKeyInfo
         */
        PrivateKeyInfo: PrivateKeyInfo,
        /**
         * PKCS#8 encrypted PrivateKey info
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.EncryptedPrivateKeyInfo
         */
        EncryptedPrivateKeyInfo: EncryptedPrivateKeyInfo,
        /**
         * X.509 subject PublicKey info
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.SubjectPublicKeyInfo
         */
        SubjectPublicKeyInfo: SubjectPublicKeyInfo,
        /**
         * X.509 To be signed Certificate
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.TBSCertificate
         */
        TBSCertificate: TBSCertificate,
        /**
         * X.509 Certificate
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.Certificate
         */
        Certificate: Certificate,
        /**
         * PKCS#10 Certification request definition
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.CertificationRequestInfo
         */
        CertificationRequestInfo: CertificationRequestInfo,
        /**
         * PKCS#10 Certification request 
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.CertificationRequest
         */
        CertificationRequest: CertificationRequest,
        /**
         * X.509 To be signed CRL
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.TBSCertList
         */
        TBSCertList: TBSCertList,
        /**
         * X.509 CRL
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.CertificateList
         */
        CertificateList: CertificateList,
        /**
         * X.509 Attribute Certificate definition
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.AttributeCertificateInfo
         */
        AttributeCertificateInfo: AttributeCertificateInfo,
        /**
         * X.509 Attribute Certificate
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.AttributeCertificate
         */
        AttributeCertificate: AttributeCertificate,
        /**
         * CMS Signed Attributes
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.SignedAttributes
         */
        SignedAttributes: SignedAttributes,
        /**
         * CMS Unsigned Attributes
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.UnsignedAttributes
         */
        UnsignedAttributes: UnsignedAttributes,
        /**
         * CMS Content definition
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.ContentInfo
         */
        ContentInfo: ContentInfo,
        /**
         * PKCS#12 Safe Contents
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.SafeContents
         */
        SafeContents: SafeContents,
        /**
         * PKCS#12 Authenticated Safe
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.AuthenticatedSafe
         */
        AuthenticatedSafe: AuthenticatedSafe,
        /**
         * PKCS#12 Personal Information Exchange (PFX)
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.PFX
         */
        PFX: PFX,
        /**
         * PKI Request
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.PKIData
         */
        PKIData: PKIData,
        /**
         * PKI Response
         * 
         * @memberOf GostASN1
         * @instance
         * @type GostASN1.PKIResponse
         */
        PKIResponse: PKIResponse
    };

    /**
     * PKCS ASN.1 message syntax and converters  
     * 
     * @memberOf gostCrypto
     * @type GostASN1
     */
    gostCrypto.asn1 = new GostASN1();

module.exports = GostASN1;


/***/ }),

/***/ "./node_modules/node-gost-crypto/lib/gostCMS.js":
/*!******************************************************!*\
  !*** ./node_modules/node-gost-crypto/lib/gostCMS.js ***!
  \******************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

/**
 * @file Implements the Cryptographic Message Syntax as specified in RFC-2630.
 * @version 1.76
 * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *    
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice, this 
 *    list of conditions and the following disclaimer.
 *    
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *    
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

const gostCrypto = __webpack_require__(/*! ./gostCrypto */ "./node_modules/node-gost-crypto/lib/gostCrypto.js");
// const GostASN1 = require('./gostASN1');
// const GostCert = require('./gostCert');

    /*
     * Common algorithms
     */
    var root = __webpack_require__.g;
    var Promise = root.Promise;
    var Object = root.Object;
    var CryptoOperationData = root.ArrayBuffer;
    var Date = root.Date;

    var subtle = gostCrypto.subtle;
    var asn1 = gostCrypto.asn1;
    var coding = gostCrypto.coding;
    var cert = gostCrypto.cert;
    var providers = gostCrypto.security.providers;

    // Expand javascript object
    function expand() {
        var r = {};
        for (var i = 0, n = arguments.length; i < n; i++) {
            var item = arguments[i];
            if (typeof item === 'object')
                for (var name in item)
                    if (item.hasOwnProperty(name))
                        r[name] = item[name];
        }
        return r;
    }

    function defineProperty(object, name, descriptor, enumerable) {
        if (typeof descriptor !== 'object')
            descriptor = {value: descriptor};
        if (enumerable !== undefined)
            descriptor.enumerable = enumerable;
        Object.defineProperty(object, name, descriptor);
    }

    function defineProperties(object, properties, enumerable) {
        for (var name in properties)
            defineProperty(object, name, properties[name], enumerable);
    }

    // Extend javascript class
    function extend(Super, Class, propertiesObject, propertiesClass) {
        // If constructor not defined
        if (typeof Class !== 'function') {
            propertiesClass = propertiesObject;
            propertiesObject = Class;
            Class = function () {
                Super.apply(this, arguments);
            };
        }
        // Create prototype properties
        Class.prototype = Object.create(Super.prototype, {
            constructor: {
                value: Class
            },
            superclass: {
                value: Super.prototype
            }
        });
        if (propertiesObject)
            defineProperties(Class.prototype, propertiesObject, true);
        // Inherites super class properties
        if (Super !== Object)
            for (var name in Super)
                Class[name] = Super[name];
        Class.super = Super;
        if (propertiesClass)
            defineProperties(Class, propertiesClass, true);
        return Class;
    }

    // Self resolver
    function call(callback) {
        try {
            callback();
        } catch (e) {
        }
    }

    // Check the buffers to equal
    function equalBuffers(r1, r2) {
        var s1 = new Uint8Array(r1),
                s2 = new Uint8Array(r2);
        if (s1.length !== s2.length)
            return false;
        for (var i = 0, n = s1.length; i < n; i++)
            if (s1[i] !== s2[i])
                return false;
        return true;
    }

    // True if equal numbers
    var equalNumbers = (function () {
        // Convert number to bigendian hex string
        var hex = function (s) {
            var t = typeof s;
            return t === 'undefined' || s === '' ? '0' :
                    t === 'number' || s instanceof Number ? s.toString(16).toLowerCase() :
                    s.replace('0x', '').toLowerCase();
        };
        // Zero left padding
        var lpad = function (s, size) {
            return (new Array(size + 1).join('0') + s).slice(-size);
        };
        return function (s1, s2) {
            s1 = hex(s1);
            s2 = hex(s2);
            var len = Math.max(s1.length, s2.length);
            return lpad(s1, len) === lpad(s2, len);
        };
    })();

    // Check equal names
    function equalNames(name1, name2) {
        for (var key in name1)
            if (name1[key] !== name2[key])
                return false;
        for (var key in name2)
            if (name1[key] !== name2[key])
                return false;
        return true;
    }

    // Add unique value to array
    function addUnique(array, item, comparator) {
        var found = false;
        for (var i = 0, n = array.length; i < n; i++)
            if (comparator(array[i], item)) {
                found = true;
                break;
            }
        if (!found)
            array.push(item);
    }

    // Set content data
    function setContentData(object, data) {
        var content = object.content;
        switch (object.contentType) {
            case 'data':
                object.content = data.content;
                break;
            case 'digestedData':
            case 'signedData':
            case 'authData':
                content.encapContentInfo = {
                    eContentType: data.contentType,
                    eContent: data.content
                };
                break;
            case 'envelopedData':
            case 'encryptedData':
                content.encryptedContentInfo = {
                    contentType: data.contentType,
                    encryptedContent: data.content
                };
                break;
        }
    }

    // Get content data
    function getContentData(object) {
        var content = object.content;
        switch (object.contentType) {
            case 'data':
                return {
                    contentType: object.contentType,
                    content: object.content
                };
            case 'digestedData':
            case 'signedData':
            case 'authData':
                var encap = content.encapContentInfo;
                return  {
                    contentType: encap.eContentType,
                    content: encap.eContent
                };
            case 'envelopedData':
            case 'encryptedData':
                var enc = content.encryptedContentInfo;
                return {
                    contentType: enc.contentType,
                    content: enc.encryptedContent
                };
        }
    }

    // Check content info type
    function checkContentInfo(contentInfo) {
        var content, contentType;
        if (contentInfo) {
            if (typeof contentInfo === 'string')
                try {
                    contentInfo = coding.PEM.decode(contentInfo);
                } catch (e1) {
                    contentInfo = coding.Chars.decode(contentInfo);
                }
            if (contentInfo instanceof CryptoOperationData)
                try {
                    contentInfo = asn1.ContentInfo.decode(contentInfo);
                } catch (e) {
                    contentInfo = {contentType: 'data', content: contentInfo};
                }
            contentType = contentInfo.contentType;
            if (!contentType)
                throw new Error('Invalid content object');
            content = contentInfo.content;
            if (!(content instanceof CryptoOperationData))
                content = content.encode();
            return {contentType: contentType, content: content};
        } else
            contentInfo = {contentType: 'data'};
        return contentInfo;
    }

    function createContentInfo(contentInfo) {
        try {
            // Some provider has mistake to envelop ContentInfo enstead 
            // content field of ContentInfo
            contentInfo = new asn1.ContentInfo(contentInfo.content, true);
        } catch (e) {
        }
        // Create situable content info object
        switch (contentInfo.contentType) {
            case 'data':
                return new DataContentInfo(contentInfo);
            case 'digestedData':
                return new DigestedDataContentInfo(contentInfo);
            case 'signedData':
                return new SignedDataContentInfo(contentInfo);
            case 'encryptedData':
                return new EncryptedDataContentInfo(contentInfo);
            case 'envelopedData':
                return new EnvelopedDataContentInfo(contentInfo);
            default:
                return new asn1.ContentInfo(contentInfo);
        }
    }
    ;

    function matchCert(id, cert) {
        return (id instanceof CryptoOperationData ? cert.extensions &&
                equalBuffers(id, cert.extensions.subjectKeyIdentifier) :
                equalNames(cert.issuer, id.issuer) &&
                equalNumbers(cert.serialNumber, id.serialNumber));
    }

    // Get random values
    function getSeed(length) {
        var seed = new Uint8Array(length);
        gostCrypto.getRandomValues(seed);
        return seed.buffer;
    }

    // Salt size
    function saltSize(algorithm) {
        switch (algorithm.id) {
            case 'pbeWithSHAAnd40BitRC2-CBC':
            case 'pbeWithSHAAnd128BitRC2-CBC':
                return 8;
            case 'pbeUnknownGost':
                return 16;
            case 'sha1':
                return 20;
            default:
                return 32;
        }
    }

    // Password to bytes
    function passwordData(derivation, password) {
        if (!password)
            return new CryptoOperationData(0);
        if (password instanceof CryptoOperationData)
            return password;
        if (typeof password !== 'string')
            throw new Error('The password must be string or raw data type');
        if (derivation.name.indexOf('CPKDF') >= 0) {
            // CryptoPro store password
            var r = [];
            for (var i = 0; i < password.length; i++) {
                var c = password.charCodeAt(i);
                r.push(c & 0xff);
                r.push(c >>> 8 & 0xff);
                r.push(0);
                r.push(0);
            }
            return new Uint8Array(r).buffer;
        } else if (derivation.name.indexOf('PFXKDF') >= 0)
            // PKCS#12 unicode password
            return coding.Chars.decode(password + '\0', 'unicode');
        else
            // PKCS#5 password mode
            return coding.Chars.decode(password, 'utf8');
    }

    // Define provider for encription algorithm
    function encryptionProvider(algorithm) {
        var id = algorithm.id;
        for (var name in providers) {
            var provider = providers[name];
            if (provider.encryption.id === id)
                return provider;
        }
    }



    /**
     * Provides facilities for handling certificates, CRLs, etc.
     * @class GostCMS
     */
    function GostCMS() {
    }

    /**
     * Message templates
     * <ul>
     *      <li>providerName - provider name for key generation, default 'CP-01'</li>
     *      <li>autoAddCert - automatic add signer certificate to signature, default false</li>
     *      <li>useKeyIdentifier - true to add Signer as the SignerIdentifier (v3), otherwise, as the IssuerAndSerialNumber (v1) (default false).</li>
     * </ul>
     * 
     * @memberOf GostCMS
     * @instance
     */
    var options = {
        providerName: 'CP-01',
        autoAddCert: false,
        useKeyIdentifier: false
    };

    GostCMS.prototype.options = options;

    /**
     * The base class for all CMS objects.<br><br>
     * 
     * A CMS object consists of a content type, and content.<br><br>
     * 
     * @class GostCMS.DataContentInfo
     * @param {(FormatedData|GostASN1.ContentInfo)} contentInfo The content object.
     * @param {string} defaultSet The default object initialization set.
     * @extends GostASN1.ContentInfo
     */
    function DataContentInfo(contentInfo, defaultSet)
    {
        asn1.ContentInfo.call(this, contentInfo || defaultSet || {contentType: 'data'});
        if (defaultSet && this.contentType !== (defaultSet.contentType || 'data'))
            throw new Error('Invalid content type');
    }

    extend(asn1.ContentInfo, DataContentInfo, {
        /**
         * Indicates if this is a detached CMS object.
         * 
         * @memberOf GostCMS.DataContentInfo
         * @instance
         * @returns {boolean} true if detached; false otherwise.
         */
        isDetached: {
            value: false,
            enumerable: true,
            writable: true
        },
        /**
         * Indicates if an external (detached) signature must be created.
         * 
         * @memberOf GostCMS.DataContentInfo
         * @instance
         * @param {boolean} createDetached True if detached; false otherwise.
         */
        writeDetached: function (createDetached)
        {
            // Define external signature mode
            this.isDetached = createDetached;
        },
        /**
         * Encode the message to binary format 'DER' or 'PEM'
         * 
         * @memberOf GostCMS.DataContentInfo
         * @instance
         * @param {string} format
         * @returns {FormatedData}
         */
        encode: function (format)
        {
            if (this.isDetached) {
                var data = getContentData(this);
                setContentData(this, {contentType: data.contentType});
                var result = asn1.ContentInfo.method('encode').call(this, format);
                setContentData(this, data);
                return result;
            } else
                return asn1.ContentInfo.method('encode').call(this, format);
        },
        /**
         * Enclose content to document. 
         * 
         * @memberOf GostCMS.DataContentInfo
         * @instance
         * @param {(FormatedData|GostASN1.ContentInfo)} contentInfo
         * @returns {Promise} Promise to return self object after enclose content
         */
        encloseContent: function (contentInfo)
        {
            var self = __webpack_require__.g;
            return new Promise(call).then(function () {
                self.setEnclosed(contentInfo);
                return self;
            });
        },
        /**
         * Sets the content of attached document.<br><br>
         * 
         * This is necessary only in detached mode.
         * 
         * @memberOf GostCMS.DataContentInfo
         * @instance
         * @param {(FormatedData|GostASN1.ContentInfo)} contentInfo - The encapsulated CMS Object.
         */
        setEnclosed: function (contentInfo)
        {
            setContentData(this, checkContentInfo(contentInfo));
        },
        /**
         * Returns the document which attached. If the content is not attached, the CMS object 
         * which is returned will be degenerate.
         * 
         * @memberOf GostCMS.DataContentInfo
         * @instance
         * @returns {GostASN1.ContentInfo} The encapsulated CMS Object.
         */
        getEnclosed: function ()
        {
            return createContentInfo(getContentData(this));
        }
    });

    /**
     * This class encapsulates a CMS object of content type binary data.
     * 
     * @memberOf GostCMS
     * @type GostCMS.DigestedDataContentInfo
     */
    GostCMS.prototype.DataContentInfo = DataContentInfo;

    /**
     * This class encapsulates a CMS object of content type digested-data.
     * 
     * @class GostCMS.DigestedDataContentInfo
     * @param {(FormatedData|GostASN1.ContentInfo)} contentInfo - The content that is to be signed.
     * @extends GostCMS.DataContentInfo
     * @extends GostASN1.DigestedData
     */
    function DigestedDataContentInfo(contentInfo)
    {
        DataContentInfo.call(this, contentInfo, {
            contentType: 'digestedData',
            version: 0,
            digestAlgorithm: providers[options.providerName].digest,
            encapContentInfo: {
                eContentType: 'data'
            },
            digest: new CryptoOperationData(0)
        });
    }

    extend(DataContentInfo, DigestedDataContentInfo, {
        /**
         * Enclose the content and calculate the message digest with given digest algorithm
         * 
         * @memberOf GostCMS.DigestedDataContentInfo
         * @instance
         * @param {(FormatedData|GostASN1.ContentInfo)} contentInfo Content data to be enclosed.
         * @param {(AlgorithmIdentifier|string)} digestAlgorithm Digest algorithm or provider name
         * @returns {Promise} 
         */
        encloseContent: function (contentInfo, digestAlgorithm)
        {
            var self = __webpack_require__.g;
            return new Promise(call).then(function () {
                // Set enclosed data
                self.setEnclosed(contentInfo);

                // Define digest algorithm
                if (digestAlgorithm) {
                    var digestProvider = providers[digestAlgorithm];
                    self.digestAlgorithm = (digestProvider && digestProvider.digest) || digestAlgorithm;
                }

                // Calculate digest
                return subtle.digest(self.digestAlgorithm, self.encapContentInfo.eContent);
            }).then(function (digest) {

                // Set digest attribute
                self.digest = digest;
            });
        },
        /**
         * Verify the Message Digest. <br><br>
         * 
         * @memberOf GostCMS.DigestedDataContentInfo
         * @instance
         * @param contentInfo Detached content (optional)
         * @returns {Promise} Promise to return enclosed object {@link GostASN1.ContentInfo} if digest verified
         */
        verify: function (contentInfo)
        {
            var self = __webpack_require__.g;
            return new Promise(call).then(function () {
                // Append attached
                if (contentInfo)
                    self.setEnclosed(contentInfo);

                // Check data
                var dataToVerify = self.encapContentInfo &&
                        self.encapContentInfo.eContent;
                if (!dataToVerify)
                    throw new Error('Detached content is not found');

                // Calculate digest
                return subtle.digest(self.digestAlgorithm, self.encapContentInfo.eContent);
            }).then(function (digest) {
                if (!equalBuffers(digest, self.digest))
                    throw Error('Message digest is not verified');
                // Return content
                return createContentInfo({
                    contentType: self.encapContentInfo.eContentType,
                    content: self.encapContentInfo.eContent
                });
            });
        }
    });

    /**
     * This class encapsulates a CMS object of content type digested-data.
     * 
     * @memberOf GostCMS
     * @type GostCMS.DigestedDataContentInfo
     */
    GostCMS.prototype.DigestedDataContentInfo = DigestedDataContentInfo;

    /**
     * This class encapsulates a CMS object of content type signed-data.
     * 
     * Use encloseContent or setEnclosed methods to add a enclosed content before add signatures
     * 
     * @class GostCMS.SignedDataContentInfo
     * @param {(FormatedData|GostASN1.ContentInfo)} contentInfo - The signed content. 
     * @extends GostCMS.DataContentInfo
     * @extends GostASN1.SignedData
     */
    function SignedDataContentInfo(contentInfo)
    {
        DataContentInfo.call(this, contentInfo, {
            contentType: 'signedData',
            version: 1,
            digestAlgorithms: [],
            encapContentInfo: {
                eContentType: 'data'
            },
            signerInfos: []
        });
    }

    extend(DataContentInfo, SignedDataContentInfo, {
        /**
         * Add a Signer using the the IssuerAndSerialNumber as the SignerIdentifier i.e a Version1 CMSSignerInfo 
         * or SubjectPublicKeyIdentifier as the SignerIdentifier i.e a Version3 CMSSignerInfo.
         * 
         * @memberOf GostCMS.SignedDataContentInfo
         * @instance
         * @param {GostASN1.PrivateKeyInfo} signerKey Private Key of the signer.
         * @param {GostCert.X509} signerCert Signer certificate or certificate chain
         * @param {GostASN1.SignedAttributes} signedAttrs The set of signed attributes. Default undefined. If true or {} standard attributes will be appended: contentType and messageDigest
         * @param {GostASN1.UnsignedAttributes} unsignedAttrs  The set of unsigned attributes. Default undefined.
         * @returns {Promise} Promise to return self object after add signature
         */
        addSignature: function (signerKey, signerCert, signedAttrs, unsignedAttrs)
        {
            var self = this, signerInfo, dataToSign, signerCertChain;
            return new Promise(call).then(function () {
                // Check attribures
                if (!signerKey || !signerCert)
                    throw new Error('Signer key or certificate is not defined');
                // Cert chain
                if (signerCert instanceof Array) {
                    signerCertChain = signerCert;
                    signerCert = signerCertChain[0];
                } else
                    signerCertChain = [signerCert];
                // Signature algorithm provider
                var provider = signerCert.getProvider() ||
                        providers[options.providerName];
                var useKeyIdentifier = options.useKeyIdentifier && signerCert.extensions &&
                        signerCert.extensions.subjectKeyIdentifier;
                // Get enclosed data
                dataToSign = self.encapContentInfo.eContent;
                // Prepare signer info structure
                signerInfo = {
                    version: useKeyIdentifier ? 2 : 0,
                    sid: useKeyIdentifier ? signerCert.extensions.subjectKeyIdentifier : {
                        issuer: signerCert.issuer,
                        serialNumber: signerCert.serialNumber},
                    digestAlgorithm: provider.digest,
                    signatureAlgorithm: signerCert.subjectPublicKeyInfo.algorithm};
                // Set an unsigned attributes
                if (unsignedAttrs)
                    signerInfo.unsignedAttrs = unsignedAttrs;
                // For a signed attributes calculate digest
                if (signedAttrs) {
                    if (typeof signedAttrs !== 'object')
                        signedAttrs = {};
                    return subtle.digest(signerInfo.digestAlgorithm, dataToSign);
                }
            }).then(function (digest) {
                if (digest) {
                    // Add standard signed attributes
                    signedAttrs.contentType = self.encapContentInfo.eContentType,
                            signedAttrs.messageDigest = digest,
                            signedAttrs.signingTime = new Date();
                    signerInfo.signedAttrs = signedAttrs,
                            // Now data to sign = attributes
                            dataToSign = asn1.SignedAttributes.encode(signerInfo.signedAttrs);
                }

                // Import the private key
                return subtle.importKey('pkcs8', asn1.PrivateKeyInfo.encode(signerKey),
                        signerKey.privateKeyAlgorithm, false, ['sign']);
            }).then(function (key) {

                // Sign data
                var algorithm = expand(signerInfo.signatureAlgorithm, {hash: signerInfo.digestAlgorithm});
                return subtle.sign(algorithm, key, dataToSign);
            }).then(function (signatureValue) {
                signerInfo.signatureValue = signatureValue;

                // Add digest algorithm
                addUnique(self.digestAlgorithms, signerInfo.digestAlgorithm, function (algorithm1, algorithm2) {
                    return algorithm1.id === algorithm2.id;
                });

                // Add signer certificate
                if (options.autoAddCert) {
                    if (!self.certificates)
                        self.certificates = [];
                    for (var i = 0, n = signerCertChain.length; i < n; i++) {
                        addUnique(self.certificates, signerCertChain[i], function (cert1, cert2) {
                            return equalNames(cert1.issuer, cert2.issuer) &&
                                    equalNumbers(cert1.serialNumber, cert2.serialNumber);
                        });
                    }
                }

                // Add signer info
                self.signerInfos.push(signerInfo);
            });
        },
        /**
         * Indicates if this object has any signers i.e. checks for the absence of any SignerInfo structures.
         * CMS (RFC-2630) defines a degenerate object as one which has no signers.
         * 
         * @memberOf GostCMS.SignedDataContentInfo
         * @instance
         * @returns {boolean} True if this object has no signers; false otherwise.
         */
        isDegenerate: {
            get: function () {
                return !(this.signerInfos && this.signerInfos.length > 0);
            }
        },
        /**
         * Returns normally if this CMS signed data object contains at least one valid signature, 
         * according to the given trust policy; otherwise throws an Error.<br><br>
         * 
         * In order to be considered valid, there must be at least one signature on this CMS 
         * message which is validated by one of the certificates included with it; furthermore, 
         * the validating certificate must itself be valid according to the given certificate 
         * trust policy. This latter validation process may involve examining the other certificates 
         * or CRLs included with this object, if called for by the trust policy.<br><br>
         * 
         * If a signature is encountered for which a certification path can be found, but is 
         * invalid, an Error will be created, but will not be thrown until 
         * all other signatures have been checked. If another signature is found which is valid, 
         * then the method simply returns and no exception at all is thrown. 
         * 
         * @memberOf GostCMS.SignedDataContentInfo
         * @instance
         * @param {GostCert.CertificateTrustPolicy} trustPolicy The trust prolicy for verification
         * @param {(FormatedData|GostASN1.ContentInfo)} contentInfo The content that was signed (optional)
         * @returns {Promise} Promise to return enclosed object {@link GostASN1.ContentInfo} if signature verified
         */
        verify: function (trustPolicy, contentInfo)
        {
            var self = this, result;
            return new Promise(call).then(function () {
                // Append attached
                if (contentInfo)
                    self.setEnclosed(contentInfo);
                if (!self.signerInfos || self.signerInfos.length === 0)
                    throw new Error('No signatures found');
                // Validate certificate of signers
                return Promise.all(self.signerInfos.map(function (signerInfo, i) {
                    var sid = signerInfo.sid, selector = sid instanceof CryptoOperationData ? {
                        subjectKeyIdentifier: sid
                    } : {
                        issuer: sid.issuer,
                        serialNumber: sid.serialNumber};
                    // Signing date
                    var date;
                    if (signerInfo.signedAttrs && signerInfo.signedAttrs.signingTime)
                        date = signerInfo.signedAttrs.signingTime;
                    // Use certificate trust policy validation
                    return trustPolicy.getValidCertificate(selector,
                            self.certificates, self.crls, date).catch(function () {
                        return; // Ignore error
                    });
                }));

            }).then(function (certs) {
                // Get encapsulated data
                var verifiers = [];
                // Verify signatures for each signers
                certs.forEach(function (signerCert) {
                    if (signerCert)
                        verifiers.push(self.verifySignature(signerCert).then(function (data) {
                            result = data; // Enough one valid signature
                        }, function () {
                            return; // Ignore error
                        }));
                });
                if (verifiers.length === 0)
                    throw new Error('Valid verification path not found');
                return Promise.all(verifiers);
            }).then(function () {
                if (!result)
                    throw Error('Verification path found but no valid signature');
                // Return content
                return result;
            });
        },
        /**
         * Returns successfully if this CMS signed data object contains a signature which is 
         * validated by the given certificate and data; otherwise throws an Error.<br><br>
         * 
         * This method verifies the specified signature directly and ignores any certificates 
         * or CRLs which may be contained in this CMS object. A more complex verification process, 
         * which does make use of attached certificates and CRLs, is provided by the verify method.
         * 
         * @memberOf GostCMS.SignedDataContentInfo
         * @instance
         * @param {GostCert.X509} signerCert The signer certificate
         * @param {(FormatedData|GostASN1.ContentInfo)} contentInfo The content that was signed (optional)
         * @returns {Promise} Promise to return enclosed object {@link GostASN1.ContentInfo} if signature verified
         */
        verifySignature: function (signerCert, contentInfo)
        {
            var self = this, signerInfo, dataToVerify, dataDigest;
            return new Promise(call).then(function () {
                // Append attached
                if (contentInfo)
                    self.setEnclosed(contentInfo);
                dataToVerify = self.encapContentInfo && self.encapContentInfo.eContent;
                if (!dataToVerify)
                    throw new Error('Detached content is not found');
                // Find signer
                for (var i = 0; i < self.signerInfos.length; i++) {
                    var sid = self.signerInfos[i].sid;
                    if (matchCert(sid, signerCert)) {
                        signerInfo = self.signerInfos[i];
                        break;
                    }
                }
                if (!signerInfo)
                    throw new Error('Signature not found for the certificate');
                // Choice data for verification
                if (signerInfo.signedAttrs) {
                    dataDigest = signerInfo.signedAttrs.messageDigest;
                    if (!dataDigest)
                        throw new Error('Message digest must present in signed attributes');

                    // To exclude implicit [0] need to reassemble signed attributes (auto on CTX object)
                    dataToVerify = signerInfo.signedAttrs.encode();
                }
                if (!dataToVerify)
                    throw new Error('Data for verification not found');
                // Verify signature
                var algorithm = expand(signerInfo.signatureAlgorithm, {hash: signerInfo.digestAlgorithm});
                return signerCert.verifySignature(dataToVerify, signerInfo.signatureValue, algorithm);
            }).then(function (result) {
                if (!result)
                    throw new Error('Signature not verified');
                // Verify digest
                if (signerInfo.signedAttrs)
                    return subtle.digest(signerInfo.digestAlgorithm, self.encapContentInfo.eContent);
            }).then(function (digest) {
                if (digest && !equalBuffers(digest, dataDigest))
                    throw new Error('Message digest not verified');
                // Return content
                return createContentInfo({
                    contentType: self.encapContentInfo.eContentType,
                    content: self.encapContentInfo.eContent
                });
            });
        }
    });

    /**
     * This class encapsulates a CMS object of content type signed-data.
     * 
     * @memberOf GostCMS
     * @type GostCMS.SignedDataContentInfo
     */
    GostCMS.prototype.SignedDataContentInfo = SignedDataContentInfo;

    /**
     * This class encapsulates a CMS object of content type encrypted-data.
     * 
     * @class GostCMS.EncryptedDataContentInfo
     * @param {(FormatedData|GostASN1.ContentInfo)} contentInfo The encrypted data content.
     * @extends GostCMS.DataContentInfo
     * @extends GostASN1.EncryptedData
     */
    function EncryptedDataContentInfo(contentInfo)
    {
        DataContentInfo.call(this, contentInfo, {
            contentType: 'encryptedData',
            version: 0,
            encryptedContentInfo: {
                contentType: 'data',
                contentEncryptionAlgorithm: providers[options.providerName].encryption
            }
        });
    }

    extend(DataContentInfo, EncryptedDataContentInfo, {
        /**
         * Encrypt the content with given encryption algorithm, secret key or password
         * 
         * @memberOf GostCMS.EncryptedDataContentInfo
         * @instance
         * @param {(FormatedData|GostASN1.ContentInfo)} contentInfo The content data to be enclosed.
         * @param {Key|string} contentEncryptionKey content The encryption key or password for derive key
         * @param {(AlgorithmIdentifier|string)} encryptionAlgorithm The encryption algorithm or provider name
         * @returns {Promise} Promise to return self object after encrypt content
         */
        encloseContent: function (contentInfo, contentEncryptionKey, encryptionAlgorithm)
        {
            var self = this, encryption, derivation;
            return new Promise(call).then(function () {
                // Check content info
                contentInfo = checkContentInfo(contentInfo);
                if (!contentInfo.content)
                    throw new Error('Content for encryption must be specified');

                // Define encryption algorithm
                var type = typeof contentEncryptionKey === 'string' ? 'pbes' : 'encryption';
                if (encryptionAlgorithm) {
                    var provider = providers[encryptionAlgorithm];
                    encryptionAlgorithm = (provider && provider[type]) || encryptionAlgorithm;
                } else
                    encryptionAlgorithm = providers[options.providerName][type];
                // Prepare content encryption key
                if (encryptionAlgorithm.derivation) {
                    // Encrypt with password
                    derivation = expand(encryptionAlgorithm.derivation);
                    encryption = expand(encryptionAlgorithm.encryption);
                    derivation.salt = getSeed(saltSize(encryptionAlgorithm));
                    // Import password for key generation
                    var integrityKey;
                    return subtle.importKey('raw', passwordData(derivation, contentEncryptionKey),
                            derivation, false, ['deriveKey', 'deriveBits']).then(function (key) {
                        integrityKey = key;
                        // Derive IV
                        if (derivation.name.indexOf('PFXKDF') >= 0) {
                            derivation.diversifier = 2;
                            return subtle.deriveBits(derivation, integrityKey, 64);
                        }
                    }).then(function (iv) {
                        if (iv)
                            encryption.iv = iv;
                        // Generate key from password 
                        derivation.diversifier = 1;
                        return subtle.deriveKey(derivation, integrityKey, encryption, false, ['encrypt']);
                    }).then(function (encryptionKey) {
                        // Content encryption with key
                        return encryptionKey;
                    });
                } else {
                    // Base encryption
                    encryption = expand(encryptionAlgorithm);
                    if (contentEncryptionKey instanceof CryptoOperationData) {
                        // Import key
                        return subtle.importKey('raw', contentEncryptionKey, encryption, false, ['encrypt']);
                    } else if (contentEncryptionKey.type === 'secret') {
                        return contentEncryptionKey;
                    } else
                        throw new Error('Content encryption key must be raw data or secret key type');
                }
            }).then(function (encryptionKey) {
                // Initial vector
                if (!encryption.iv)
                    encryption.iv = getSeed(8);

                return subtle.encrypt(encryption, encryptionKey, contentInfo.content);
            }).then(function (encryptedContent) {
                if (encryptionAlgorithm.derivation) {
                    delete derivation.diversifier;
                    encryptionAlgorithm = expand(encryptionAlgorithm, {
                        derivation: derivation,
                        encryption: encryption
                    });
                } else
                    encryptionAlgorithm = encryption;
                // Set enclosed data
                self.encryptedContentInfo = {
                    contentType: contentInfo.contentType,
                    contentEncryptionAlgorithm: encryptionAlgorithm,
                    encryptedContent: encryptedContent
                };
                return self;
            });
        },
        /**
         * Returns the decrypted content. 
         * 
         * @memberOf GostCMS.EncryptedDataContentInfo
         * @instance
         * @param {Key|string} decryptionKey The decryption key or password for derive key   
         * @param {(FormatedData|GostASN1.ContentInfo)} contentInfo The detached content (optional).
         * @returns {Promise} Promise to return enclosed object {@ling GostASN1.ContentInfo} after decrypt content
         */
        getEnclosed: function (decryptionKey, contentInfo)
        {
            var self = this, encryption, derivation, encryptedContent;
            return new Promise(call).then(function () {
                // Append attached
                if (contentInfo)
                    self.setEnclosed(contentInfo);
                encryptedContent = self.encryptedContentInfo.encryptedContent;
                if (!encryptedContent)
                    throw new Error('Encrypted content must be specified');

                encryption = expand(self.encryptedContentInfo.contentEncryptionAlgorithm);
                if (encryption.derivation) {
                    // Decrypt with password
                    derivation = expand(encryption.derivation);
                    encryption = expand(encryption.encryption);
                    // Derive encryption key from password
                    var integrityKey;
                    return subtle.importKey('raw', passwordData(derivation, decryptionKey),
                            derivation, false, ['deriveKey', 'deriveBits']).then(function (key) {
                        integrityKey = key;
                        // Derive iv for PFX
                        if (derivation.name.indexOf('PFXKDF') >= 0) {
                            derivation.diversifier = 2;
                            return subtle.deriveBits(derivation, integrityKey, 64);
                        }
                    }).then(function (iv) {
                        if (iv)
                            encryption.iv = iv;
                        // Generate key from password 
                        derivation.diversifier = 1;
                        return subtle.deriveKey(derivation, integrityKey, encryption, false, ['decrypt']);
                    });
                } else {
                    // Base encryption. Password should be secret key
                    if (decryptionKey instanceof CryptoOperationData) {
                        // Import key
                        return subtle.importKey('raw', decryptionKey, encryption, false, ['decrypt']);
                    } else if (decryptionKey.type === 'secret') {
                        return decryptionKey;
                    } else
                        throw new Error('Decryption key must be raw data or secret key type');
                }
            }).then(function (encryptionKey) {
                // Decrypt key with encryption key
                return subtle.decrypt(encryption, encryptionKey, encryptedContent);
            }).then(function (decryptedContent) {
                // Create content info object
                return createContentInfo({
                    contentType: self.encryptedContentInfo.contentType,
                    content: decryptedContent
                });
            });
        }
    });

    /**
     * This class encapsulates a CMS object of content type encrypted-data.
     * 
     * @memberOf GostCMS
     * @type GostCMS.EncryptedDataContentInfo
     */
    GostCMS.prototype.EncryptedDataContentInfo = EncryptedDataContentInfo;
    /**
     * This class encapsulates a CMS object of content type enveloped-data.
     * 
     * @class GostCMS.EnvelopedDataContentInfo
     * @param {(FormatedData|GostASN1.ContentInfo)} contentInfo The encrypted data content.
     * @extends GostCMS.DataContentInfo
     * @extends GostASN1.EnvelopedData
     */
    function EnvelopedDataContentInfo(contentInfo)
    {
        DataContentInfo.call(this, contentInfo, {
            contentType: 'envelopedData',
            version: 0,
            recipientInfos: [],
            encryptedContentInfo: {
                contentType: 'data',
                contentEncryptionAlgorithm: providers[options.providerName].encryption
            }
        });
    }

    extend(DataContentInfo, EnvelopedDataContentInfo, {
        /**
         * Generate content encryption key with given encryption algorithm and encrypt the content
         * 
         * @memberOf GostCMS.EnvelopedDataContentInfo
         * @instance
         * @param {(FormatedData|GostASN1.ContentInfo)} contentInfo The content data to be enclosed.
         * @param {(AlgorithmIdentifier|string)} encryptionAlgorithm The encryption algorithm or provider name
         * @returns {Promise} Promise to return self object after encrypt content
         */
        encloseContent: function (contentInfo, encryptionAlgorithm)
        {
            var self = __webpack_require__.g;
            return new Promise(call).then(function () {
                // Check content info
                contentInfo = checkContentInfo(contentInfo);
                if (!contentInfo.content)
                    throw new Error('Content for encryption must be specified');
                // Define encryption algorithm
                if (encryptionAlgorithm) {
                    var provider = providers[encryptionAlgorithm];
                    encryptionAlgorithm = (provider && provider.encryption) || encryptionAlgorithm;
                } else
                    encryptionAlgorithm = providers[options.providerName].encryption;
                // Generate key for encryption content
                return subtle.generateKey(encryptionAlgorithm, true, ['encrypt']);
            }).then(function (encryptionKey) {
                // Encrypt content
                self.contentEncryptionKey = encryptionKey;
                // Initial vector
                if (!encryptionAlgorithm.iv)
                    encryptionAlgorithm.iv = getSeed(8);
                return subtle.encrypt(encryptionAlgorithm, encryptionKey, contentInfo.content);
            }).then(function (encryptedContent) {
                self.encryptedContentInfo = {
                    contentType: contentInfo.contentType,
                    contentEncryptionAlgorithm: encryptionAlgorithm,
                    encryptedContent: encryptedContent
                };
                return self;
            });
        },
        /**
         * Add a recipient. <br><br>
         * 
         * Uses the Recipient Information with IssuerAndSerialNumber as the Recipient Identifier.
         * Note: If senderCert specified uses the Key Agreement algorithm overwise Key Transport algorithm.
         * 
         * @memberOf GostCMS.EnvelopedDataContentInfo
         * @instance
         * @param {GostCert.X509} recipientCert The certificate of recepient
         * @param {(AlgorithmIdentifier|string)} keyEncryptionAlgorithm Key encryption algorithm or provider name
         * @param {GostASN1.PrivateKeyInfo} senderKey The private key of sender for key agreement protocol
         * @param {GostCert.X509} senderCert The certificate of sender for key agreement protocol
         * @returns {Promise} Promise to return self object after add recipient
         */
        addRecipient: function (recipientCert, keyEncryptionAlgorithm, senderKey, senderCert)
        {
            var self = this, privateKey, encryptionProvider, derivation, wrapping;
            return new Promise(call).then(function () {
                // Check for recepient cert
                recipientCert = new cert.X509(recipientCert);
                if (keyEncryptionAlgorithm && typeof keyEncryptionAlgorithm !== 'string' &&
                        !keyEncryptionAlgorithm.algorithm) {
                    // Sender parameters
                    senderCert = senderKey;
                    senderKey = keyEncryptionAlgorithm;
                    keyEncryptionAlgorithm = undefined;
                }
                if (keyEncryptionAlgorithm) {
                    encryptionProvider = providers[keyEncryptionAlgorithm];
                } else
                    encryptionProvider = recipientCert.getProvider();

                // Check for content encryption key
                if (!self.contentEncryptionKey)
                    throw new Error('The content encryption key is not assigned');

                if (senderCert) {
                    // Sender certificate for agreement protocol
                    var senderCertChain;
                    if (senderCert instanceof Array) {
                        senderCertChain = senderCert;
                        senderCert = senderCertChain[0];
                    } else
                        senderCertChain = [senderCert];

                    // Add sender certificate
                    if (options.autoAddCert) {
                        if (!self.originatorInfo)
                            self.originatorInfo = {certs: []};
                        else if (!self.originatorInfo.certs)
                            self.originatorInfo.certs = [];
                        for (var i = 0, n = senderCertChain.length; i < n; i++) {
                            addUnique(self.originatorInfo.certs, senderCertChain[i], function (cert1, cert2) {
                                return equalNames(cert1.issuer, cert2.issuer) &&
                                        equalNumbers(cert1.serialNumber, cert2.serialNumber);
                            });
                        }
                    }
                    // Key Agreement
                    if (encryptionProvider)
                        keyEncryptionAlgorithm = expand(encryptionProvider.agreement);
                    else
                        encryptionProvider = recipientCert.getProvider();
                    // Certificates must have similar curve parameters
                    if (recipientCert.subjectPublicKeyInfo.algorithm.namedCurve !==
                            senderCert.subjectPublicKeyInfo.algorithm.namedCurve)
                        throw new Error('The sender and the recipient have different public key algorithms');
                    // Get private sender key
                    return subtle.importKey('pkcs8', senderKey.encode(), senderKey.privateKeyAlgorithm,
                            false, ['deriveKey']);
                } else {
                    // Key Transport
                    if (encryptionProvider)
                        keyEncryptionAlgorithm = expand(recipientCert.subjectPublicKeyInfo.algorithm);
                    else
                        encryptionProvider = recipientCert.getProvider();
                    // Generate key pair
                    return subtle.generateKey(keyEncryptionAlgorithm, true, ['deriveKey']).then(function (keyPair) {
                        keyEncryptionAlgorithm['public'] = keyPair.publicKey;
                        return keyPair.privateKey;
                    });
                }
            }).then(function (key) {
                privateKey = key;
                // Get public key from recipient certificate
                return subtle.importKey('spki', recipientCert.subjectPublicKeyInfo.encode(),
                        recipientCert.subjectPublicKeyInfo.algorithm, false, ['deriveKey', 'deriveBits']);
            }).then(function (publicKey) {
                // Derivate key encryption key
                keyEncryptionAlgorithm.ukm = getSeed(8);
                derivation = expand(encryptionProvider.agreement,
                        {sBox: keyEncryptionAlgorithm.sBox, ukm: keyEncryptionAlgorithm.ukm, 'public': publicKey});
                wrapping = expand(keyEncryptionAlgorithm.wrapping || encryptionProvider.wrapping,
                        {ukm: keyEncryptionAlgorithm.ukm});
                return subtle.deriveKey(derivation, privateKey, wrapping, true, ['wrapKey']);
            }).then(function (wrappingKey) {
                // Wrap content encryption key 
                keyEncryptionAlgorithm.wrapping = wrapping;
                return subtle.wrapKey('raw', self.contentEncryptionKey, wrappingKey, wrapping);
            }).then(function (wrappedKey) {
                // Create recipient info
                var recipientInfo;
                var useKeyIdentifier = options.useKeyIdentifier && recipientCert.extensions &&
                        recipientCert.extensions.subjectKeyIdentifier,
                        rid = useKeyIdentifier ? recipientCert.extensions.subjectKeyIdentifier : {
                            issuer: recipientCert.issuer,
                            serialNumber: recipientCert.serialNumber};
                if (senderCert) {
                    var spki = senderCert.subjectPublicKeyInfo;
                    recipientInfo = {// KeyAgreeRecipientInfo
                        version: 3, // always set to 3
                        originator: {
                            algorithm: spki.algorithm,
                            publicKey: spki.subjectPublicKey
                        },
                        ukm: keyEncryptionAlgorithm.ukm,
                        keyEncryptionAlgorithm: keyEncryptionAlgorithm,
                        recipientEncryptedKeys: [{// use only one recipient in domain
                                rid: rid,
                                encryptedKey: asn1.GostEncryptedKey(keyEncryptionAlgorithm).encode(wrappedKey)
                            }]
                    };
                } else {
                    recipientInfo = {
                        version: 0, // always set to 0 or 2
                        rid: rid,
                        keyEncryptionAlgorithm: keyEncryptionAlgorithm,
                        encryptedKey: asn1.GostEncryptedKey(keyEncryptionAlgorithm).encode({
                            algorithm: keyEncryptionAlgorithm,
                            sessionEncryptedKey: wrappedKey
                        })
                    };
                }
                self.recipientInfos.push(recipientInfo);
                return self;
            });
        },
        /**
         * Returns the decrypted content. 
         * 
         * @memberOf GostCMS.EnvelopedDataContentInfo
         * @instance
         * @param {GostASN1.PrivateKeyInfo} recipientKey The decryption key or password for derive key   
         * @param {GostCert.X509} recipientCert  The decryption key or password for derive key   
         * @param {(FormatedData|GostASN1.ContentInfo)} contentInfo The detached content (optional).
         * @param {GostCert.X509} originatorCert The originator certificate (optional).
         * @returns {Promise} Promise to return enclosed object {@ling GostASN1.ContentInfo} after decrypt content
         */
        getEnclosed: function (recipientKey, recipientCert, contentInfo, originatorCert)
        {
            var self = this, wrappedKey, encryptedContent, derivation, wrapping, encryption;
            return new Promise(call).then(function () {
                var encryptionProvider = recipientCert.getProvider();
                // Append attached
                if (contentInfo)
                    self.setEnclosed(contentInfo);
                encryptedContent = self.encryptedContentInfo.encryptedContent;
                if (!encryptedContent)
                    throw new Error('Encrypted content must be specified');

                encryption = self.encryptedContentInfo.contentEncryptionAlgorithm;

                // Find receiver
                for (var i = 0; i < self.recipientInfos.length; i++) {
                    var recipientInfo = self.recipientInfos[i],
                            algorithm = expand(recipientInfo.keyEncryptionAlgorithm);
                    if (recipientInfo.rid) {
                        if (matchCert(recipientInfo.rid, recipientCert)) {
                            // Algorithm and wrapped key
                            var transportKey = asn1.GostEncryptedKey(algorithm).decode(recipientInfo.encryptedKey).object;
                            wrappedKey = transportKey.sessionEncryptedKey;
                            algorithm = expand(algorithm, transportKey.algorithm);
                            derivation = expand(encryptionProvider.agreement, {ukm: algorithm.ukm, sBox: algorithm.sBox});
                            wrapping = expand(encryptionProvider.wrapping, algorithm.wrapping, {ukm: algorithm.ukm});
                            return algorithm['public'];
                        }
                    } else {
                        var keys = recipientInfo.recipientEncryptedKeys;
                        if (keys) {
                            for (var j = 0; j < keys.length; j++) {
                                if (matchCert(keys[j].rid, recipientCert)) {
                                    // Algorithm and wrapped key
                                    algorithm = expand(encryptionProvider.agreement, algorithm, {ukm: recipientInfo.ukm});
                                    wrappedKey = asn1.GostEncryptedKey(algorithm).decode(keys[j].encryptedKey).object;
                                    derivation = algorithm;
                                    wrapping = expand(algorithm.wrapping || encryptionProvider.wrapping, {ukm: recipientInfo.ukm});
                                    // Check originator
                                    var originator = recipientInfo.originator;
                                    if (originator.algorithm) {
                                        var spki = new asn1.SubjectPublicKeyInfo({
                                            algorithm: originator.algorithm,
                                            subjectPublicKey: originator.publicKey});
                                        return subtle.importKey('spki', spki.encode(), spki.algorithm, false, ['deriveKey', 'deriveBits']);
                                    } else if (originatorCert && matchCert(originator, originatorCert))
                                        return importKey('pkcs', originatorCert.subjectPublicKeyInfo.encode(),
                                                originatorCert.subjectPublicKeyInfo.algorithm, false, ['deriveKey', 'deriveBits']);
                                    else
                                        throw Error('Originator certificate not specified or not valid');
                                }
                            }
                        }
                    }
                }
                throw new Error('Recipient not found or format not supported');
            }).then(function (publicKey) {
                derivation['public'] = publicKey;
                // Import private key
                return subtle.importKey('pkcs8', recipientKey.encode(), recipientKey.privateKeyAlgorithm,
                        false, ['deriveKey', 'deriveBits']);
            }).then(function (privateKey) {
                // Derive key
                return subtle.deriveKey(derivation, privateKey, wrapping, true, ['unwrapKey']);
            }).then(function (unwrappingKey) {
                // Unwrap key
                return subtle.unwrapKey('raw', wrappedKey, unwrappingKey,
                        wrapping, encryption, false, ['decrypt']);
            }).then(function (encryptionKey) {
                // Decrypt content
                return subtle.decrypt(encryption, encryptionKey, encryptedContent);
            }).then(function (decryptedContent) {
                return createContentInfo({
                    contentType: self.encryptedContentInfo.contentType,
                    content: decryptedContent
                });
            });
        }
    });

    /**
     * This class encapsulates a CMS object of content type enveloped-data.
     * 
     * @memberOf GostCMS
     * @type GostCMS.EnvelopedDataContentInfo
     */
    GostCMS.prototype.EnvelopedDataContentInfo = EnvelopedDataContentInfo;

    /**
     * Implements the Cryptographic Message Syntax as specified in RFC-2630.
     * 
     * @memberOf gostCrypto
     * @type GostCMS
     */
    gostCrypto.cms = new GostCMS();

module.exports = GostCMS;


/***/ }),

/***/ "./node_modules/node-gost-crypto/lib/gostCert.js":
/*!*******************************************************!*\
  !*** ./node_modules/node-gost-crypto/lib/gostCert.js ***!
  \*******************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

/**
 * @file Provides facilities for handling certificates, CRLs, etc.
 * @version 1.76
 * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *    
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice, this 
 *    list of conditions and the following disclaimer.
 *    
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *    
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

const gostCrypto = __webpack_require__(/*! ./gostCrypto */ "./node_modules/node-gost-crypto/lib/gostCrypto.js");

    /*
     * Common algorithms
     * 
     */
    var root = __webpack_require__.g;
    var Promise = root.Promise;
    var Object = root.Object;
    var CryptoOperationData = root.ArrayBuffer;
    var Date = root.Date;

    // Crypto subtle
    var subtle = gostCrypto.subtle;

    // Coding
    var coding = gostCrypto.coding;

    // ASN.1 syntax
    var asn1 = gostCrypto.asn1;

    // Providers
    var providers = gostCrypto.security.providers;

    // Expand javascript object
    function expand(r) {
        for (var i = 1, n = arguments.length; i < n; i++) {
            var item = arguments[i];
            if (typeof item === 'object')
                for (var name in item)
                    if (item.hasOwnProperty(name))
                        r[name] = item[name];
        }
        return r;
    }

    // Extend javascript class
    // function extend(Class) {
    //     var F = function () {
    //     };
    //     F.prototype = Class.prototype;
    //     var r = new F, args = [r];
    //     for (var i = 1; i < arguments.length; i++)
    //         args.push(arguments[i]);
    //     return expand.apply(this, args);
    // }

    // Today date + n days
    function today(n) {
        var date = new Date();
        date.setHours(0, 0, 0, 0);
        if (n)
            date.setDate(date.getDate() + n);
        return date;
    }

    // Self resolver
    function call(callback) {
        try {
            callback();
        } catch (e) {
        }
    }

    // Serial number
    function genSerialNumber() {
        var seed = new Uint8Array(4);
        gostCrypto.getRandomValues(seed);
        seed[0] = seed[0] & 0x7f;
        return coding.Int16.encode(seed);
    }

    // True if equal numbers
    var equalNumbers = (function () {
        // Convert number to bigendian hex string
        var hex = function (s) {
            var t = typeof s;
            return t === 'undefined' || s === '' ? '0' :
                    t === 'number' || s instanceof Number ? s.toString(16).toLowerCase() :
                    s.replace('0x', '').toLowerCase();
        };
        // Zero left padding
        var lpad = function (s, size) {
            return (new Array(size + 1).join('0') + s).slice(-size);
        };
        return function (s1, s2) {
            s1 = hex(s1);
            s2 = hex(s2);
            var len = Math.max(s1.length, s2.length);
            return lpad(s1, len) === lpad(s2, len);
        };
    })();

    // Check equal names
    function equalNames(name1, name2) {
        for (var key in name1)
            if (name1[key] !== name2[key])
                return false;
        for (var key in name2)
            if (name1[key] !== name2[key])
                return false;
        return true;
    }

    // Check the buffers to equal
    function equalBuffers(r1, r2) {
        var s1 = new Uint8Array(r1),
                s2 = new Uint8Array(r2);
        if (s1.length !== s2.length)
            return false;
        for (var i = 0, n = s1.length; i < n; i++)
            if (s1[i] !== s2[i])
                return false;
        return true;
    }

    // Match certificate
    function matchCertificate(cert, selector) {
        var skid = cert.extensions && cert.extensions.subjectKeyIdentifier;
        return (cert && selector &&
                (!selector.issuer || equalNames(cert.issuer, selector.issuer)) &&
                (!selector.serialNumber || equalNumbers(cert.serialNumber, selector.serialNumber)) &&
                (!selector.subjectKeyIdentifier || equalBuffers(skid, selector.subjectKeyIdentifier)) &&
                (!selector.subject || equalNames(cert.subject, selector.subject)) &&
                (!selector.date || (cert.notBefore.getTime() <= selector.date.getTime() &&
                        cert.notAfter.getTime() > selector.date.getTime())));
    }

    // Create authority certificate selector
    function authoritySelector(cert, extensions, date) {
        var selector = {subject: cert.issuer, date: date},
        akid = extensions && extensions.authorityKeyIdentifier;
        if (akid) {
            selector.subjectKeyIdentifier = akid.keyIdentifier;
            if (akid.authorityCertIssuer && akid.authorityCertIssuer[0] &&
                    akid.authorityCertSerialNumber) {
                selector.issuer = akid.authorityCertIssuer[0];
                selector.serialNumber = akid.authorityCertSerialNumber;
            }
        }
        return selector;
    }

    // Find certificates
    function selectCertificates(certs, selector) {
        var result = [];
        for (var i = 0, n = certs.length; i < n; i++)
            if (matchCertificate(certs[i], selector))
                result.push(certs[i]);
        return result;
    }

    // Match CRL
    function matchCRL(crl, selector) {
        return ((!selector.issuer || equalNames(crl.issuer, selector.issuer)) &&
                (!selector.date || (crl.thisUpdate.getTime() < selector.date.getTime())));
    }

    // Find certificates
    function selectCRLs(crls, selector) {
        var result = [];
        for (var i = 0, n = crls.length; i < n; i++)
            if (matchCRL(crls[i], selector))
                result.push(crls[i]);
        return result;
    }

    // Define provider for key algorithm
    function keyProvider(algorithm) {
        var id = algorithm.id;
        for (var name in providers) {
            var provider = providers[name];
            if (provider.publicKey.id === id)
                return provider;
        }
    }

    function defineProperty(object, name, descriptor, enumerable) {
        if (typeof descriptor !== 'object')
            descriptor = {value: descriptor};
        if (enumerable !== undefined)
            descriptor.enumerable = enumerable;
        Object.defineProperty(object, name, descriptor);
    }

    function defineProperties(object, properties, enumerable) {
        for (var name in properties)
            defineProperty(object, name, properties[name], enumerable);
    }

    // Extend javascript class
    function extend(Super, Class, propertiesObject, propertiesClass) {
        // If constructor not defined
        if (typeof Class !== 'function') {
            propertiesClass = propertiesObject;
            propertiesObject = Class;
            Class = function () {
                Super.apply(this, arguments);
            };
        }
        // Create prototype properties
        Class.prototype = Object.create(Super.prototype, {
            constructor: {
                value: Class
            },
            superclass: {
                value: Super.prototype
            }
        });
        if (propertiesObject)
            defineProperties(Class.prototype, propertiesObject, true);
        // Inherites super class properties
        if (Super !== Object)
            for (var name in Super)
                Class[name] = Super[name];
        Class.super = Super;
        if (propertiesClass)
            defineProperties(Class, propertiesClass, true);
        return Class;
    }



    /**
     * Provides facilities for handling certificates, CRLs, etc.
     * 
     * @class GostCert
     */
    function GostCert() {
    }

    /**
     * Certificate templates
     * <ul>
     *      <li>providerName - provider name for key generation, default 'CP-01'</li>
     *      <li>subject - template of subject name {countryName: 'RU', commonName: 'Anonymous'}</li>
     *      <li>caKeyUsage - default key usages for a CA certificates 
     *          ['digitalSignature', 'nonRepudiation', 'keyEncipherment',
     *          'dataEncipherment', 'keyAgreement', 'keyCertSign', 'cRLSign']</li>
     *      <li>caExtKeyUsage - default extended key usages for a CA certificates 
     *          ['serverAuth', 'clientAuth', 'codeSigning', 'emailProtection', 'ipsecEndSystem',
     *          'ipsecTunnel', 'ipsecUser', 'timeStamping', 'OCSPSigning']</li>
     *      <li>userKeyUsage - default key usages for a user certificate 
     *          ['digitalSignature', 'nonRepudiation', 'keyEncipherment', 'dataEncipherment', 'keyAgreement'],
     *      <li>userExtKeyUsage - default extended key usages for user certificate 
     *          ['clientAuth', 'emailProtection']</li>
     *      <li>days - validity of the certificate in days, default 7305</li>
     * </ul>
     * 
     * @memberOf GostCert
     * @instance
     */
    var options = {
        providerName: 'CP-01',
        subject: {countryName: 'RU', commonName: 'Anonymous'},
        caKeyUsage: ['digitalSignature', 'nonRepudiation', 'keyEncipherment',
            'dataEncipherment', 'keyAgreement', 'keyCertSign', 'cRLSign'],
        caExtKeyUsage: ['serverAuth', 'clientAuth', 'codeSigning', 'emailProtection', 'ipsecEndSystem',
            'ipsecTunnel', 'ipsecUser', 'timeStamping', 'OCSPSigning'],
        userKeyUsage: ['digitalSignature', 'nonRepudiation', 'keyEncipherment', 'dataEncipherment', 'keyAgreement'],
        userExtKeyUsage: ['clientAuth', 'emailProtection'],
        days: 7305
    };

    GostCert.prototype.options = options;

    /**
     * This class encapsulates X.509 Version 3 certificates.<br><br>
     * 
     * Constructs an X.509 certificate from the given DER encoding or ASN.1 Certificate object.
     * 
     * @class GostCert.X509
     * @extends GostASN1.Certificate
     * @param {(FormatedData|GostASN1.Certificate)} cert The certificate
     */
    var X509 = function (cert)
    {
        try {
            // Try to use decode X.509 certificate
            asn1.Certificate.call(this, cert, true);
        } catch (e) {
            try {
                // Try to decode certification request
                cert = new asn1.CertificationRequest(cert, true);
            } catch (e) {
            }
            // Create new certificate structure
            cert = cert || {};
            asn1.Certificate.call(this, {
                version: 2,
                serialNumber: cert.serialNumber || genSerialNumber(),
                signature: cert.signature || {id: 'noSignature'},
                issuer: cert.subject || options.subject,
                notBefore: cert.notBefore || today(),
                notAfter: cert.notAfter ||
                        today(cert.days || options.days),
                subject: cert.subject || options.subject,
                subjectPublicKeyInfo: cert.subjectPublicKeyInfo || {
                    algorithm: {id: 'noSignature'},
                    subjectPublicKey: new CryptoOperationData(0)
                },
                extensions: (cert.attributes && (cert.attributes.extensionRequest ||
                        cert.attributes.msCertExtensions)) || cert.extensions,
                signatureAlgorithm: {id: 'noSignature'},
                signatureValue: new CryptoOperationData(0)
            });
        }
    };

    extend(asn1.Certificate, X509, {
        /**
         * Generate the contents of this certificate and sign it.<br><br>
         * 
         * If issuerCertificate is not defined self signed certificate generated
         * 
         * @memberOf GostCert.X509
         * @instance
         * @param {GostASN1.PrivateKeyInfo} issuerPrivateKey The issuer's private key
         * @param {GostCert.X509} issuerCertificate The issuer's certificate or undefined for self-signed certificate
         * @returns {Promise} Promise to return self object after sign the certificate
         */
        sign: function (issuerPrivateKey, issuerCertificate)
        {

            var self = this, spki = self.subjectPublicKeyInfo;
            return new Promise(call).then(function () {

                // Need generated key
                if (!spki || !spki.algorithm || spki.algorithm === 'noSignature')
                    throw new Error('Key pair was not generated for the certificate');
                // Check issuer private key
                if (!issuerPrivateKey)
                    throw new Error('The private key of the issuer is not defined');
                        
                // Certificate can be self signed
                issuerCertificate = issuerCertificate || self;

                // Calculate subject key indentifier
                return subtle.digest('SHA-1', spki.subjectPublicKey);
            }).then(function (digest) {

                // Signature algorithm
                var provider = issuerCertificate.getProvider() || providers[options.providerName];
                if (!self.signature || self.signature.id === 'noSignature')
                    self.signature = provider.signature;
                self.signatureAlgorithm = self.signature;

                // Set issuer
                self.issuer = issuerCertificate.subject;
                // Set default extensions
                if (!self.extensions)
                    self.extensions = {};
                var exts = self.extensions, ae = issuerCertificate.extensions;
                if (self === issuerCertificate) { // Self-signed CA certificate
                    // Set key usage
                    exts.keyUsage = exts.keyUsage || options.caKeyUsage;
                    exts.extKeyUsage = exts.extKeyUsage || options.caExtKeyUsage;
                    // Set basic constraints
                    exts.basicConstraints = exts.basicConstraints || {cA: true};
                } else {
                    // Check key usage and validity
                    if (!issuerCertificate.checkUsage('keyCertSign', self.notBefore))
                        throw new Error('The issuer\'s certificate is not valid for signing a certificate');

                    // Set key usage
                    exts.keyUsage = exts.keyUsage || options.userKeyUsage;
                    exts.extKeyUsage = exts.extKeyUsage || options.userExtKeyUsage;
                    // Set basic constraints
                    exts.basicConstraints = exts.basicConstraints || {
                        cA: exts.keyUsage.indexOf('keyCertSign') >= 0
                    };
                    // Check path length constraint
                    if (exts.basicConstraints.cA) {
                        var pathLen = ae && ae.basicConstraints && ae.pathLenConstraint;
                        if (pathLen !== undefined) {
                            if (pathLen > 0)
                                exts.basicConstraints.pathLenConstraint = pathLen - 1;
                            else
                                throw new Error('Path length constraint exceeded');
                        }
                    }
                }
                // Subject key identifier 160 bit from public key hash
                exts.subjectKeyIdentifier = digest;
                // Authority key identifier
                if (ae && ae.subjectKeyIdentifier)
                    exts.authorityKeyIdentifier = {
                        keyIdentifier: ae.subjectKeyIdentifier,
                        authorityCertIssuer: [issuerCertificate.issuer],
                        authorityCertSerialNumber: issuerCertificate.serialNumber};

                // Import the private key
                return subtle.importKey('pkcs8', issuerPrivateKey.encode(), issuerPrivateKey.privateKeyAlgorithm, false, ['sign']);
            }).then(function (key) {

                // Sign certificate
                return subtle.sign(self.signatureAlgorithm, key, self.tbsCertificate.encode());
            }).then(function (signatureValue) {
                // Siganture value
                self.signatureValue = signatureValue;

                return self;
            });
        },
        /**
         * Generate key pair for certificate
         * 
         * @memberOf GostCert.X509
         * @instance
         * @param {(AlgorithmIdentifier|string)} keyAlgorithm The key algorithm or name of provider
         * @returns {Promise} Promise to return {@link GostASN1.PrivateKeyInfo} after self-signed certificate generation
         */
        generate: function (keyAlgorithm)
        {
            var self = this, privateKey, provider;
            if (keyAlgorithm)
                provider = providers[keyAlgorithm];
            else
                provider = this.getProvider() || providers[options.providerName];
            if (provider)
                keyAlgorithm = expand(provider.publicKey, {privateKey: provider.privateKey});

            return new Promise(call).then(function () {

                // Generate key pair
                return subtle.generateKey(keyAlgorithm, 'true', ['sign', 'verify']);
            }).then(function (keyPair) {
                privateKey = keyPair.privateKey;

                // Export public key
                return subtle.exportKey('spki', keyPair.publicKey);
            }).then(function (spki) {
                self.subjectPublicKeyInfo = new asn1.SubjectPublicKeyInfo(spki);

                return subtle.exportKey('pkcs8', privateKey);
            }).then(function (pkcs8) {

                return new asn1.PrivateKeyInfo(pkcs8);
            });
        },
        /**
         * Gets the public key.
         * 
         * @memberOf GostCert.X509
         * @instance
         * @returns {Promise} Promise to return {@link Key}
         */
        getPublicKey: function ()
        {
            var spki = this.subjectPublicKeyInfo,
                    keyUsages = (spki.algorithm.id === 'rsaEncryption') ? ['verify'] :
                    ['verify', 'deriveKey', 'deriveBits'];
            return subtle.importKey('spki', spki.encode(), spki.algorithm, 'false', keyUsages);
        },
        /**
         * Get appropriate crypto provider for public key
         * 
         * @memberOf GostCert.X509
         * @instance
         * @returns Object Set of crypto provider algorithms
         */
        getProvider: function ()
        {
            return keyProvider(this.subjectPublicKeyInfo.algorithm);
        },
        /**
         * Verifies this certificate.<br><br>
         * 
         * More precisely:<br><br>
         * <ul>
         *      <li>Verifies that the current VM date/time is within the validity period of the certificate.</li>
         *      <li>If an unrecognized critical extension is present, the certificate is rejected.</li> 
         *      <li>If the issuer certificate has been set, verifies that the signing certificate is a 
         *          CA certificate, and that the signature is correct. The signing certificate is considered 
         *          to be a CA certificate unless one of the following two conditions hold: The signing 
         *          certificate contains a basicConstraints extension, and the CA flag is false; or the 
         *          signing certificate contains a keyUsage extension, the keyUsage extension is marked 
         *          critical, and the keyCertSign bit is false.</li>
         *      <li>If the issuer CRL has been set, verifies that the certificate has not been revoked.</li>
         * </ul>
         * 
         * @memberOf GostCert.X509
         * @instance
         * @param {GostCert.X509} issuerCertificate The issuer X.509 certificate
         * @param {GostCert.CRL} issuerCRL The issuer CRL
         * @param {Date} date Validation date. Default current date
         * @returns {Promise} Promise to return self object if the certificate is valid
         */
        verify: function (issuerCertificate, issuerCRL, date)
        {
            var self = this, exts = self.extensions;
            return new Promise(call).then(function () {
                // Current date
                date = date || today();
                if (self.notBefore.getTime() > date.getTime() ||
                        self.notAfter.getTime() <= date.getTime())
                    throw new Error('The certificate has not yet started or expired');
                // A unrecognized critical extensions 
                for (var name in exts) {
                    var value = exts[name];
                    if (value.critical &&
                            ['authorityKeyIdentifier', 'subjectKeyIdentifier', 'keyUsage', 'certificatePolicies',
                                'policyMappings', 'basicConstraints', 'nameConstraints', 'policyConstraints',
                                'extKeyUsage'].indexOf(name) < 0)
                        throw new Error('The critical extension \'' + name + '\' is unrecognized');
                }
                // The certificate can be self-signed
                var selector = authoritySelector(self, exts, self.notBefore);
                if (!issuerCertificate && matchCertificate(self, selector))
                    issuerCertificate = self;
                // Check issuer
                if (issuerCertificate) {
                    if (!matchCertificate(issuerCertificate, selector) ||
                            !issuerCertificate.checkUsage('keyCertSign', self.notBefore))
                        throw new Error('The issuer\'s certificate is not valid');
                    // Check certificate signature
                    return issuerCertificate.verifySignature(self.tbsCertificate.encode(),
                            self.signatureValue, self.signatureAlgorithm);
                }
                return true;
            }).then(function (result) {
                if (!result)
                    throw new Error('The certificate has invalid signature');
                // Check CRL
                if (issuerCRL) {
                    if (!matchCRL(issuerCRL, {issuer: self.issuer, date: date}))
                        throw new Error('The issuer\'s CRL is not valid');
                    if (issuerCRL.isRevoked(self.serialNumber))
                        throw new Error('The certificate is revoked');
                }
                return self;
            });
        },
        /**
         * Verify a signature made with this certificate's public key.
         * 
         * @memberOf GostCert.X509
         * @instance
         * @param {CryptoOperationData} data The signed document.
         * @param {CryptoOperationData} signature The signature
         * @param {AlgorithmIdentifier} algorithm The algorithm ID used for the signature.
         * @returns {Promise} Promise to return true if the signature is verified, and false otherwise
         */
        verifySignature: function (data, signature, algorithm)
        {
            return this.getPublicKey().then(function (publicKey) {
                return subtle.verify(algorithm, publicKey, signature, data);
            });
        },
        /**
         * Check key usage and date validation
         * 
         * @memberOf GostCert.X509
         * @instance
         * @param {DOMString} operation The operation
         * @param {Date} date Operation date. Default current date
         * @returns {boolean} 
         */
        checkUsage: function (operation, date)
        {
            var self = this, exts = self.extensions;
            date = date || today();
            return (self.notBefore.getTime() <= date.getTime() && self.notAfter.getTime() > date.getTime()) &&
                    (!exts || !((['keyCertSign', 'cRLSign'].indexOf(operation) > 0 && exts.basicConstraints && !exts.basicConstraints.cA) ||
                            ((exts.keyUsage && exts.keyUsage.indexOf(operation) < 0) && (exts.extKeyUsage && exts.extKeyUsage.indexOf(operation) < 0))));
        }
    });

    /**
     * This class encapsulates X.509 Version 3 certificates.
     * 
     * @memberOf GostCert
     * @type GostCert.X509
     */
    GostCert.prototype.X509 = X509;

    /**
     * This class encapsulates a X.509 certificate revocation list (CRL) of RevokedCertificate objects.<br><br>
     *
     * Note: the methods and constructors that input a CRL do not automatically verify it. 
     * You need to explicitly call the verify method.
     *  
     * @class GostCert.CRL       
     * @extends GostASN1.CertificateList
     * @param {(FormatedData|GostASN1.CertificateList)} crl
     */
    var CRL = function (crl)
    {
        // Call super
        CRL.super.call(this, crl);
        // Initialize defaults
        if (!this.version)
            this.version = 1;
        if (!this.revokedCertificates)
            this.revokedCertificates = [];
        if (!this.thisUpdate)
            this.thisUpdate = today();
    };

    extend(asn1.CertificateList, CRL, {
        /**
         * Signs this CRL. The issuer's private key has to be set. The default random number generator is used, if needed.<br><br>
         * 
         * Note: Making any modifications to the contents of the CRL after signing invalidates the signature. 
         * The sign method must be invoked again after any modifications for a valid signature to be computed.
         * 
         * @memberOf GostCert.CRL
         * @instance
         * @param {GostASN1.PrivateKeyInfo} issuerPrivateKey the issuer's private signing key
         * @param {GostCert.X509} issuerCertificate the issuer's certificate
         * @returns {Promise} Promise to return self object after sign the CRL
         */
        sign: function (issuerPrivateKey, issuerCertificate)
        {

            var self = __webpack_require__.g;
            return new Promise(call).then(function () {
                // Check issuer private key
                if (!issuerPrivateKey)
                    throw new Error('The issuer\'s private key is not defined');
                // Check issuer certificate
                if (!issuerCertificate)
                    throw new Error('The issuer\'s certificate is not defined');
                // Check issuer name
                if (!self.issuer)
                    self.issuer = issuerCertificate.issuer;
                else if (!equalNames(self.issuer, issuerCertificate.issuer))
                    throw new Error('The CRL prototype and authority certificate have different issuers');
                // Check key usage and validity
                if (!issuerCertificate.checkUsage('cRLSign', self.thisUpdate))
                    throw new Error('The issuer\'s certificate is not valid for signing a CRL');

                // Signature algorithm
                var provider = issuerCertificate.getProvider() || providers[options.providerName];
                if (!self.signature)
                    self.signature = provider.signature;
                self.signatureAlgorithm = self.signature;

                // Set issuer
                self.issuer = issuerCertificate.subject;
                // Set default extensions
                if (!self.crlExtensions)
                    self.crlExtensions = {};
                var exts = self.crlExtensions,
                        ae = issuerCertificate.extensions;
                if (ae && ae.subjectKeyIdentifier)
                    exts.authorityKeyIdentifier = {
                        keyIdentifier: ae.subjectKeyIdentifier,
                        authorityCertIssuer: [issuerCertificate.issuer],
                        authorityCertSerialNumber: issuerCertificate.serialNumber};
                exts.cRLNumber = exts.cRLNumber || 0;

                // Import the private key
                return subtle.importKey('pkcs8', issuerPrivateKey.encode(),
                        issuerPrivateKey.privateKeyAlgorithm, false, ['sign']);
            }).then(function (key) {

                // Sign CRL
                return subtle.sign(self.signatureAlgorithm, key, self.tbsCertList.encode());
            }).then(function (signatureValue) {

                // Siganture value
                self.signatureValue = signatureValue;
                return self;
            });
        },
        /**
         * Verify the CRL. Checks the date and signature if issuer's certifiate has been defined.
         * 
         * @memberOf GostCert.CRL
         * @instance
         * @param {GostCert.X509} issuerCertificate the issuer's certificate
         * @param {Date} date Validation date. Default current date
         * @returns {Promise} Promise to return self object if the certificate is valid
         */
        verify: function (issuerCertificate, date)
        {
            var self = this, exts = self.crlExtensions;
            return new Promise(call).then(function () {
                // Current date
                date = date || today();
                if (!self.thisUpdate.getTime() > date.getTime())
                    throw new Error('The CRL has not yet started');
                // Check issuer
                if (issuerCertificate) {
                    if (!matchCertificate(issuerCertificate, authoritySelector(self, exts, self.thisUpdate)) ||
                            !issuerCertificate.checkUsage('cRLSign', self.thisUpdate))
                        throw new Error('The issuer\'s certificate is not valid');
                    if (!self.signatureValue || !self.signatureAlgorithm)
                        throw new Error('The has no signature');
                    // Check CRL signature
                    return issuerCertificate.verifySignature(self.tbsCertList.encode(),
                            self.signatureValue, self.signatureAlgorithm);
                }
            }).then(function (result) {
                if (!result)
                    throw new Error('The CRL has invalid signature');
                return self;
            });
        },
        /**
         * Checks whether this certificate serial number is on the list.
         * 
         * @memberOf GostCert.CRL
         * @instance
         * @param {Number} serialNumber the issuer's certificate
         * @param {Date} date Validation date. Default current date
         * @returns {boolean} True if the certificate is valid, and false otherwise
         */
        isRevoked: function (serialNumber, date)
        {
            var rc = this.revokedCertificates;
            date = date || today();
            for (var i = 0; i < rc.length; i++) {
                // Check date and serial number
                if (date.getTime() >= rc[i].revocationDate.getTime() &&
                        equalNumbers(rc[i].userCertificate, serialNumber))
                    return true;
            }
            return false;
        }
    });

    /**
     * This class encapsulates a X.509 certificate revocation list (CRL) of RevokedCertificate objects.
     * 
     * @memberOf GostCert
     * @type GostCert.CRL
     */
    GostCert.prototype.CRL = CRL;

    /**
     * A class that encapsulates a DER-encoded PKCS #10 certificate request. The request contains 
     * the subject's name and public key, and it is signed with the subject's private key. 
     * The public key contained in the request is used to verify the signature. 
     * The signature on the request is verified automatically when the request is read. 
     * Note that the subject's private key is used only to produce a signature when the request is output, 
     * and is not actually stored with the request.
     * 
     * @class GostCert.Request
     * @extends GostASN1.CertificationRequest
     * @param {(FormatedData|GostASN1.CertificationRequest)} req
     */
    function Request(req)
    {
        try {
            // Try to use encode
            asn1.CertificationRequest.call(this, req, true);
        } catch (e) {
            // Create new certificate structure
            req = req || {};
            asn1.CertificationRequest.call(this, {
                version: 0,
                subject: req.subject || options.subject,
                subjectPublicKeyInfo: req.subjectPublicKeyInfo || {
                    algorithm: {id: 'noSignature'},
                    subjectPublicKey: new CryptoOperationData(0)
                },
                attributes: req.attributes || {
                    extensionRequest: {
                        keyUsage: options.userKeyUsage,
                        extKeyUsage: options.userExtKeyUsage
                    }
                },
                signatureAlgorithm: {id: 'noSignature'},
                signatureValue: new CryptoOperationData(0)
            });
        }
    }

    extend(asn1.CertificationRequest, Request, {
        /**
         * Generate key pair and sign request
         * 
         * @memberOf GostCert.Request
         * @instance
         * @param {(AlgorithmIdentifier|string)} keyAlgorithm The name of provider or algorithm
         * @returns {Promise} Promise to return {@link GostASN1.PrivateKeyInfo} after request generation
         */
        generate: function (keyAlgorithm)
        {
            var self = this, privateKey, provider;
            if (keyAlgorithm)
                provider = providers[keyAlgorithm];
            else
                provider = this.getProvider() || providers[options.providerName];
            if (provider)
                keyAlgorithm = expand(provider.publicKey, {privateKey: provider.privateKey});

            return new Promise(call).then(function () {

                // Generate key pair
                return subtle.generateKey(keyAlgorithm, 'true', ['sign', 'verify']);
            }).then(function (keyPair) {
                privateKey = keyPair.privateKey;

                // Export public key
                return subtle.exportKey('spki', keyPair.publicKey);
            }).then(function (spki) {
                self.subjectPublicKeyInfo = new asn1.SubjectPublicKeyInfo(spki);

                return subtle.exportKey('pkcs8', privateKey);
            }).then(function (pkcs8) {
                privateKey = new asn1.PrivateKeyInfo(pkcs8);

                // Sign request
                return self.sign(privateKey);
            }).then(function () {

                return privateKey;
            });
        },
        /**
         * Get appropriate crypto provider for public key
         * 
         * @memberOf GostCert.Request
         * @instance
         * @returns Object Set of crypto provider algorithms
         */
        getProvider: function ()
        {
            return keyProvider(this.subjectPublicKeyInfo.algorithm);
        },
        /**
         * Generate the contents of this request and sign it.<br><br>
         * 
         * @memberOf GostCert.Request
         * @instance
         * @param {GostASN1.PrivateKeyInfo} privateKey The subject's private key
         * @returns Promise to return self object after sign the request
         */
        sign: function (privateKey)
        {

            var self = this, spki = self.subjectPublicKeyInfo;
            return new Promise(call).then(function () {

                // Need generated key
                if (!spki || !spki.algorithm || spki.algorithm === 'noSignature')
                    throw new Error('Key pair was not generated for the certificate');
                // Check issuer private key
                if (!privateKey)
                    throw new Error('The private key is not defined');

                // Signature algorithm
                var provider = keyProvider(spki.algorithm) || providers[options.providerName];
                self.signatureAlgorithm = provider.signature;

                // Import the private key
                return subtle.importKey('pkcs8', privateKey.encode(),
                        privateKey.privateKeyAlgorithm, false, ['sign']);
            }).then(function (key) {

                // Sign the certification request
                return subtle.sign(self.signatureAlgorithm, key, self.requestInfo.encode());
            }).then(function (signatureValue) {

                // Siganture value
                self.signatureValue = signatureValue;
                return self;
            });
        },
        /**
         * Verify the Certification Request. Checks the signature on the public key in the request.
         * 
         * @memberOf GostCert.Request
         * @instance
         * @returns {Promise} Promise to return self object  if the certificate is valid
         */
        verify: function ()
        {
            var self = this, spki = self.subjectPublicKeyInfo;
            return new Promise(call).then(function () {

                // Import key
                return subtle.importKey('spki', spki.encode(), spki.algorithm, 'false', ['verify']);
            }).then(function (publicKey) {

                // Verify signature
                return subtle.verify(self.signatureAlgorithm, publicKey, self.signatureValue,
                        self.requestInfo.encode());
            }).then(function (result) {
                if (!result)
                    throw new Error('The certification request has invalid signature');
                return self;
            });
        }
    });

    /**
     * A class that encapsulates a DER-encoded PKCS #10 certificate request.
     * 
     * @memberOf GostCert
     * @type GostCert.Request
     */
    GostCert.prototype.Request = Request;

    /**
     * A class for retrieving Certificates and CRLs from a repository.<br><br>
     * 
     * Once the CertStore has been created, it can be used to retrieve Certificates 
     * and CRLs by calling its getCertificates and getCRLs methods. Unlike a KeyStore, 
     * which provides access to a cache of private keys and trusted certificates, 
     * a CertStore is designed to provide access to a potentially vast repository 
     * of untrusted certificates and CRLs.
     * 
     * @class GostCert.CertStore
     * @param {GostCert.X509[]} certificates Certificates
     * @param {GostCert.CRL[]} crls CLRs
     */
    function CertStore(certificates, crls)
    {
        this.certificates = certificates || [];
        this.crls = crls || [];
    }

    extend(Object, CertStore, {
        /**
         * Returns a Array of Certificates that match the specified selector.
         * 
         * @memberOf GostCert.CertStore
         * @instance
         * @param {GostCert.CertSelector} selector Certificate filter selector
         * @returns {GostCert.X509[]} Selected certificates
         */
        getCertificates: function (selector)
        {
            return selectCertificates(this.certificates, selector);
        },
        /**
         * Returns a Collection of CRLs that match the specified selector.
         * 
         * @memberOf GostCert.CertStore
         * @instance
         * @param {GostCert.CertSelector} selector CRL filter selector
         * @returns {GostCert.CRL[]} selected CRLs
         */
        getCRLs: function (selector)
        {
            return selectCRLs(this.certificates, selector);
        },
        /**
         * Loads this CertStore from the given PKCS#7 formated input stream.
         * 
         * @memberOf GostCert.CertStore
         * @instance
         * @param {(FormatedData|GostASN1.ContentInfo)} store The input stream from which the certstore is loaded
         * @returns {GostCert.CertStore} Self object after store loaded
         */
        load: function (store)
        {
            var info = new asn1.ContentInfo(store),
                    certs = info.certificates, crls = info.crls;
            for (var i = 0; i < certs.length; i++)
                this.certificates.push(new X509(certs[i]));
            for (var i = 0; i < crls.length; i++)
                this.crls.push(new CRL(crls[i]));
            return this;
        },
        /**
         * Stores this CertStore to the given output stream in PKCS#7 format.
         * 
         * @memberOf GostCert.CertStore
         * @instance
         * @returns {GostASN1.ContentInfo} PKCS#7 content info with certificates and crls from CertStore
         */
        store: function ()
        {
            return new asn1.ContentInfo({
                contentType: 'signedData',
                version: 0,
                digestAlgorithms: [],
                encapContentInfo: {contentType: 'data'},
                certificates: this.certs,
                crls: this.crls,
                signerInfos: []
            });
        }
    });

    /**
     * A class for retrieving Certificates and CRLs from a repository.
     * 
     * @memberOf GostCert
     * @type GostCert.Request
     */
    GostCert.prototype.CertStore = CertStore;

    /**
     * A class for building and validating certification paths (also known as certificate chains).
     * 
     * @class GostCert.CertPath
     * @param {GostCert.CertStore} certStore
     */
    function CertPath(certStore)
    {
        this.certStore = certStore;
    }

    extend(Object, CertPath, {
        /**
         * Attempts to build a certification path using the specified algorithm parameter set.
         * 
         * @memberOf GostCert.CertPath
         * @instance
         * @param {GostCert.X509} certificate Starting path certificate 
         * @param {Date} date Validation date. Default today
         * @returns {Promise} Promise to return array of {@link GostCert.X509} with certification path
         */
        build: function (certificate, date)
        {
            var self = __webpack_require__.g;
            return new Promise(call).then(function () {
                // Build certification path
                var current = new X509(certificate), certPath = [], success = false, verifiers = [];
                while (current) {
                    var foundCRLs = [], founds = [];
                    certPath.push(current);
                    if (!success) {
                        // Select issuer CRL
                        foundCRLs = self.certStore.getCRLs({issuer: current.issuer, date: date});
                        // Create issuer's selection criteria
                        var selector = authoritySelector(current, current.extensions,
                                current.notBefore);
                        // Self-signed certificate?
                        if (!matchCertificate(current, selector))
                            // Select issuer form trusted CA root list
                            founds = self.certStore.getCertificates(selector);
                        else
                            success = true;
                    }
                    // Add verification tasks
                    var next = founds.length > 0 && new X509(founds[0]),
                            crl = foundCRLs.length > 0 && new CRL(foundCRLs[0]);
                    // Verify CRLs
                    if (crl)
                        verifiers.push(crl.verify(next, date));

                    // Verify the certificate
                    verifiers.push(current.verify(next, crl, date));
                    current = next;
                }
                if (!success)
                    throw new Error('Root certificate is not found');
                // Verify all certificates in path
                return Promise.all(verifiers).then(function (results) {
                    for (var i = 0; i < results; i++)
                        if (!results[i])
                            throw new Error('Certification path is not validated');
                    return certPath;
                });
            });
        }
    });

    /**
     * A class for building and validating certification paths (also known as certificate chains).
     * 
     * @memberOf GostCert
     * @type GostCert.CertPath
     */
    GostCert.prototype.CertPath = CertPath;

    /**
     * A generic interface for implementing a particular certificate verification 
     * scheme, such as constructing and verifying 
     * certificate chains.
     * 
     * @class GostCert.CertificateTrustPolicy
     */
    function CertificateTrustPolicy() {
    }

    extend(Object, CertificateTrustPolicy, {
        /**
         * Returns a certificate, known to be valid (according to criteria dependent 
         * on the verification scheme), which has the given selector, certificate and 
         * CRL lists to implement a particular certificate verification  scheme, 
         * such a forming valid certificate chains.<br>
         * Second and third argument to this method may be undefined, and such a case 
         * must be treated exactly the same as if the particular argument was an empty array.
         * 
         * @memberOf GostCert.CertificateTrustPolicy
         * @instance
         * @param {GostCert.CertificateSelector} selector Certificate selector
         * @param {GostCert.X509[]} certificates Certificates
         * @param {GostCert.CRL[]} crls CLRs
         * @returns {Promise} Promise to return valid {@link GostCert.X509}
         */
        getValidCertificate: function (selector, certificates, crls) {
        }
    });

    /**
     * A generic interface for implementing a particular certificate verification
     * 
     * @memberOf GostCert
     * @type GostCert.CertificateTrustPolicy
     */
    GostCert.prototype.CertificateTrustPolicy = CertificateTrustPolicy;

    /**
     * A certificate trust policy based on a set of trusted root CAs.<br><br>
     * 
     * In this policy, a certificate will be trusted if and only if it is part of a 
     * valid certificate chain which terminates in one of the trusted root CAs. <br><br>
     * 
     * This policy has two options for certificate chain verification:
     * <ul>
     *      <li>requireCRL - If true, then for every certificate in a chain 
     *          (unless it is one of the trusted root CA certificates) a valid CRL 
     *          must be provided to determine its revocation status. The default is false.</li>
     *      <li>requireCAFlag - If true, then every intermediate CA certificate (excluding 
     *          the root CA or the end entity certificate) must contain a Basic Constraints 
     *          extension, with the CA flag set. The default for this option is true.</li>
     * </ul>
     * 
     * @class GostCert.TrustedCAPolicy
     * @extends GostCert.CertificateTrustPolicy
     * @param {GostCert.X509[]} trustedCACerts 
     * @param {boolean} requireCRL 
     * @param {boolean} requireCA 
     */
    function TrustedCAPolicy(trustedCACerts, requireCRL, requireCA)
    {
        this.trustedCACerts = trustedCACerts || [];
        this.requireCRL = requireCRL || false;
        this.requireCA = requireCA || true;
    }

    extend(CertificateTrustPolicy, TrustedCAPolicy, {
        /**
         * Returns a certificate, known to be valid (according to criteria dependent 
         * on the verification scheme), which has the given selector, certificate and 
         * CRL lists to implement a particular certificate verification  scheme, 
         * such a forming valid certificate chains.<br>
         * Second and third argument to this method may be undefined, and such a case 
         * must be treated exactly the same as if the particular argument was an empty array.
         * 
         * @memberOf GostCert.TrustedCAPolicy
         * @instance
         * @param {GostCert.CertificateSelector} selector Certificate selector
         * @param {GostASN1.Certificate[]} certificates Certificates
         * @param {GostASN1.CertificateList[]} crls CLRs
         * @param {Date} date Validation date. Default today
         * @returns {Promise} Promise to return valid {@link GostCert.X509}
         */
        getValidCertificate: function (selector, certificates, crls, date)
        {
            var self = this, certPath;
            return new Promise(call).then(function () {
                certificates = certificates || [];
                crls = crls || [];
                // Get certificates from the trusted list
                var certs = selectCertificates(self.trustedCACerts, selector);
                if (certs.length > 0)
                    return new X509(certs[0]);
                // Get certificates from the list
                certs = selectCertificates(certificates, selector);
                if (certs.length === 0)
                    return;
                // Build certification path
                var current = new X509(certs[0]), success = false, verifiers = [];
                certPath = [];
                while (current) {
                    var foundCRLs = [], founds = [];
                    certPath.push(current);
                    if (!success) {
                        // Select issuer CRL
                        foundCRLs = selectCRLs(crls, {issuer: current.issuer, date: date});
                        if (foundCRLs.length === 0 && self.requireCRL)
                            return; // The issuer\'s CRL is not found
                        // Create issuer's selection criteria
                        selector = authoritySelector(current, current.extensions,
                                current.notBefore);
                        // Select issuer form trusted CA root list
                        founds = selectCertificates(self.trustedCACerts, selector);
                        if (founds.length === 0) {
                            // Non-trusted self-signed certificate?
                            if (!matchCertificate(current, selector)) {
                                // Select issuer from certificate list
                                founds = selectCertificates(certificates, selector);
                                if (founds.length > 0) {
                                    // Check basic contrains and CA flag
                                    var exts = founds[0].extensions;
                                    if (self.requireCA) {
                                        if (!exts || !exts.basicConstraints || !exts.basicConstraints.cA)
                                            return; // The issuer\'s certificate is not valid
                                        // Check path length limit
                                        if (exts.basicConstraints.pathLenConstraint !== undefined &&
                                                exts.basicConstraints.pathLenConstraint < certPath.length - 1)
                                            return; // The issuer\'s certificate path length constraint exceeded
                                    }
                                } else
                                    return; // Certification path is not built
                            }
                        } else
                            success = true;
                    }
                    // Add verification tasks
                    var next = founds.length > 0 && new X509(founds[0]),
                            crl = foundCRLs.length > 0 && new CRL(foundCRLs[0]);
                    // Verify CRLs
                    if (crl)
                        verifiers.push(crl.verify(next, date));

                    // Verify the certificate
                    verifiers.push(current.verify(next, crl, date));
                    current = next;
                }
                if (!success)
                    throw new Error('Trusted root certificate is not found');
                // Verify all certificates in path
                return Promise.all(verifiers).then(function (results) {
                    for (var i = 0; i < results; i++)
                        if (!results[i])
                            throw new Error('Certification path is not validated');
                    return certPath[0];
                });
            });
        }
    });

    /**
     * A certificate trust policy based on a set of trusted root CAs.
     * 
     * @memberOf GostCert
     * @type GostCert.TrustedCAPolicy
     */
    GostCert.prototype.TrustedCAPolicy = TrustedCAPolicy;

    /**
     * Provides facilities for handling certificates, CRLs, etc.
     * 
     * @memberOf gostCrypto
     * @type GostCert
     */
    gostCrypto.cert = new GostCert();

module.exports = GostCert;




/***/ }),

/***/ "./node_modules/node-gost-crypto/lib/gostCipher.js":
/*!*********************************************************!*\
  !*** ./node_modules/node-gost-crypto/lib/gostCipher.js ***!
  \*********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

/**
 * @file GOST 28147-89/GOST R 34.12-2015/GOST R 32.13-2015 Encryption Algorithm
 * @version 1.76
 * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *    
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

const GostRandom = __webpack_require__(/*! ./gostRandom */ "./node_modules/node-gost-crypto/lib/gostRandom.js");

    /*
     * Initial parameters and common algortithms of GOST 28147-89 
     * 
     * http://tools.ietf.org/html/rfc5830
     * 
     */

    var root = __webpack_require__.g;
    var rootCrypto = root.crypto || root.msCrypto;
    var CryptoOperationData = root.ArrayBuffer;
    var SyntaxError = root.SyntaxError || root.Error,
            DataError = root.DataError || root.Error,
            NotSupportedError = root.NotSupportedError || root.Error;
    /*
     * Check supported
     * This implementation support only Little Endian arhitecture
     */

    var littleEndian = (function () {
        var buffer = new CryptoOperationData(2);
        new DataView(buffer).setInt16(0, 256, true);
        return new Int16Array(buffer)[0] === 256;
    })();

    // Default initial vector
    var defaultIV = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0]);

    // Predefined sBox collection
    var sBoxes = {
        'E-TEST': [
            0x4, 0x2, 0xF, 0x5, 0x9, 0x1, 0x0, 0x8, 0xE, 0x3, 0xB, 0xC, 0xD, 0x7, 0xA, 0x6,
            0xC, 0x9, 0xF, 0xE, 0x8, 0x1, 0x3, 0xA, 0x2, 0x7, 0x4, 0xD, 0x6, 0x0, 0xB, 0x5,
            0xD, 0x8, 0xE, 0xC, 0x7, 0x3, 0x9, 0xA, 0x1, 0x5, 0x2, 0x4, 0x6, 0xF, 0x0, 0xB,
            0xE, 0x9, 0xB, 0x2, 0x5, 0xF, 0x7, 0x1, 0x0, 0xD, 0xC, 0x6, 0xA, 0x4, 0x3, 0x8,
            0x3, 0xE, 0x5, 0x9, 0x6, 0x8, 0x0, 0xD, 0xA, 0xB, 0x7, 0xC, 0x2, 0x1, 0xF, 0x4,
            0x8, 0xF, 0x6, 0xB, 0x1, 0x9, 0xC, 0x5, 0xD, 0x3, 0x7, 0xA, 0x0, 0xE, 0x2, 0x4,
            0x9, 0xB, 0xC, 0x0, 0x3, 0x6, 0x7, 0x5, 0x4, 0x8, 0xE, 0xF, 0x1, 0xA, 0x2, 0xD,
            0xC, 0x6, 0x5, 0x2, 0xB, 0x0, 0x9, 0xD, 0x3, 0xE, 0x7, 0xA, 0xF, 0x4, 0x1, 0x8
        ],
        'E-A': [
            0x9, 0x6, 0x3, 0x2, 0x8, 0xB, 0x1, 0x7, 0xA, 0x4, 0xE, 0xF, 0xC, 0x0, 0xD, 0x5,
            0x3, 0x7, 0xE, 0x9, 0x8, 0xA, 0xF, 0x0, 0x5, 0x2, 0x6, 0xC, 0xB, 0x4, 0xD, 0x1,
            0xE, 0x4, 0x6, 0x2, 0xB, 0x3, 0xD, 0x8, 0xC, 0xF, 0x5, 0xA, 0x0, 0x7, 0x1, 0x9,
            0xE, 0x7, 0xA, 0xC, 0xD, 0x1, 0x3, 0x9, 0x0, 0x2, 0xB, 0x4, 0xF, 0x8, 0x5, 0x6,
            0xB, 0x5, 0x1, 0x9, 0x8, 0xD, 0xF, 0x0, 0xE, 0x4, 0x2, 0x3, 0xC, 0x7, 0xA, 0x6,
            0x3, 0xA, 0xD, 0xC, 0x1, 0x2, 0x0, 0xB, 0x7, 0x5, 0x9, 0x4, 0x8, 0xF, 0xE, 0x6,
            0x1, 0xD, 0x2, 0x9, 0x7, 0xA, 0x6, 0x0, 0x8, 0xC, 0x4, 0x5, 0xF, 0x3, 0xB, 0xE,
            0xB, 0xA, 0xF, 0x5, 0x0, 0xC, 0xE, 0x8, 0x6, 0x2, 0x3, 0x9, 0x1, 0x7, 0xD, 0x4
        ],
        'E-B': [
            0x8, 0x4, 0xB, 0x1, 0x3, 0x5, 0x0, 0x9, 0x2, 0xE, 0xA, 0xC, 0xD, 0x6, 0x7, 0xF,
            0x0, 0x1, 0x2, 0xA, 0x4, 0xD, 0x5, 0xC, 0x9, 0x7, 0x3, 0xF, 0xB, 0x8, 0x6, 0xE,
            0xE, 0xC, 0x0, 0xA, 0x9, 0x2, 0xD, 0xB, 0x7, 0x5, 0x8, 0xF, 0x3, 0x6, 0x1, 0x4,
            0x7, 0x5, 0x0, 0xD, 0xB, 0x6, 0x1, 0x2, 0x3, 0xA, 0xC, 0xF, 0x4, 0xE, 0x9, 0x8,
            0x2, 0x7, 0xC, 0xF, 0x9, 0x5, 0xA, 0xB, 0x1, 0x4, 0x0, 0xD, 0x6, 0x8, 0xE, 0x3,
            0x8, 0x3, 0x2, 0x6, 0x4, 0xD, 0xE, 0xB, 0xC, 0x1, 0x7, 0xF, 0xA, 0x0, 0x9, 0x5,
            0x5, 0x2, 0xA, 0xB, 0x9, 0x1, 0xC, 0x3, 0x7, 0x4, 0xD, 0x0, 0x6, 0xF, 0x8, 0xE,
            0x0, 0x4, 0xB, 0xE, 0x8, 0x3, 0x7, 0x1, 0xA, 0x2, 0x9, 0x6, 0xF, 0xD, 0x5, 0xC
        ],
        'E-C': [
            0x1, 0xB, 0xC, 0x2, 0x9, 0xD, 0x0, 0xF, 0x4, 0x5, 0x8, 0xE, 0xA, 0x7, 0x6, 0x3,
            0x0, 0x1, 0x7, 0xD, 0xB, 0x4, 0x5, 0x2, 0x8, 0xE, 0xF, 0xC, 0x9, 0xA, 0x6, 0x3,
            0x8, 0x2, 0x5, 0x0, 0x4, 0x9, 0xF, 0xA, 0x3, 0x7, 0xC, 0xD, 0x6, 0xE, 0x1, 0xB,
            0x3, 0x6, 0x0, 0x1, 0x5, 0xD, 0xA, 0x8, 0xB, 0x2, 0x9, 0x7, 0xE, 0xF, 0xC, 0x4,
            0x8, 0xD, 0xB, 0x0, 0x4, 0x5, 0x1, 0x2, 0x9, 0x3, 0xC, 0xE, 0x6, 0xF, 0xA, 0x7,
            0xC, 0x9, 0xB, 0x1, 0x8, 0xE, 0x2, 0x4, 0x7, 0x3, 0x6, 0x5, 0xA, 0x0, 0xF, 0xD,
            0xA, 0x9, 0x6, 0x8, 0xD, 0xE, 0x2, 0x0, 0xF, 0x3, 0x5, 0xB, 0x4, 0x1, 0xC, 0x7,
            0x7, 0x4, 0x0, 0x5, 0xA, 0x2, 0xF, 0xE, 0xC, 0x6, 0x1, 0xB, 0xD, 0x9, 0x3, 0x8
        ],
        'E-D': [
            0xF, 0xC, 0x2, 0xA, 0x6, 0x4, 0x5, 0x0, 0x7, 0x9, 0xE, 0xD, 0x1, 0xB, 0x8, 0x3,
            0xB, 0x6, 0x3, 0x4, 0xC, 0xF, 0xE, 0x2, 0x7, 0xD, 0x8, 0x0, 0x5, 0xA, 0x9, 0x1,
            0x1, 0xC, 0xB, 0x0, 0xF, 0xE, 0x6, 0x5, 0xA, 0xD, 0x4, 0x8, 0x9, 0x3, 0x7, 0x2,
            0x1, 0x5, 0xE, 0xC, 0xA, 0x7, 0x0, 0xD, 0x6, 0x2, 0xB, 0x4, 0x9, 0x3, 0xF, 0x8,
            0x0, 0xC, 0x8, 0x9, 0xD, 0x2, 0xA, 0xB, 0x7, 0x3, 0x6, 0x5, 0x4, 0xE, 0xF, 0x1,
            0x8, 0x0, 0xF, 0x3, 0x2, 0x5, 0xE, 0xB, 0x1, 0xA, 0x4, 0x7, 0xC, 0x9, 0xD, 0x6,
            0x3, 0x0, 0x6, 0xF, 0x1, 0xE, 0x9, 0x2, 0xD, 0x8, 0xC, 0x4, 0xB, 0xA, 0x5, 0x7,
            0x1, 0xA, 0x6, 0x8, 0xF, 0xB, 0x0, 0x4, 0xC, 0x3, 0x5, 0x9, 0x7, 0xD, 0x2, 0xE
        ],
        'E-SC': [
            0x3, 0x6, 0x1, 0x0, 0x5, 0x7, 0xd, 0x9, 0x4, 0xb, 0x8, 0xc, 0xe, 0xf, 0x2, 0xa,
            0x7, 0x1, 0x5, 0x2, 0x8, 0xb, 0x9, 0xc, 0xd, 0x0, 0x3, 0xa, 0xf, 0xe, 0x4, 0x6,
            0xf, 0x1, 0x4, 0x6, 0xc, 0x8, 0x9, 0x2, 0xe, 0x3, 0x7, 0xa, 0xb, 0xd, 0x5, 0x0,
            0x3, 0x4, 0xf, 0xc, 0x5, 0x9, 0xe, 0x0, 0x6, 0x8, 0x7, 0xa, 0x1, 0xb, 0xd, 0x2,
            0x6, 0x9, 0x0, 0x7, 0xb, 0x8, 0x4, 0xc, 0x2, 0xe, 0xa, 0xf, 0x1, 0xd, 0x5, 0x3,
            0x6, 0x1, 0x2, 0xf, 0x0, 0xb, 0x9, 0xc, 0x7, 0xd, 0xa, 0x5, 0x8, 0x4, 0xe, 0x3,
            0x0, 0x2, 0xe, 0xc, 0x9, 0x1, 0x4, 0x7, 0x3, 0xf, 0x6, 0x8, 0xa, 0xd, 0xb, 0x5,
            0x5, 0x2, 0xb, 0x8, 0x4, 0xc, 0x7, 0x1, 0xa, 0x6, 0xe, 0x0, 0x9, 0x3, 0xd, 0xf
        ],
        'E-Z': [// This is default S-box in according to draft of new standard
            0xc, 0x4, 0x6, 0x2, 0xa, 0x5, 0xb, 0x9, 0xe, 0x8, 0xd, 0x7, 0x0, 0x3, 0xf, 0x1,
            0x6, 0x8, 0x2, 0x3, 0x9, 0xa, 0x5, 0xc, 0x1, 0xe, 0x4, 0x7, 0xb, 0xd, 0x0, 0xf,
            0xb, 0x3, 0x5, 0x8, 0x2, 0xf, 0xa, 0xd, 0xe, 0x1, 0x7, 0x4, 0xc, 0x9, 0x6, 0x0,
            0xc, 0x8, 0x2, 0x1, 0xd, 0x4, 0xf, 0x6, 0x7, 0x0, 0xa, 0x5, 0x3, 0xe, 0x9, 0xb,
            0x7, 0xf, 0x5, 0xa, 0x8, 0x1, 0x6, 0xd, 0x0, 0x9, 0x3, 0xe, 0xb, 0x4, 0x2, 0xc,
            0x5, 0xd, 0xf, 0x6, 0x9, 0x2, 0xc, 0xa, 0xb, 0x7, 0x8, 0x1, 0x4, 0x3, 0xe, 0x0,
            0x8, 0xe, 0x2, 0x5, 0x6, 0x9, 0x1, 0xc, 0xf, 0x4, 0xb, 0x0, 0xd, 0xa, 0x3, 0x7,
            0x1, 0x7, 0xe, 0xd, 0x0, 0x5, 0x8, 0x3, 0x4, 0xf, 0xa, 0x6, 0x9, 0xc, 0xb, 0x2
        ],
        //S-box for digest
        'D-TEST': [
            0x4, 0xA, 0x9, 0x2, 0xD, 0x8, 0x0, 0xE, 0x6, 0xB, 0x1, 0xC, 0x7, 0xF, 0x5, 0x3,
            0xE, 0xB, 0x4, 0xC, 0x6, 0xD, 0xF, 0xA, 0x2, 0x3, 0x8, 0x1, 0x0, 0x7, 0x5, 0x9,
            0x5, 0x8, 0x1, 0xD, 0xA, 0x3, 0x4, 0x2, 0xE, 0xF, 0xC, 0x7, 0x6, 0x0, 0x9, 0xB,
            0x7, 0xD, 0xA, 0x1, 0x0, 0x8, 0x9, 0xF, 0xE, 0x4, 0x6, 0xC, 0xB, 0x2, 0x5, 0x3,
            0x6, 0xC, 0x7, 0x1, 0x5, 0xF, 0xD, 0x8, 0x4, 0xA, 0x9, 0xE, 0x0, 0x3, 0xB, 0x2,
            0x4, 0xB, 0xA, 0x0, 0x7, 0x2, 0x1, 0xD, 0x3, 0x6, 0x8, 0x5, 0x9, 0xC, 0xF, 0xE,
            0xD, 0xB, 0x4, 0x1, 0x3, 0xF, 0x5, 0x9, 0x0, 0xA, 0xE, 0x7, 0x6, 0x8, 0x2, 0xC,
            0x1, 0xF, 0xD, 0x0, 0x5, 0x7, 0xA, 0x4, 0x9, 0x2, 0x3, 0xE, 0x6, 0xB, 0x8, 0xC
        ],
        'D-A': [
            0xA, 0x4, 0x5, 0x6, 0x8, 0x1, 0x3, 0x7, 0xD, 0xC, 0xE, 0x0, 0x9, 0x2, 0xB, 0xF,
            0x5, 0xF, 0x4, 0x0, 0x2, 0xD, 0xB, 0x9, 0x1, 0x7, 0x6, 0x3, 0xC, 0xE, 0xA, 0x8,
            0x7, 0xF, 0xC, 0xE, 0x9, 0x4, 0x1, 0x0, 0x3, 0xB, 0x5, 0x2, 0x6, 0xA, 0x8, 0xD,
            0x4, 0xA, 0x7, 0xC, 0x0, 0xF, 0x2, 0x8, 0xE, 0x1, 0x6, 0x5, 0xD, 0xB, 0x9, 0x3,
            0x7, 0x6, 0x4, 0xB, 0x9, 0xC, 0x2, 0xA, 0x1, 0x8, 0x0, 0xE, 0xF, 0xD, 0x3, 0x5,
            0x7, 0x6, 0x2, 0x4, 0xD, 0x9, 0xF, 0x0, 0xA, 0x1, 0x5, 0xB, 0x8, 0xE, 0xC, 0x3,
            0xD, 0xE, 0x4, 0x1, 0x7, 0x0, 0x5, 0xA, 0x3, 0xC, 0x8, 0xF, 0x6, 0x2, 0x9, 0xB,
            0x1, 0x3, 0xA, 0x9, 0x5, 0xB, 0x4, 0xF, 0x8, 0x6, 0x7, 0xE, 0xD, 0x0, 0x2, 0xC
        ],
        'D-SC': [
            0xb, 0xd, 0x7, 0x0, 0x5, 0x4, 0x1, 0xf, 0x9, 0xe, 0x6, 0xa, 0x3, 0xc, 0x8, 0x2,
            0x1, 0x2, 0x7, 0x9, 0xd, 0xb, 0xf, 0x8, 0xe, 0xc, 0x4, 0x0, 0x5, 0x6, 0xa, 0x3,
            0x5, 0x1, 0xd, 0x3, 0xf, 0x6, 0xc, 0x7, 0x9, 0x8, 0xb, 0x2, 0x4, 0xe, 0x0, 0xa,
            0xd, 0x1, 0xb, 0x4, 0x9, 0xc, 0xe, 0x0, 0x7, 0x5, 0x8, 0xf, 0x6, 0x2, 0xa, 0x3,
            0x2, 0xd, 0xa, 0xf, 0x9, 0xb, 0x3, 0x7, 0x8, 0xc, 0x5, 0xe, 0x6, 0x0, 0x1, 0x4,
            0x0, 0x4, 0x6, 0xc, 0x5, 0x3, 0x8, 0xd, 0xa, 0xb, 0xf, 0x2, 0x1, 0x9, 0x7, 0xe,
            0x1, 0x3, 0xc, 0x8, 0xa, 0x6, 0xb, 0x0, 0x2, 0xe, 0x7, 0x9, 0xf, 0x4, 0x5, 0xd,
            0xa, 0xb, 0x6, 0x0, 0x1, 0x3, 0x4, 0x7, 0xe, 0xd, 0x5, 0xf, 0x8, 0x2, 0x9, 0xc
        ]
    };

    var C = new Uint8Array([
        0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23,
        0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4,
        0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12,
        0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B
    ]);

    function signed(x) {
        return x >= 0x80000000 ? x - 0x100000000 : x;
    }

    function unsigned(x) {
        return x < 0 ? x + 0x100000000 : x;
    }

    // Set random values into Uint8Arry
    // Random generator
    function randomSeed(e) {
        var randomSource = new GostRandom();
        if (randomSource.getRandomValues)
            randomSource.getRandomValues(e);
        else
            throw new NotSupportedError('Random generator not found');
    }

    // Get buffer
    function buffer(d) {
        if (d instanceof CryptoOperationData)
            return d;
        else if (d && d.buffer && d.buffer instanceof CryptoOperationData)
            return d.byteOffset === 0 && d.byteLength === d.buffer.byteLength ?
                    d.buffer : new Uint8Array(new Uint8Array(d, d.byteOffset, d.byteLength)).buffer;
        else
            throw new DataError('CryptoOperationData required');
    }

    // Get byte array
    function byteArray(d) {
        return new Uint8Array(buffer(d));
    }

    // Clone byte array
    function cloneArray(d) {
        return new Uint8Array(byteArray(d));
    }


    // Get int32 array
    function intArray(d) {
        return new Int32Array(buffer(d));
    }

    // Swap bytes for version 2015
    function swap32(b) {
        return ((b & 0xff) << 24)
                | ((b & 0xff00) << 8)
                | ((b >> 8) & 0xff00)
                | ((b >> 24) & 0xff);
    }



    /*
     * Initial parameters and common algortithms of GOST R 34.12-15 
     * Algorithm "Kuznechik" 128bit
     * 
     */

    // Default initial vector
    var defaultIV128 = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);

    // Mult table for R function
    var multTable = (function () {

        // Multiply two numbers in the GF(2^8) finite field defined 
        // by the polynomial x^8 + x^7 + x^6 + x + 1 = 0 */
        function gmul(a, b) {
            var p = 0, counter, carry;
            for (counter = 0; counter < 8; counter++) {
                if (b & 1)
                    p ^= a;
                carry = a & 0x80; // detect if x^8 term is about to be generated 
                a = (a << 1) & 0xff;
                if (carry)
                    a ^= 0xc3; // replace x^8 with x^7 + x^6 + x + 1 
                b >>= 1;
            }
            return p & 0xff;
        }

        // It is required only this values for R function
        //       0   1   2    3    4    5    6    7
        var x = [1, 16, 32, 133, 148, 192, 194, 251];
        var m = [];
        for (var i = 0; i < 8; i++) {
            m[i] = [];
            for (var j = 0; j < 256; j++)
                m[i][j] = gmul(x[i], j);
        }
        return m;
    })();

    // 148, 32, 133, 16, 194, 192, 1, 251, 1, 192, 194, 16, 133, 32, 148, 1
    var kB = [4, 2, 3, 1, 6, 5, 0, 7, 0, 5, 6, 1, 3, 2, 4, 0];

    // R - function
    function funcR(d) {
        var sum = 0;
        for (var i = 0; i < 16; i++)
            sum ^= multTable[kB[i]][d[i]];

        for (var i = 16; i > 0; --i)
            d[i] = d[i - 1];
        d[0] = sum;
    }

    function funcReverseR(d) {
        var tmp = d[0];
        for (var i = 0; i < 15; i++)
            d[i] = d[i + 1];
        d[15] = tmp;

        var sum = 0;
        for (i = 0; i < 16; i++)
            sum ^= multTable[kB[i]][d[i]];
        d[15] = sum;
    }

    // Nonlinear transformation
    var kPi = [
        252, 238, 221, 17, 207, 110, 49, 22, 251, 196, 250, 218, 35, 197, 4, 77,
        233, 119, 240, 219, 147, 46, 153, 186, 23, 54, 241, 187, 20, 205, 95, 193,
        249, 24, 101, 90, 226, 92, 239, 33, 129, 28, 60, 66, 139, 1, 142, 79,
        5, 132, 2, 174, 227, 106, 143, 160, 6, 11, 237, 152, 127, 212, 211, 31,
        235, 52, 44, 81, 234, 200, 72, 171, 242, 42, 104, 162, 253, 58, 206, 204,
        181, 112, 14, 86, 8, 12, 118, 18, 191, 114, 19, 71, 156, 183, 93, 135,
        21, 161, 150, 41, 16, 123, 154, 199, 243, 145, 120, 111, 157, 158, 178, 177,
        50, 117, 25, 61, 255, 53, 138, 126, 109, 84, 198, 128, 195, 189, 13, 87,
        223, 245, 36, 169, 62, 168, 67, 201, 215, 121, 214, 246, 124, 34, 185, 3,
        224, 15, 236, 222, 122, 148, 176, 188, 220, 232, 40, 80, 78, 51, 10, 74,
        167, 151, 96, 115, 30, 0, 98, 68, 26, 184, 56, 130, 100, 159, 38, 65,
        173, 69, 70, 146, 39, 94, 85, 47, 140, 163, 165, 125, 105, 213, 149, 59,
        7, 88, 179, 64, 134, 172, 29, 247, 48, 55, 107, 228, 136, 217, 231, 137,
        225, 27, 131, 73, 76, 63, 248, 254, 141, 83, 170, 144, 202, 216, 133, 97,
        32, 113, 103, 164, 45, 43, 9, 91, 203, 155, 37, 208, 190, 229, 108, 82,
        89, 166, 116, 210, 230, 244, 180, 192, 209, 102, 175, 194, 57, 75, 99, 182
    ];

    var kReversePi = (function () {
        var m = [];
        for (var i = 0, n = kPi.length; i < n; i++)
            m[kPi[i]] = i;
        return m;
    })();

    function funcS(d) {
        for (var i = 0; i < 16; ++i)
            d[i] = kPi[d[i]];
    }

    function funcReverseS(d) {
        for (var i = 0; i < 16; ++i)
            d[i] = kReversePi[d[i]];
    }

    function funcX(a, b) {
        for (var i = 0; i < 16; ++i)
            a[i] ^= b[i];
    }

    function funcL(d) {
        for (var i = 0; i < 16; ++i)
            funcR(d);
    }

    function funcReverseL(d) {
        for (var i = 0; i < 16; ++i)
            funcReverseR(d);
    }

    function funcLSX(a, b) {
        funcX(a, b);
        funcS(a);
        funcL(a);
    }

    function funcReverseLSX(a, b) {
        funcX(a, b);
        funcReverseL(a);
        funcReverseS(a);
    }

    function funcF(inputKey, inputKeySecond, iterationConst) {
        var tmp = new Uint8Array(inputKey);
        funcLSX(inputKey, iterationConst);
        funcX(inputKey, inputKeySecond);
        inputKeySecond.set(tmp);
    }

    function funcC(number, d) {
        for (var i = 0; i < 15; i++)
            d[i] = 0;
        d[15] = number;
        funcL(d);
    }



    /**
     * Key schedule for GOST R 34.12-15 128bits
     * 
     * @memberOf GostCipher
     * @private
     * @instance
     * @method keySchedule
     * @param {type} k
     * @returns {Uint8Array}
     */
    function keySchedule128(k)
    {
        var keys = new Uint8Array(160), c = new Uint8Array(16);
        keys.set(byteArray(k));
        for (var j = 0; j < 4; j++) {
            var j0 = 32 * j, j1 = 32 * (j + 1);
            keys.set(new Uint8Array(keys.buffer, j0, 32), j1);
            for (var i = 1; i < 9; i++) {
                funcC(j * 8 + i, c);
                funcF(new Uint8Array(keys.buffer, j1, 16),
                        new Uint8Array(keys.buffer, j1 + 16, 16), c);
            }
        }
        return keys;
    }

    /**
     * GOST R 34.12-15 128 bits encrypt/decrypt process 
     * 
     * @memberOf GostCipher
     * @private
     * @instance
     * @method round
     * @param {Uint8Array} k Scheduled key
     * @param {Uint8Array} d Data
     * @param {number} ofs Offsec
     * @param {number} e true - decrypt
     */
    function process128(k, d, ofs, e)
    {
        ofs = ofs || d.byteOffset;
        var r = new Uint8Array(d.buffer, ofs, 16);
        if (e) {
            for (var i = 0; i < 9; i++)
                funcReverseLSX(r, new Uint8Array(k.buffer, (9 - i) * 16, 16));

            funcX(r, new Uint8Array(k.buffer, 0, 16));
        } else {
            for (var i = 0; i < 9; i++)
                funcLSX(r, new Uint8Array(k.buffer, 16 * i, 16));

            funcX(r, new Uint8Array(k.buffer, 16 * 9, 16));
        }
    }

    /**
     * One GOST encryption round
     * 
     * @memberOf GostCipher
     * @private
     * @instance
     * @method round
     * @param {Int8Array} S sBox
     * @param {Int32Array} m 2x32 bits cipher block 
     * @param {Int32Array} k 32 bits key[i] 
     */
    function round(S, m, k)
    {
        var cm = (m[0] + k) & 0xffffffff;

        var om = S[  0 + ((cm >> (0 * 4)) & 0xF)] << (0 * 4);
        om |= S[ 16 + ((cm >> (1 * 4)) & 0xF)] << (1 * 4);
        om |= S[ 32 + ((cm >> (2 * 4)) & 0xF)] << (2 * 4);
        om |= S[ 48 + ((cm >> (3 * 4)) & 0xF)] << (3 * 4);
        om |= S[ 64 + ((cm >> (4 * 4)) & 0xF)] << (4 * 4);
        om |= S[ 80 + ((cm >> (5 * 4)) & 0xF)] << (5 * 4);
        om |= S[ 96 + ((cm >> (6 * 4)) & 0xF)] << (6 * 4);
        om |= S[112 + ((cm >> (7 * 4)) & 0xF)] << (7 * 4);
        cm = om << 11 | om >>> (32 - 11);

        cm ^= m[1];
        m[1] = m[0];
        m[0] = cm;

    }

    /**
     * Process encrypt/decrypt block with key K using GOST 28147-89
     * 
     * @memberOf GostCipher
     * @private
     * @instance
     * @method process
     * @param k {Int32Array} 8x32 bits key 
     * @param d {Int32Array} 8x8 bits cipher block 
     * @param ofs {number} offset
     */
    function process89(k, d, ofs)
    {
        ofs = ofs || d.byteOffset;
        var s = this.sBox,
                m = new Int32Array(d.buffer, ofs, 2);

        for (var i = 0; i < 32; i++)
            round(s, m, k[i]);

        var r = m[0];
        m[0] = m[1];
        m[1] = r;
    }

    /**
     * Process encrypt/decrypt block with key K using GOST R 34.12-15 64bit block
     * 
     * @memberOf GostCipher
     * @private
     * @instance
     * @method process
     * @param k {Int32Array} 8x32 bits key 
     * @param d {Int32Array} 8x8 bits cipher block 
     * @param ofs {number} offset
     */
    function process15(k, d, ofs)
    {
        ofs = ofs || d.byteOffset;
        var s = this.sBox,
                m = new Int32Array(d.buffer, ofs, 2),
                r = swap32(m[0]);
        m[0] = swap32(m[1]);
        m[1] = r;

        for (var i = 0; i < 32; i++)
            round(s, m, k[i]);

        m[0] = swap32(m[0]);
        m[1] = swap32(m[1]);
    }

    /**
     * Key keySchedule algorithm for GOST 28147-89 64bit cipher
     * 
     * @memberOf GostCipher
     * @private
     * @instance
     * @method process
     * @param k {Uint8Array} 8 bit key array
     * @param e {boolean}  true - decrypt
     * @returns {Int32Array} keyScheduled 32-bit key
     */
    function keySchedule89(k, e)
    {
        var sch = new Int32Array(32),
                key = new Int32Array(buffer(k));

        for (var i = 0; i < 8; i++)
            sch[i] = key[i];

        if (e) {
            for (var i = 0; i < 8; i++)
                sch[i + 8] = sch[7 - i];

            for (var i = 0; i < 8; i++)
                sch[i + 16] = sch[7 - i];
        } else {
            for (var i = 0; i < 8; i++)
                sch[i + 8] = sch[i];

            for (var i = 0; i < 8; i++)
                sch[i + 16] = sch[i];
        }

        for (var i = 0; i < 8; i++)
            sch[i + 24] = sch[7 - i];

        return sch;
    }

    /**
     * Key keySchedule algorithm for GOST R 34.12-15 64bit cipher
     * 
     * @memberOf GostCipher
     * @private
     * @instance
     * @method process
     * @param k {Uint8Array} 8 bit key array
     * @param e {boolean}  true - decrypt
     * @returns {Int32Array} keyScheduled 32-bit key
     */
    function keySchedule15(k, e)
    {
        var sch = new Int32Array(32),
                key = new Int32Array(buffer(k));

        for (var i = 0; i < 8; i++)
            sch[i] = swap32(key[i]);

        if (e) {
            for (var i = 0; i < 8; i++)
                sch[i + 8] = sch[7 - i];

            for (var i = 0; i < 8; i++)
                sch[i + 16] = sch[7 - i];
        } else {
            for (var i = 0; i < 8; i++)
                sch[i + 8] = sch[i];

            for (var i = 0; i < 8; i++)
                sch[i + 16] = sch[i];
        }

        for (var i = 0; i < 8; i++)
            sch[i + 24] = sch[7 - i];

        return sch;
    }

    /**
     * Key schedule for RC2
     * 
     * https://tools.ietf.org/html/rfc2268
     * 
     * @memberOf GostCipher
     * @private
     * @instance
     * @method keySchedule
     * @param {Uint8Array} k
     * @returns {Uint16Array}
     */
    var keyScheduleRC2 = (function ()
    {
        // an array of "random" bytes based on the digits of PI = 3.14159...
        var PITABLE = new Uint8Array([
            0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
            0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
            0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
            0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
            0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
            0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
            0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
            0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
            0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
            0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
            0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
            0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
            0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
            0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
            0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
            0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad
        ]);

        return function (k)
        {
            var key = new Uint8Array(buffer(k)),
                    T = Math.min(key.length, 128),
                    T1 = this.effectiveLength,
                    T8 = Math.floor((T1 + 7) / 8),
                    TM = 0xff % Math.pow(2, 8 + T1 - 8 * T8);

            var L = new Uint8Array(128), K = new Uint16Array(L.buffer);
            for (var i = 0; i < T; i++)
                L[i] = key[i];
            for (var i = T; i < 128; i++)
                L[i] = PITABLE[(L[i - 1] + L[i - T]) % 256];
            L[128 - T8] = PITABLE[L[128 - T8] & TM];
            for (var i = 127 - T8; i >= 0; --i)
                L[i] = PITABLE[L[i + 1] ^ L[i + T8]];
            return K;
        };
    }
    )();

    /**
     * RC2 encrypt/decrypt process 
     * 
     * https://tools.ietf.org/html/rfc2268
     * 
     * @memberOf GostCipher
     * @private
     * @instance
     * @method round
     * @param {CryptoOperationData} k Scheduled key
     * @param {CryptoOperationData} d Data
     * @param {number} ofs Offsec
     * @param {number} e true - decrypt
     */
    var processRC2 = (function ()
    {
        var K, j, R = new Uint16Array(4),
                s = new Uint16Array([1, 2, 3, 5]), reverse;

        function rol(R, s) {
            return (R << s | R >>> (16 - s)) & 0xffff;
        }

        function ror(R, s) {
            return (R >>> s | R << (16 - s)) & 0xffff;
        }

        function mix(i) {
            if (reverse) {
                R[i] = ror(R[i], s[i]);
                R[i] = R[i] - K[j] - (R[(i + 3) % 4] & R[(i + 2) % 4]) - ((~R[(i + 3) % 4]) & R[(i + 1) % 4]);
                j = j - 1;
            } else {
                R[i] = R[i] + K[j] + (R[(i + 3) % 4] & R[(i + 2) % 4]) + ((~R[(i + 3) % 4]) & R[(i + 1) % 4]);
                j = j + 1;
                R[i] = rol(R[i], s[i]);
            }
        }

        function mash(i) {
            if (reverse) {
                R[i] = R[i] - K[R[(i + 3) % 4] & 63];
            } else {
                R[i] = R[i] + K[R[(i + 3) % 4] & 63];
            }
        }

        function perform(method, count) {
            count = count || 1;
            for (var j = 0; j < count; j++) {
                if (reverse) {
                    for (var i = 3; i >= 0; --i)
                        method(i);
                } else {
                    for (var i = 0; i < 4; i++)
                        method(i);
                }
            }
        }

        return function (k, d, ofs, e) {
            reverse = e;
            //  1. Initialize words R[0], ..., R[3] to contain the 64-bit
            //     ciphertext value.
            R = new Uint16Array(d.buffer, ofs || d.byteOffset, 4);
            //  2. Expand the key, so that words K[0], ..., K[63] become
            //     defined.
            K = k;
            //  3. Initialize j to zero (enc) j to 63 (dec).
            j = e ? 63 : 0;
            //  4. Perform five mixing rounds.
            perform(mix, 5);
            //  5. Perform one mashing round.
            perform(mash);
            //  6. Perform six mixing rounds.
            perform(mix, 6);
            //  7. Perform one mashing round.
            perform(mash);
            //  8. Perform five mixing rounds.
            perform(mix, 5);
        };
    }
    )();

    /**
     * Algorithm name GOST 28147-ECB<br><br>
     * 
     * encryptECB (K, D) is D, encrypted with key k using GOST 28147/GOST R 34.13 in 
     * "prostaya zamena" (Electronic Codebook, ECB) mode. 
     * @memberOf GostCipher
     * @method encrypt
     * @instance
     * @param k {CryptoOperationData} 8x32 bit key 
     * @param d {CryptoOperationData} 8 bits message
     * @return {CryptoOperationData} result
     */
    function encryptECB(k, d)
    {
        var p = this.pad(byteArray(d)),
                n = this.blockSize,
                b = p.byteLength / n,
                key = this.keySchedule(k);

        for (var i = 0; i < b; i++)
            this.process(key, p, n * i);

        return p.buffer;
    }

    /**
     * Algorithm name GOST 28147-ECB<br><br>
     * 
     * decryptECB (K, D) is D, decrypted with key K using GOST 28147/GOST R 34.13 in   
     * "prostaya zamena"  (Electronic Codebook, ECB) mode.
     * 
     * @memberOf GostCipher
     * @method decrypt
     * @instance
     * @param k {CryptoOperationData} 8x32 bits key 
     * @param d {CryptoOperationData} 8 bits message
     * @return {CryptoOperationData} result
     */
    function decryptECB(k, d)
    {
        var p = cloneArray(d),
                n = this.blockSize,
                b = p.byteLength / n,
                key = this.keySchedule(k, 1);

        for (var i = 0; i < b; i++)
            this.process(key, p, n * i, 1);

        return this.unpad(p).buffer;
    }

    /**
     * Algorithm name GOST 28147-CFB<br><br>
     * 
     * encryptCFB (IV, K, D) is D, encrypted with key K using GOST 28147/GOST R 34.13   
     * in "gammirovanie s obratnoj svyaziyu" (Cipher Feedback, CFB) mode, and IV is   
     * used as the initialization vector.
     * 
     * @memberOf GostCipher
     * @method encrypt
     * @instance
     * @param {CryptoOperationData} k 8x32 bits key 
     * @param {CryptoOperationData} d 8 bits array with data 
     * @param {CryptoOperationData} iv initial vector
     * @return {CryptoOperationData} result
     */
    function encryptCFB(k, d, iv)
    {
        var s = new Uint8Array(iv || this.iv),
                c = cloneArray(d),
                m = s.length,
                t = new Uint8Array(m),
                b = this.shiftBits >> 3,
                cb = c.length, r = cb % b, q = (cb - r) / b,
                key = this.keySchedule(k);

        for (var i = 0; i < q; i++) {

            for (var j = 0; j < m; j++)
                t[j] = s[j];

            this.process(key, s);

            for (var j = 0; j < b; j++)
                c[i * b + j] ^= s[j];

            for (var j = 0; j < m - b; j++)
                s[j] = t[b + j];

            for (var j = 0; j < b; j++)
                s[m - b + j] = c[i * b + j];

            k = this.keyMeshing(k, s, i, key);
        }

        if (r > 0) {
            this.process(key, s);

            for (var i = 0; i < r; i++)
                c[q * b + i] ^= s[i];
        }
        return c.buffer;
    }

    /**
     * Algorithm name GOST 28147-CFB<br><br>
     * 
     * decryptCFB (IV, K, D) is D, decrypted with key K using GOST 28147/GOST R 34.13   
     * in "gammirovanie s obratnoj svyaziyu po shifrotekstu" (Cipher Feedback, CFB) mode, and IV is   
     * used as the initialization vector.
     * 
     * @memberOf GostCipher
     * @method decrypt
     * @instance
     * @param {CryptoOperationData} k 8x32 bits key 
     * @param {CryptoOperationData} d 8 bits array with data 
     * @param {CryptoOperationData} iv initial vector
     * @return {CryptoOperationData} result
     */
    function decryptCFB(k, d, iv)
    {
        var s = new Uint8Array(iv || this.iv),
                c = cloneArray(d),
                m = s.length,
                t = new Uint8Array(m),
                b = this.shiftBits >> 3,
                cb = c.length, r = cb % b, q = (cb - r) / b,
                key = this.keySchedule(k);

        for (var i = 0; i < q; i++) {

            for (var j = 0; j < m; j++)
                t[j] = s[j];

            this.process(key, s);

            for (var j = 0; j < b; j++) {
                t[j] = c[i * b + j];
                c[i * b + j] ^= s[j];
            }

            for (var j = 0; j < m - b; j++)
                s[j] = t[b + j];

            for (var j = 0; j < b; j++)
                s[m - b + j] = t[j];

            k = this.keyMeshing(k, s, i, key);
        }

        if (r > 0) {
            this.process(key, s);

            for (var i = 0; i < r; i++)
                c[q * b + i] ^= s[i];
        }
        return c.buffer;
    }

    /**
     * Algorithm name GOST 28147-OFB<br><br>
     * 
     * encryptOFB/decryptOFB (IV, K, D) is D, encrypted with key K using GOST 28147/GOST R 34.13   
     * in "gammirovanie s obratnoj svyaziyu po vyhodu" (Output Feedback, OFB) mode, and IV is   
     * used as the initialization vector.
     * 
     * @memberOf GostCipher
     * @method encrypt
     * @instance
     * @param {CryptoOperationData} k 8x32 bits key 
     * @param {CryptoOperationData} d 8 bits array with data 
     * @param {CryptoOperationData} iv 8x8 optional bits initial vector
     * @return {CryptoOperationData} result
     */
    /**
     * Algorithm name GOST 28147-OFB<br><br>
     * 
     * encryptOFB/decryptOFB (IV, K, D) is D, encrypted with key K using GOST 28147/GOST R 34.13   
     * in "gammirovanie s obratnoj svyaziyu po vyhodu" (Output Feedback, OFB) mode, and IV is   
     * used as the initialization vector.
     * 
     * @memberOf GostCipher
     * @method decrypt
     * @instance
     * @param {CryptoOperationData} k 8x32 bits key 
     * @param {CryptoOperationData} d 8 bits array with data 
     * @param {CryptoOperationData} iv initial vector
     * @return {CryptoOperationData} result
     */
    function processOFB(k, d, iv)
    {
        var s = new Uint8Array(iv || this.iv),
                c = cloneArray(d),
                m = s.length,
                t = new Uint8Array(m),
                b = this.shiftBits >> 3,
                p = new Uint8Array(b),
                cb = c.length, r = cb % b, q = (cb - r) / b,
                key = this.keySchedule(k);

        for (var i = 0; i < q; i++) {

            for (var j = 0; j < m; j++)
                t[j] = s[j];

            this.process(key, s);

            for (var j = 0; j < b; j++)
                p[j] = s[j];

            for (var j = 0; j < b; j++)
                c[i * b + j] ^= s[j];

            for (var j = 0; j < m - b; j++)
                s[j] = t[b + j];

            for (var j = 0; j < b; j++)
                s[m - b + j] = p[j];

            k = this.keyMeshing(k, s, i, key);
        }

        if (r > 0) {
            this.process(key, s);

            for (var i = 0; i < r; i++)
                c[q * b + i] ^= s[i];
        }
        return c.buffer;
    }

    /**
     * Algorithm name GOST 28147-CTR<br><br>
     * 
     * encryptCTR/decryptCTR (IV, K, D) is D, encrypted with key K using GOST 28147/GOST R 34.13   
     * in "gammirovanie" (Counter Mode-CTR) mode, and IV is used as the   
     * initialization vector.
     * @memberOf GostCipher
     * @method encrypt
     * @instance
     * @param {CryptoOperationData} k 8x32 bits key 
     * @param {CryptoOperationData} d 8 bits array with data 
     * @param {CryptoOperationData} iv 8x8 optional bits initial vector
     * @return {CryptoOperationData} result
     */
    /**
     * Algorithm name GOST 28147-CTR<br><br>
     * 
     * encryptCTR/decryptCTR (IV, K, D) is D, encrypted with key K using GOST 28147/GOST R 34.13   
     * in "gammirovanie" (Counter Mode-CTR) mode, and IV is used as the   
     * initialization vector.
     * @memberOf GostCipher
     * @method decrypt
     * @instance
     * @param {CryptoOperationData} k 8x32 bits key 
     * @param {CryptoOperationData} d 8 bits array with data 
     * @param {CryptoOperationData} iv initial vector
     * @return {CryptoOperationData} result
     */
    function processCTR89(k, d, iv)
    {
        var s = new Uint8Array(iv || this.iv),
                c = cloneArray(d),
                b = this.blockSize,
                t = new Int8Array(b),
                cb = c.length, r = cb % b, q = (cb - r) / b,
                key = this.keySchedule(k),
                syn = new Int32Array(s.buffer);

        this.process(key, s);

        for (var i = 0; i < q; i++) {
            syn[0] = (syn[0] + 0x1010101) & 0xffffffff;
            // syn[1] = signed(unsigned((syn[1] + 0x1010104) & 0xffffffff) % 0xffffffff);
            var tmp = unsigned(syn[1]) + 0x1010104; // Special thanks to Ilya Matveychikov
            syn[1] = signed(tmp < 0x100000000 ? tmp : tmp - 0xffffffff);

            for (var j = 0; j < b; j++)
                t[j] = s[j];

            this.process(key, syn);

            for (var j = 0; j < b; j++)
                c[i * b + j] ^= s[j];

            for (var j = 0; j < b; j++)
                s[j] = t[j];

            k = this.keyMeshing(k, s, i, key);
        }
        if (r > 0) {
            syn[0] = (syn[0] + 0x1010101) & 0xffffffff;
            // syn[1] = signed(unsigned((syn[1] + 0x1010104) & 0xffffffff) % 0xffffffff);
            var tmp = unsigned(syn[1]) + 0x1010104; // Special thanks to Ilya Matveychikov
            syn[1] = signed(tmp < 0x100000000 ? tmp : tmp - 0xffffffff);

            this.process(key, syn);

            for (var i = 0; i < r; i++)
                c[q * b + i] ^= s[i];
        }
        return c.buffer;
    }

    function processCTR15(k, d, iv)
    {
        var c = cloneArray(d),
                n = this.blockSize,
                b = this.shiftBits >> 3,
                cb = c.length, r = cb % b, q = (cb - r) / b,
                s = new Uint8Array(n),
                t = new Int32Array(n),
                key = this.keySchedule(k);

        s.set(iv || this.iv);
        for (var i = 0; i < q; i++) {

            for (var j = 0; j < n; j++)
                t[j] = s[j];

            this.process(key, s);

            for (var j = 0; j < b; j++)
                c[b * i + j] ^= s[j];

            for (var j = 0; j < n; j++)
                s[j] = t[j];

            for (var j = n - 1; i >= 0; --i) {
                if (s[j] > 0xfe) {
                    s[j] -= 0xfe;
                } else {
                    s[j]++;
                    break;
                }
            }
        }

        if (r > 0) {
            this.process(key, s);
            for (var j = 0; j < r; j++)
                c[b * q + j] ^= s[j];
        }

        return c.buffer;
    }

    /**
     * Algorithm name GOST 28147-CBC<br><br>
     * 
     * encryptCBC (IV, K, D) is D, encrypted with key K using GOST 28147/GOST R 34.13   
     * in "Prostaya zamena s zatsepleniem" (Cipher-Block-Chaining, CBC) mode and IV is used as the initialization 
     * vector.
     * 
     * @memberOf GostCipher
     * @method encrypt
     * @instance
     * @param {CryptoOperationData} k 8x32 bits key 
     * @param {CryptoOperationData} d 8 bits array with data 
     * @param {CryptoOperationData} iv initial vector
     * @return {CryptoOperationData} result
     */
    function encryptCBC(k, d, iv)
    {
        var s = new Uint8Array(iv || this.iv),
                n = this.blockSize,
                m = s.length,
                c = this.pad(byteArray(d)),
                key = this.keySchedule(k);

        for (var i = 0, b = c.length / n; i < b; i++) {

            for (var j = 0; j < n; j++)
                s[j] ^= c[i * n + j];

            this.process(key, s);

            for (var j = 0; j < n; j++)
                c[i * n + j] = s[j];

            if (m !== n) {
                for (var j = 0; j < m - n; j++)
                    s[j] = s[n + j];

                for (var j = 0; j < n; j++)
                    s[j + m - n] = c[i * n + j];
            }

            k = this.keyMeshing(k, s, i, key);
        }

        return c.buffer;
    }

    /**
     * Algorithm name GOST 28147-CBC<br><br>
     * 
     * decryptCBC (IV, K, D) is D, decrypted with key K using GOST 28147/GOST R 34.13   
     * in "Prostaya zamena s zatsepleniem" (Cipher-Block-Chaining, CBC) mode and IV is used as the initialization 
     * vector.
     * 
     * @memberOf GostCipher
     * @method decrypt
     * @instance
     * @param {CryptoOperationData} k 8x32 bits key 
     * @param {CryptoOperationData} d 8 bits array with data 
     * @param {CryptoOperationData} iv initial vector
     * @return {CryptoOperationData} result
     */
    function decryptCBC(k, d, iv)
    {
        var s = new Uint8Array(iv || this.iv),
                n = this.blockSize,
                m = s.length,
                c = cloneArray(d),
                next = new Uint8Array(n),
                key = this.keySchedule(k, 1);

        for (var i = 0, b = c.length / n; i < b; i++) {

            for (var j = 0; j < n; j++)
                next[j] = c[i * n + j];

            this.process(key, c, i * n, 1);

            for (var j = 0; j < n; j++)
                c[i * n + j] ^= s[j];

            if (m !== n) {
                for (var j = 0; j < m - n; j++)
                    s[j] = s[n + j];
            }

            for (var j = 0; j < n; j++)
                s[j + m - n] = next[j];

            k = this.keyMeshing(k, s, i, key, 1);
        }

        return this.unpad(c).buffer;
    }

    /**
     * The generateKey method returns a new generated key.
     * 
     * @memberOf GostCipher
     * @method generateKey
     * @instance
     * @return {CryptoOperationData} result
     */

    function generateKey()
    {
        // Simple generate 256 bit random seed
        var k = new Uint8Array(this.keySize);
        randomSeed(k);
        return k.buffer;
    }


    /**
     * makeIMIT (K, D) is the 32-bit result of the GOST 28147/GOST R 34.13 in   
     * "imitovstavka" (MAC) mode, used with D as plaintext, K as key and IV   
     * as initialization vector.  Note that the standard specifies its use   
     * in this mode only with an initialization vector of zero.
     * 
     * @memberOf GostCipher
     * @method processMAC
     * @private
     * @instance
     * @param {Int32Array} key 8x32 bits key 
     * @param {Int32Array} s 8x8 sum array
     * @param {Uint8Array} d 8 bits array with data 
     * @return {Uint8Array} result
     */
    function processMAC89(key, s, d)
    {
        var c = zeroPad.call(this, byteArray(d)),
                n = this.blockSize,
                q = c.length / n,
                sBox = this.sBox,
                sum = new Int32Array(s.buffer);

        for (var i = 0; i < q; i++) {

            for (var j = 0; j < n; j++)
                s[j] ^= c[i * n + j];

            for (var j = 0; j < 16; j++) // 1-16 steps
                round(sBox, sum, key[j]);
        }
    }

    function processKeyMAC15(s)
    {
        var t = 0, n = s.length;
        for (var i = n - 1; i >= 0; --i) {
            var t1 = s[i] >>> 7;
            s[i] = (s[i] << 1) & 0xff | t;
            t = t1;
        }
        if (t !== 0) {
            if (n === 16)
                s[15] ^= 0x87;
            else
                s[7] ^= 0x1b;
        }
    }

    function processMAC15(key, s, d)
    {
        var n = this.blockSize,
                sBox = this.sBox, c = byteArray(d),
                r = new Uint8Array(n);
        // R
        this.process(key, r);
        // K1
        processKeyMAC15(r);
        if (d.byteLength % n !== 0) {
            c = bitPad.call(this, byteArray(d));
            // K2
            processKeyMAC15(r);
        }

        for (var i = 0, q = c.length / n; i < q; i++) {

            for (var j = 0; j < n; j++)
                s[j] ^= c[i * n + j];

            if (i === q - 1) {// Last block
                for (var j = 0; j < n; j++)
                    s[j] ^= r[j];
            }

            this.process(key, s);
        }
    }

    /**
     * signMAC (K, D, IV) is the 32-bit result of the GOST 28147/GOST R 34.13 in   
     * "imitovstavka" (MAC) mode, used with D as plaintext, K as key and IV   
     * as initialization vector.  Note that the standard specifies its use   
     * in this mode only with an initialization vector of zero.
     * 
     * @memberOf GostCipher
     * @method sign
     * @instance
     * @param {CryptoOperationData} k 8x32 bits key 
     * @param {CryptoOperationData} d 8 bits array with data 
     * @param {CryptoOperationData} iv initial vector
     * @return {CryptoOperationData} result
     */
    function signMAC(k, d, iv)
    {
        var key = this.keySchedule(k),
                s = new Uint8Array(iv || this.iv),
                m = Math.ceil(this.macLength >> 3) || this.blockSize >> 1;

        this.processMAC(key, s, d);

        var mac = new Uint8Array(m); // mac size
        mac.set(new Uint8Array(s.buffer, 0, m));
        return mac.buffer;
    }

    /**
     * verifyMAC (K, M, D, IV) the 32-bit result verification of the GOST 28147/GOST R 34.13 in   
     * "imitovstavka" (MAC) mode, used with D as plaintext, K as key and IV   
     * as initialization vector.  Note that the standard specifies its use   
     * in this mode only with an initialization vector of zero.
     * 
     * @memberOf GostCipher
     * @method verify
     * @instance
     * @param {CryptoOperationData} k 8x32 bits key 
     * @param {CryptoOperationData} m 8 bits array with signature
     * @param {CryptoOperationData} d 8 bits array with data 
     * @param {CryptoOperationData} iv 8x8 optional bits initial vector
     * @return {boolen} MAC verified = true
     */
    function verifyMAC(k, m, d, iv)
    {
        var mac = new Uint8Array(signMAC.call(this, k, d, iv)),
                test = byteArray(m);
        if (mac.length !== test.length)
            return false;
        for (var i = 0, n = mac.length; i < n; i++)
            if (mac[i] !== test[i])
                return false;
        return true;
    }

    /**
     * Algorithm name GOST 28147-KW<br><br>
     * 
     * This algorithm encrypts GOST 28147-89 CEK with a GOST 28147/GOST R 34.13 KEK.
     * Ref. rfc4357 6.1 GOST 28147-89 Key Wrap
     * Note: This algorithm MUST NOT be used with a KEK produced by VKO GOST   
     * R 34.10-94, because such a KEK is constant for every sender-recipient   
     * pair.  Encrypting many different content encryption keys on the same   
     * constant KEK may reveal that KEK.
     * 
     * @memberOf GostCipher
     * @method wrapKey
     * @instance
     * @param {CryptoOperationData} kek Key encryption key
     * @param {CryptoOperationData} cek Content encryption key
     * @returns {CryptoOperationData} Encrypted cek
     */
    function wrapKeyGOST(kek, cek)
    {
        var n = this.blockSize, k = this.keySize, len = k + (n >> 1);
        // 1) For a unique symmetric KEK, generate 8 octets at random and call 
        // the result UKM.  For a KEK, produced by VKO GOST R 34.10-2001, use 
        // the UKM that was used for key derivation.    
        if (!this.ukm) 
            throw new DataError('UKM must be defined');
        var ukm = new Uint8Array(this.ukm);
        // 2) Compute a 4-byte checksum value, GOST 28147IMIT (UKM, KEK, CEK).       
        // Call the result CEK_MAC. 
        var mac = signMAC.call(this, kek, cek, ukm);
        // 3) Encrypt the CEK in ECB mode using the KEK.  Call the ciphertext CEK_ENC.
        var enc = encryptECB.call(this, kek, cek);
        // 4) The wrapped content-encryption key is (UKM | CEK_ENC | CEK_MAC).
        var r = new Uint8Array(len);
        r.set(new Uint8Array(enc), 0);
        r.set(new Uint8Array(mac), k);
        return r.buffer;
    }

    /**
     * Algorithm name GOST 28147-KW<br><br>
     * 
     *  This algorithm decrypts GOST 28147-89 CEK with a GOST 28147 KEK.
     *  Ref. rfc4357 6.2 GOST 28147-89 Key Unwrap
     *  
     * @memberOf GostCipher
     * @method unwrapKey
     * @instance
     * @param {type} kek Key encryption key
     * @param {type} data Content encryption key
     * @return {CryptoOperationData} result
     */
    function unwrapKeyGOST(kek, data)
    {
        var n = this.blockSize, k = this.keySize, len = k + (n >> 1);
        // 1) If the wrapped content-encryption key is not 44 octets, then error.
        var d = buffer(data);
        if (d.byteLength !== len)
            throw new DataError('Wrapping key size must be ' + len + ' bytes');
        // 2) Decompose the wrapped content-encryption key into UKM, CEK_ENC, and CEK_MAC.  
        // UKM is the most significant (first) 8 octets. CEK_ENC is next 32 octets, 
        // and CEK_MAC is the least significant (last) 4 octets.    
        if (!this.ukm)
            throw new DataError('UKM must be defined');
        var ukm = new Uint8Array(this.ukm),
                enc = new Uint8Array(d, 0, k),
                mac = new Uint8Array(d, k, n >> 1);
        // 3) Decrypt CEK_ENC in ECB mode using the KEK.  Call the output CEK.
        var cek = decryptECB.call(this, kek, enc);
        // 4) Compute a 4-byte checksum value, GOST 28147IMIT (UKM, KEK, CEK), 
        // compare the result with CEK_MAC.  If they are not equal, then error.
        var check = verifyMAC.call(this, kek, mac, cek, ukm);
        if (!check)
            throw new DataError('Error verify MAC of wrapping key');
        return cek;
    }

    /**
     * Algorithm name GOST 28147-CPKW<br><br>
     * 
     * Given a random 64-bit UKM and a GOST 28147 key K, this algorithm   
     * creates a new GOST 28147-89 key K(UKM).
     * Ref. rfc4357 6.3 CryptoPro KEK Diversification Algorithm
     * 
     * @memberOf GostCipher
     * @method diversify
     * @instance
     * @private
     * @param {CryptoOperationData} kek Key encryption key
     * @param {CryptoOperationData} ukm Random generated value
     * @returns {CryptoOperationData} Diversified kek
     */
    function diversifyKEK(kek, ukm)
    {
        var n = this.blockSize;

        // 1) Let K[0] = K;    
        var k = intArray(kek);
        // 2) UKM is split into components a[i,j]:       
        //    UKM = a[0]|..|a[7] (a[i] - byte, a[i,0]..a[i,7] - it’s bits) 
        var a = [];
        for (var i = 0; i < n; i++) {
            a[i] = [];
            for (var j = 0; j < 8; j++) {
                a[i][j] = (ukm[i] >>> j) & 0x1;
            }
        }
        // 3) Let i be 0.    
        // 4) K[1]..K[8] are calculated by repeating the following algorithm       
        //    eight times:     
        for (var i = 0; i < n; i++) {
            //     A) K[i] is split into components k[i,j]:
            //        K[i] = k[i,0]|k[i,1]|..|k[i,7] (k[i,j] - 32-bit integer)
            //     B) Vector S[i] is calculated:        
            //        S[i] = ((a[i,0]*k[i,0] + ... + a[i,7]*k[i,7]) mod 2^32) |        
            //         (((~a[i,0])*k[i,0] + ... + (~a[i,7])*k[i,7]) mod 2^32);     
            var s = new Int32Array(2);
            for (var j = 0; j < 8; j++) {
                if (a[i][j])
                    s[0] = (s[0] + k[j]) & 0xffffffff;
                else
                    s[1] = (s[1] + k[j]) & 0xffffffff;
            }
            //     C) K[i+1] = encryptCFB (S[i], K[i], K[i])
            var iv = new Uint8Array(s.buffer);
            k = new Int32Array(encryptCFB.call(this, k, k, iv));
            //     D) i = i + 1
        }
        // 5) Let K(UKM) be K[8].
        return k;
    }

    /**
     * Algorithm name GOST 28147-CPKW<br><br>
     * 
     * This algorithm encrypts GOST 28147-89 CEK with a GOST 28147 KEK.   
     * It can be used with any KEK (e.g., produced by VKO GOST R 34.10-94 or   
     * VKO GOST R 34.10-2001) because a unique UKM is used to diversify the KEK.
     * Ref. rfc4357 6.3  CryptoPro Key Wrap
     * 
     * @memberOf GostCipher
     * @method wrapKey
     * @instance
     * @param {CryptoOperationData} kek Key encryption key
     * @param {CryptoOperationData} cek Content encryption key
     * @returns {CryptoOperationData} Encrypted cek
     */
    function wrapKeyCP(kek, cek)
    {
        var n = this.blockSize, k = this.keySize, len = k + (n >> 1);
        // 1) For a unique symmetric KEK or a KEK produced by VKO GOST R       
        // 34.10-94, generate 8 octets at random.  Call the result UKM.  For       
        // a KEK, produced by VKO GOST R 34.10-2001, use the UKM that was       
        // used for key derivation.
        if (!this.ukm) 
            throw new DataError('UKM must be defined');
        var ukm = new Uint8Array(this.ukm);
        // 2) Diversify KEK, using the CryptoPro KEK Diversification Algorithm,       
        // described in Section 6.5.  Call the result KEK(UKM).
        var dek = diversifyKEK.call(this, kek, ukm);
        // 3) Compute a 4-byte checksum value, GOST 28147IMIT (UKM, KEK(UKM),       
        // CEK).  Call the result CEK_MAC.    
        var mac = signMAC.call(this, dek, cek, ukm);
        // 4) Encrypt CEK in ECB mode using KEK(UKM).  Call the ciphertext       
        // CEK_ENC.    
        var enc = encryptECB.call(this, dek, cek);
        // 5) The wrapped content-encryption key is (UKM | CEK_ENC | CEK_MAC).
        var r = new Uint8Array(len);
        r.set(new Uint8Array(enc), 0);
        r.set(new Uint8Array(mac), k);
        return r.buffer;
    }

    /**
     * Algorithm name GOST 28147-CPKW<br><br>
     * 
     * This algorithm encrypts GOST 28147-89 CEK with a GOST 28147 KEK. 
     * Ref. rfc4357 6.4 CryptoPro Key Unwrap
     *
     * @memberOf GostCipher
     * @method unwrapKey
     * @instance
     * @param {CryptoOperationData} kek Key encryption key
     * @param {CryptoOperationData} data Encrypted content encryption keu
     * @return {CryptoOperationData} result Decrypted content encryption keu
     */
    function unwrapKeyCP(kek, data)
    {
        var n = this.blockSize, k = this.keySize, len = k + (n >> 1);
        // 1) If the wrapped content-encryption key is not 44 octets, then error.    
        var d = buffer(data);
        if (d.byteLength !== len)
            throw new DataError('Wrapping key size must be ' + len + ' bytes');
        // 2) Decompose the wrapped content-encryption key into UKM, CEK_ENC,       
        // and CEK_MAC.  UKM is the most significant (first) 8 octets.       
        // CEK_ENC is next 32 octets, and CEK_MAC is the least significant       
        // (last) 4 octets.    
        if (!this.ukm)
            throw new DataError('UKM must be defined');
        var ukm = new Uint8Array(this.ukm),
                enc = new Uint8Array(d, 0, k),
                mac = new Uint8Array(d, k, n >> 1);
        // 3) Diversify KEK using the CryptoPro KEK Diversification Algorithm,       
        // described in section 6.5.  Call the result KEK(UKM).    
        var dek = diversifyKEK.call(this, kek, ukm);
        // 4) Decrypt CEK_ENC in ECB mode using KEK(UKM).  Call the output CEK.    
        var cek = decryptECB.call(this, dek, enc);
        // 5) Compute a 4-byte checksum value, GOST 28147IMIT (UKM, KEK(UKM),       
        // CEK), compare the result with CEK_MAC.  If they are not equal, 
        // then it is an error.
        var check = verifyMAC.call(this, dek, mac, cek, ukm);
        if (!check)
            throw new DataError('Error verify MAC of wrapping key');
        return cek;
    }

    /**
     * SignalCom master key packing algorithm
     * 
     * kek stored in 3 files - kek.opq, mk.db3, masks.db3
     * kek.opq - always 36 bytes length = 32 bytes encrypted kek + 4 bytes mac of decrypted kek
     * mk.db3 - 6 bytes header (1 byte magic code 0x22 + 1 byte count of masks + 4 bytes mac of 
     * xor summarizing masks value) + attached masks 
     * masks.db3 - detached masks. 
     * Total length  of attached + detached masks = 32 bits * count of masks
     * Default value of count 8 = (7 attached + 1 detached). But really no reason for such 
     * separation - all masks xor summarizing - order is not matter.
     * Content of file rand.opq can used as ukm. Don't forget change file content after using. 
     * 
     * For usb-token files has names: 
     * a001 - mk.db3, b001 - masks.db3, c001 - kek.opq, d001 - rand.opq
     * For windows registry
     * 00000001 - mk.db3, 00000002 - masks.db3, 00000003 - key.opq, 00000004 - rand.opq, 
     * 00000006 - keys\00000001.key, 0000000A - certificate
     * 
     * @memberOf GostCipher
     * @method packKey
     * @instance
     * @private
     * @param {CryptoOperationData} unpacked - clear main key 32 bytes
     * @param {CryptoOperationData} ukm - random vector for packing - 32 bytes * (count of masks - 1)
     * @returns {CryptoOperationData} packed master key - concatination of mk.db3 + masks.db3
     */
    function packKeySC(unpacked, ukm)
    {
        var m = this.blockSize >> 1, k = this.keySize;
        var mcount = 8;
        var key = new Uint8Array(buffer(unpacked));
        if (key.byteLength !== k)
            throw new DataError('Wrong cleartext size ' + key.byteLength + ' bytes');
        // Check or generate UKM
        ukm = ukm || this.ukm;
        if (ukm) {
            ukm = new Uint8Array(buffer(ukm));
            if (ukm.byteLength > 0 && ukm.byteLength % k === 0)
                mcount = ukm.byteLength / k + 1;
            else
                throw new DataError('Wrong rand size ' + ukm.byteLength + ' bytes');
        } else
            randomSeed(ukm = new Uint8Array((mcount - 1) * k));
        // Output array
        var d = new Uint8Array(mcount * k + m + 2), b = d.buffer;
        // Calculate MAC
        var zero32 = new Uint8Array(k);
        var mac = signMAC.call(this, key, zero32);
        d[0] = 0x22; // Magic code
        d[1] = mcount; // Count of masks
        d.set(new Uint8Array(mac), 2);
        d.set(ukm, k + m + 2);
        for (var i = 1; i < mcount; i++) {
            var mask = new Uint8Array(b, 2 + m + k * i);
            for (var j = 0; j < k; j++)
                key[j] ^= mask[j];
        }
        d.set(key, m + 2);
        return d.buffer;
    }

    /**
     * Algorithm name GOST 28147-SCKW<br><br>
     * 
     * SignalCom master key unpacking algorithm
     * 
     * @memberOf GostCipher
     * @method unpackKey
     * @instance
     * @private
     * @param {CryptoOperationData} packed - concatination of mk.db3 + masks.db3
     * @returns {CryptoOperationData} unpacked master key
     */
    function unpackKeySC(packed)
    {
        var m = this.blockSize >> 1, k = this.keySize;
        var b = buffer(packed);
        // Unpack master key
        var magic = new Uint8Array(b, 0, 1)[0];
        if (magic !== 0x22)
            throw new DataError('Invalid magic number');
        var mcount = new Uint8Array(b, 1, 1)[0];
        var mac = new Uint8Array(b, 2, m); // MAC for summarized mask
        // Compute packKey xor summing for all masks
        var key = new Uint8Array(k);
        for (var i = 0; i < mcount; i++) {
            var mask = new Uint8Array(b, 2 + m + k * i, k);
            for (var j = 0; j < k; j++)
                key[j] ^= mask[j];
        }
        // Test MAC for packKey with default sBox on zero 32 bytes array
        var zero32 = new Uint8Array(k);
        var test = verifyMAC.call(this, key, mac, zero32);
        if (!test) {
            // Try to use different sBoxes
            var names = ['E-A', 'E-B', 'E-C', 'E-D', 'E-SC'];
            for (var i = 0, n = names.length; i < n; i++) {
                this.sBox = sBoxes[names[i]];
                test = verifyMAC.call(this, key, mac, zero32);
                if (test)
                    break;
            }
        }
        if (!test)
            throw new DataError('Invalid main key MAC');
        return key.buffer;
    }

    /**
     * Algorithm name GOST 28147-SCKW<br><br>
     * 
     * SignalCom Key Wrapping algorithm
     * 
     * @memberOf GostCipher
     * @method wrapKey
     * @instance
     * @param {CryptoOperationData} kek - clear kek or concatination of mk.db3 + masks.db3
     * @param {CryptoOperationData} cek - key for wrapping 
     * @returns {CryptoOperationData} wrapped key - file kek.opq
     */
    function wrapKeySC(kek, cek)
    {
        var m = this.blockSize >> 1, n = this.keySize;
        var k = buffer(kek);
        var c = buffer(cek);
        if (k.byteLength !== n)
            k = unpackKeySC.call(this, k);
        var enc = encryptECB.call(this, k, c);
        var mac = signMAC.call(this, k, c);
        var d = new Uint8Array(m + n);
        d.set(new Uint8Array(enc), 0);
        d.set(new Uint8Array(mac), n);
        return d.buffer;
    }

    /**
     * Algorithm name GOST 28147-SCKW<br><br>
     * 
     * SignalCom Key UnWrapping algorithm
     * 
     * @memberOf GostCipher
     * @method unwrapKey
     * @instance
     * @param {CryptoOperationData} kek - concatination of files mk.db3 + masks.db3 or clear kek 
     * @param {CryptoOperationData} cek - wrapping key - file kek.opq
     * @return {CryptoOperationData} result
     */
    function unwrapKeySC(kek, cek)
    {
        var m = this.blockSize >> 1, n = this.keySize;
        var k = buffer(kek);
        var c = buffer(cek);
        if (k.byteLength !== n)
            k = unpackKeySC.call(this, k);
        var enc = new Uint8Array(c, 0, n); // Encrypted kek
        var mac = new Uint8Array(c, n, m); // MAC for clear kek
        var d = decryptECB.call(this, k, enc);
        if (!verifyMAC.call(this, k, mac, d))
            throw new DataError('Invalid key MAC');
        return d;
    }

    /**
     * Algorithm name GOST 28147-SCKW<br><br>
     * 
     * SignalCom master key generation for wrapping
     * 
     * @memberOf GostCipher
     * @method generateKey
     * @instance
     * @return {CryptoOperationData} result
     */
    function generateWrappingKeySC()
    {
        return packKeySC.call(this, generateKey.call(this));
    }

    function maskKey(mask, key, inverse, keySize)
    {
        var k = keySize / 4, 
                m32 = new Int32Array(buffer(mask)),
                k32 = new Int32Array(buffer(key)), 
                r32 = new Int32Array(k);
        if (inverse)
            for (var i = 0; i < k; i++) 
                r32[i] = (k32[i] + m32[i]) & 0xffffffff;
        else
            for (var i = 0; i < k; i++) 
                r32[i] = (k32[i] - m32[i]) & 0xffffffff;
        return r32.buffer;
    }

    /**
     * Algorithm name GOST 28147-MASK<br><br>
     * 
     * This algorithm wrap key mask
     * 
     * @memberOf GostCipher
     * @method wrapKey
     * @instance
     * @param {CryptoOperationData} mask The mask
     * @param {CryptoOperationData} key The key
     * @returns {CryptoOperationData} The masked key
     */
    function wrapKeyMask(mask, key)
    {
        return maskKey(mask, key, this.procreator === 'VN', this.keySize);
    }

    /**
     * Algorithm name GOST 28147-CPKW<br><br>
     * 
     * This algorithm unwrap key mask
     *
     * @memberOf GostCipher
     * @method unwrapKey
     * @instance
     * @param {CryptoOperationData} mask The mask
     * @param {CryptoOperationData} key The masked key
     * @return {CryptoOperationData} result The key
     */
    function unwrapKeyMask(mask, key)
    {
        return maskKey(mask, key, this.procreator !== 'VN', this.keySize);
    }
    
    /**
     * Algorithm name GOST 28147-CPKM<br><br>
     * 
     * Key meshing in according to rfc4357 2.3.2. CryptoPro Key Meshing
     * 
     * @memberOf GostCipher
     * @method keyMeshing
     * @instance
     * @private
     * @param {(Uint8Array|CryptoOperationData)} k 8x8 bit key 
     * @param {Uint8Array} s 8x8 bit sync (iv)
     * @param {Integer} i block index
     * @param {Int32Array} key 8x32 bit key schedule 
     * @param {boolean} e true - decrypt
     * @returns CryptoOperationData next 8x8 bit key
     */
    function keyMeshingCP(k, s, i, key, e)
    {
        if ((i + 1) * this.blockSize % 1024 === 0) { // every 1024 octets
            // K[i+1] = decryptECB (K[i], C);
            k = decryptECB.call(this, k, C);
            // IV0[i+1] = encryptECB (K[i+1],IVn[i])
            s.set(new Uint8Array(encryptECB.call(this, k, s)));
            // restore key schedule
            key.set(this.keySchedule(k, e));
        }
        return k;
    }

    /**
     *  Null Key Meshing in according to rfc4357 2.3.1
     * 
     * @memberOf GostCipher
     * @method keyMeshing
     * @instance
     * @private
     * @param {(Uint8Array|CryptoOperationData)} k 8x8 bit key 
     */
    function noKeyMeshing(k)
    {
        return k;
    }

    /**
     * Algorithm name GOST 28147-NoPadding<br><br>
     * 
     * No padding.
     * 
     * @memberOf GostCipher
     * @method padding
     * @instance
     * @private
     * @param {Uint8Array} d array with source data
     * @returns {Uint8Array} result
     */
    function noPad(d)
    {
        return new Uint8Array(d);
    }

    /**
     * Algorithm name GOST 28147-PKCS5Padding<br><br>
     * 
     *  PKCS#5 padding: 8-x remaining bytes are filled with the value of      
     *  8-x.  If there’s no incomplete block, one extra block filled with      
     *  value 8 is added
     * 
     * @memberOf GostCipher
     * @method padding
     * @instance
     * @private
     * @param {Uint8Array} d array with source data
     * @returns {Uint8Array} result
     */
    function pkcs5Pad(d)
    {
        var n = d.byteLength,
                nb = this.blockSize,
                q = nb - n % nb,
                m = Math.ceil((n + 1) / nb) * nb,
                r = new Uint8Array(m);
        r.set(d);
        for (var i = n; i < m; i++)
            r[i] = q;
        return r;
    }

    function pkcs5Unpad(d)
    {
        var m = d.byteLength,
                nb = this.blockSize,
                q = d[m - 1],
                n = m - q;
        if (q > nb)
            throw DataError('Invalid padding');
        var r = new Uint8Array(n);
        if (n > 0)
            r.set(new Uint8Array(d.buffer, 0, n));
        return r;
    }


    /**
     * Algorithm name GOST 28147-ZeroPadding<br><br>
     * 
     * Zero padding: 8-x remaining bytes are filled with zero
     * 
     * @memberOf GostCipher
     * @method padding
     * @instance
     * @private
     * @param {Uint8Array} d array with source data
     * @returns {Uint8Array} result
     */
    function zeroPad(d)
    {
        var n = d.byteLength,
                nb = this.blockSize,
                m = Math.ceil(n / nb) * nb,
                r = new Uint8Array(m);
        r.set(d);
        for (var i = n; i < m; i++)
            r[i] = 0;
        return r;
    }


    /**
     * Algorithm name GOST 28147-BitPadding<br><br>
     * 
     * Bit padding: P* = P || 1 || 000...0 If there’s no incomplete block, 
     * one extra block filled with 1 || 000...0
     * 
     * @memberOf GostCipher
     * @method padding
     * @instance
     * @private
     * @param {Uint8Array} d array with source data
     * @returns {Uint8Array} result
     */
    function bitPad(d)
    {
        var n = d.byteLength,
                nb = this.blockSize,
                m = Math.ceil((n + 1) / nb) * nb,
                r = new Uint8Array(m);
        r.set(d);
        r[n] = 1;
        for (var i = n + 1; i < m; i++)
            r[i] = 0;
        return r;
    }

    function bitUnpad(d)
    {
        var m = d.byteLength,
                n = m;
        while (n > 1 && d[n - 1] === 0)
            n--;
        if (d[n - 1] !== 1)
            throw DataError('Invalid padding');
        n--;
        var r = new Uint8Array(n);
        if (n > 0)
            r.set(new Uint8Array(d.buffer, 0, n));
        return r;
    }

    /**
     * Algorithm name GOST 28147-RandomPadding<br><br>
     * 
     * Random padding: 8-x remaining bytes of the last block are set to      
     * random.
     * 
     * @memberOf GostCipher
     * @method padding
     * @instance
     * @private
     * @param {Uint8Array} d array with source data
     * @returns {Uint8Array} result
     */
    function randomPad(d)
    {
        var n = d.byteLength,
                nb = this.blockSize,
                q = nb - n % nb,
                m = Math.ceil(n / nb) * nb,
                r = new Uint8Array(m), e = new Uint8Array(r.buffer, n, q);
        r.set(d);
        randomSeed(e);
        return r;
    }

    /**
     * GOST 28147-89 Encryption Algorithm<br><br> 
     * 
     * References {@link http://tools.ietf.org/html/rfc5830}<br><br>
     * 
     * When keys and initialization vectors are converted to/from byte arrays, 
     * little-endian byte order is assumed.<br><br>
     * 
     * Normalized algorithm identifier common parameters:
     * 
     *  <ul>
     *      <li><b>name</b> Algorithm name 'GOST 28147' or 'GOST R 34.12'</li>
     *      <li><b>version</b> Algorithm version, number
     *          <ul>
     *              <li><b>1989</b> Current version of standard</li>
     *              <li><b>2015</b> New draft version of standard</li>
     *          </ul>
     *      </li>
     *      <li><b>length</b> Block length
     *          <ul>
     *              <li><b>64</b> 64 bits length (default)</li>
     *              <li><b>128</b> 128 bits length (only for version 2015)</li>
     *          </ul>
     *      </li>
     *      <li><b>mode</b> Algorithm mode, string
     *          <ul>
     *              <li><b>ES</b> Encryption mode (default)</li>
     *              <li><b>MAC</b> "imitovstavka" (MAC) mode</li>
     *              <li><b>KW</b> Key wrapping mode</li>
     *          </ul>
     *      </li>
     *      <li><b>sBox</b> Paramset sBox for GOST 28147-89, string. Used only if version = 1989</li>
     *  </ul>
     *  
     * Supported algorithms, modes and parameters:
     * 
     *  <ul>
     *      <li>Encript/Decrypt mode (ES)
     *          <ul>
     *              <li><b>block</b> Block mode, string. Default ECB</li>
     *              <li><b>keyMeshing</b> Key meshing mode, string. Default NO</li>
     *              <li><b>padding</b> Padding mode, string. Default NO for CFB and CTR modes, or ZERO for others</li>
     *              <li><b>iv</b> {@link CryptoOperationData} Initial vector with length of block. Default - zero block</li>
     *          </ul>
     *      </li>
     *      <li>Sign/Verify mode (MAC)
     *          <ul>
     *              <li><b>macLength</b> Length of mac in bits (default - 32 bits)</li>
     *              <li><b>iv</b> {@link CryptoOperationData} Initial vector with length of block. Default - zero block</li>
     *          </ul>
     *      </li>
     *      <li>Wrap/Unwrap key mode (KW)
     *          <ul>
     *              <li><b>keyWrapping</b> Mode of keywrapping, string. Default NO - standard GOST key wrapping</li>
     *              <li><b>ukm</b> {@link CryptoOperationData} User key material. Default - random generated value</li>
     *          </ul>
     *      </li>
     *  </ul>
     *      
     * Supported paramters values:
     *      
     *  <ul>
     *      <li>Block modes (parameter 'block')
     *          <ul>
     *              <li><b>ECB</b> "prostaya zamena" (ECB) mode (default)</li>
     *              <li><b>CFB</b> "gammirovanie s obratnoj svyaziyu po shifrotekstu" (CFB) mode</li>
     *              <li><b>OFB</b> "gammirovanie s obratnoj svyaziyu po vyhodu" (OFB) mode</li>
     *              <li><b>CTR</b> "gammirovanie" (counter) mode</li>
     *              <li><b>CBC</b> Cipher-Block-Chaining (CBC) mode</li>
     *          </ul>
     *      </li>
     *      <li>Key meshing modes (parameter 'keyMeshing')
     *          <ul>
     *              <li><b>NO</b> No key wrapping (default)</li>
     *              <li><b>CP</b> CryptoPor Key key meshing</li>
     *          </ul>
     *      </li>
     *      <li>Padding modes (parameter 'padding')
     *          <ul>
     *              <li><b>NO</b> No padding only for CFB, OFB and CTR modes</li>
     *              <li><b>PKCS5</b> PKCS#5 padding mode</li>
     *              <li><b>ZERO</b> Zero bits padding mode</li>
     *              <li><b>RANDOM</b> Random bits padding mode</li>
     *              <li><b>BIT</b> One bit padding mode</li>
     *          </ul>
     *      </li>
     *      <li>Wrapping key modes (parameter 'keyWrapping')
     *          <ul>
     *              <li><b>NO</b> Ref. rfc4357 6.1 GOST 28147-89 Key wrapping</li>
     *              <li><b>CP</b> CryptoPro Key wrapping mode</li>
     *              <li><b>SC</b> SignalCom Key wrapping mode</li>
     *          </ul>
     *      </li>
     *  </ul>
     * 
     * @class GostCipher
     * @param {AlgorithmIndentifier} algorithm WebCryptoAPI algorithm identifier
     */
    function GostCipher(algorithm)
    {
        // Check little endian support
        if (!littleEndian)
            throw new NotSupportedError('Big endian platform not supported');
        algorithm = algorithm || {};
        this.keySize = 32;
        this.blockLength = algorithm.length || 64;
        this.blockSize = this.blockLength >> 3;

        this.name = (algorithm.name || (algorithm.version === 1 ? 'RC2' :
                algorithm.version === 1989 ? 'GOST 28147' : 'GOST R 34.12')) +
                (algorithm.version > 4 ? '-' + ((algorithm.version || 1989) % 100) : '') + '-' +
                (this.blockLength === 64 ? '' : this.blockLength + '-') +
                ((algorithm.mode === 'MAC') ? 'MAC-' + (algorithm.macLength || this.blockLength >> 1) :
                        (algorithm.mode === 'KW' || algorithm.keyWrapping) ?
                        ((algorithm.keyWrapping || 'NO') !== 'NO' ? algorithm.keyWrapping : '') + 'KW' :
                        (algorithm.block || 'ECB') + ((algorithm.block === 'CFB' || algorithm.block === 'OFB' ||
                        (algorithm.block === 'CTR' && algorithm.version === 2015)) &&
                        algorithm.shiftBits && algorithm.shiftBits !== this.blockLength ? '-' + algorithm.shiftBits : '') +
                        (algorithm.padding ? '-' + (algorithm.padding || (algorithm.block === 'CTR' ||
                                algorithm.block === 'CFB' || algorithm.block === 'OFB' ? 'NO' : 'ZERO')) + 'PADDING' : '') +
                        ((algorithm.keyMeshing || 'NO') !== 'NO' ? '-CPKEYMESHING' : '')) +
                (algorithm.procreator ? '/' + algorithm.procreator : '') +
                (typeof algorithm.sBox === 'string' ? '/' + algorithm.sBox : '');

        // Algorithm procreator
        this.procreator = algorithm.procreator;
        
        switch (algorithm.version || 1989) {
            case 1:
                this.process = processRC2;
                this.keySchedule = keyScheduleRC2;
                this.blockLength = 64;
                this.effectiveLength = algorithm.length || 32;
                this.keySize = 8 * Math.ceil(this.effectiveLength / 8); // Max 128
                this.blockSize = this.blockLength >> 3;
                break;
            case 2015:
                this.version = 2015;
                if (this.blockLength === 64) {
                    this.process = process15;
                    this.keySchedule = keySchedule15;
                } else if (this.blockLength === 128) {
                    this.process = process128;
                    this.keySchedule = keySchedule128;
                } else
                    throw new DataError('Invalid block length');
                this.processMAC = processMAC15;
                break;
            case 1989:
                this.version = 1989;
                this.process = process89;
                this.processMAC = processMAC89;
                this.keySchedule = keySchedule89;
                if (this.blockLength !== 64)
                    throw new DataError('Invalid block length');
                break;
            default:
                throw new NotSupportedError('Algorithm version ' + algorithm.version + ' not supported');
        }

        switch (algorithm.mode || (algorithm.keyWrapping && 'KW') || 'ES') {

            case 'ES':
                switch (algorithm.block || 'ECB') {
                    case 'ECB':
                        this.encrypt = encryptECB;
                        this.decrypt = decryptECB;
                        break;
                    case 'CTR':
                        if (this.version === 1989) {
                            this.encrypt = processCTR89;
                            this.decrypt = processCTR89;
                        } else {
                            this.encrypt = processCTR15;
                            this.decrypt = processCTR15;
                            this.shiftBits = algorithm.shiftBits || this.blockLength;
                        }
                        break
                    case 'CBC':
                        this.encrypt = encryptCBC;
                        this.decrypt = decryptCBC;
                        break
                    case 'CFB':
                        this.encrypt = encryptCFB;
                        this.decrypt = decryptCFB;
                        this.shiftBits = algorithm.shiftBits || this.blockLength;
                        break;
                    case 'OFB':
                        this.encrypt = processOFB;
                        this.decrypt = processOFB;
                        this.shiftBits = algorithm.shiftBits || this.blockLength;
                        break;
                    default:
                        throw new NotSupportedError('Block mode ' + algorithm.block + ' not supported');
                }
                switch (algorithm.keyMeshing) {
                    case 'CP':
                        this.keyMeshing = keyMeshingCP;
                        break;
                    default:
                        this.keyMeshing = noKeyMeshing;
                }
                if (this.encrypt === encryptECB || this.encrypt === encryptCBC) {
                    switch (algorithm.padding) {
                        case 'PKCS5P':
                            this.pad = pkcs5Pad;
                            this.unpad = pkcs5Unpad;
                            break;
                        case 'RANDOM':
                            this.pad = randomPad;
                            this.unpad = noPad;
                            break;
                        case 'BIT':
                            this.pad = bitPad;
                            this.unpad = bitUnpad;
                            break;
                        default:
                            this.pad = zeroPad;
                            this.unpad = noPad;
                    }
                } else {
                    this.pad = noPad;
                    this.unpad = noPad;
                }
                this.generateKey = generateKey;
                break;
            case 'MAC':
                this.sign = signMAC;
                this.verify = verifyMAC;
                this.generateKey = generateKey;
                this.macLength = algorithm.macLength || (this.blockLength >> 1);
                this.pad = noPad;
                this.unpad = noPad;
                this.keyMeshing = noKeyMeshing;
                break;
            case 'KW':
                this.pad = noPad;
                this.unpad = noPad;
                this.keyMeshing = noKeyMeshing;
                switch (algorithm.keyWrapping) {
                    case 'CP':
                        this.wrapKey = wrapKeyCP;
                        this.unwrapKey = unwrapKeyCP;
                        this.generateKey = generateKey;
                        this.shiftBits = algorithm.shiftBits || this.blockLength;
                        break;
                    case 'SC':
                        this.wrapKey = wrapKeySC;
                        this.unwrapKey = unwrapKeySC;
                        this.generateKey = generateWrappingKeySC;
                        break;
                    default:
                        this.wrapKey = wrapKeyGOST;
                        this.unwrapKey = unwrapKeyGOST;
                        this.generateKey = generateKey;
                }
                break;
            case 'MASK':
                this.wrapKey = wrapKeyMask;
                this.unwrapKey = unwrapKeyMask;
                this.generateKey = generateKey;
                break;
            default:
                throw new NotSupportedError('Mode ' + algorithm.mode + ' not supported');
        }

        // Define sBox parameter
        var sBox = algorithm.sBox, sBoxName;
        if (!sBox)
            sBox = this.version === 2015 ? sBoxes['E-Z'] : this.procreator === 'SC' ? sBoxes['E-SC'] : sBoxes['E-A'];
        else if (typeof sBox === 'string') {
            sBoxName = sBox.toUpperCase();
            sBox = sBoxes[sBoxName];
            if (!sBox)
                throw new SyntaxError('Unknown sBox name: ' + algorithm.sBox);
        } else if (!sBox.length || sBox.length !== sBoxes['E-Z'].length)
            throw new SyntaxError('Length of sBox must be ' + sBoxes['E-Z'].length);
        this.sBox = sBox;
        // Initial vector
        if (algorithm.iv) {
            this.iv = new Uint8Array(algorithm.iv);
            if (this.iv.byteLength !== this.blockSize && this.version === 1989)
                throw new SyntaxError('Length of iv must be ' + this.blockLength + ' bits');
            else if (this.iv.byteLength !== this.blockSize >> 1 && this.encrypt === processCTR15)
                throw new SyntaxError('Length of iv must be ' + this.blockLength >> 1 + ' bits');
            else if (this.iv.byteLength % this.blockSize !== 0 && this.encrypt !== processCTR15)
                throw new SyntaxError('Length of iv must be a multiple of ' + this.blockLength + ' bits');
        } else
            this.iv = this.blockLength === 128 ? defaultIV128 : defaultIV;
        // User key material
        if (algorithm.ukm) {
            this.ukm = new Uint8Array(algorithm.ukm);
            if (this.ukm.byteLength * 8 !== this.blockLength)
                throw new SyntaxError('Length of ukm must be ' + this.blockLength + ' bits');
        }
    }

module.exports = GostCipher;




/***/ }),

/***/ "./node_modules/node-gost-crypto/lib/gostCoding.js":
/*!*********************************************************!*\
  !*** ./node_modules/node-gost-crypto/lib/gostCoding.js ***!
  \*********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

/**
 * @file Coding algorithms: Base64, Hex, Int16, Chars, BER and PEM
 * @version 1.76
 * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *    
 * THIS SOfTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES Of MERCHANTABILITY AND fITNESS fOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * fOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT Of SUBSTITUTE GOODS OR
 * SERVICES; LOSS Of USE, DATA, OR PROfITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY Of LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT Of THE USE
 * Of THIS SOfTWARE, EVEN If ADVISED Of THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

const gostCrypto = __webpack_require__(/*! ./gostCrypto */ "./node_modules/node-gost-crypto/lib/gostCrypto.js");

    /**
     * The Coding interface provides string converting methods: Base64, Hex, 
     * Int16, Chars, BER and PEM
     * @class GostCoding
     * 
     */
    var root = __webpack_require__.g;
    var DataError = root.DataError || root.Error;
    var CryptoOperationData = root.ArrayBuffer;
    var Date = root.Date;

    function buffer(d) {
        if (d instanceof CryptoOperationData)
            return d;
        else if (d && d.buffer && d.buffer instanceof CryptoOperationData)
            return d.byteOffset === 0 && d.byteLength === d.buffer.byteLength ?
                    d.buffer : new Uint8Array(new Uint8Array(d, d.byteOffset, d.byteLength)).buffer;
        else
            throw new DataError('CryptoOperationData required');
    }

    function GostCoding() {
    }

    /**
     * BASE64 conversion
     * 
     * @class GostCoding.Base64
     */
    var Base64 = {
        /**
         * Base64.decode convert BASE64 string s to CryptoOperationData
         * 
         * @memberOf GostCoding.Base64
         * @param {String} s BASE64 encoded string value
         * @returns {CryptoOperationData} Binary decoded data
         */
        decode: function (s) {
            s = s.replace(/[^A-Za-z0-9\+\/]/g, '');
            var n = s.length,
                    k = n * 3 + 1 >> 2, r = new Uint8Array(k);

            for (var m3, m4, u24 = 0, j = 0, i = 0; i < n; i++) {
                m4 = i & 3;
                var c = s.charCodeAt(i);

                c = c > 64 && c < 91 ?
                        c - 65 : c > 96 && c < 123 ?
                        c - 71 : c > 47 && c < 58 ?
                        c + 4 : c === 43 ?
                        62 : c === 47 ?
                        63 : 0;

                u24 |= c << 18 - 6 * m4;
                if (m4 === 3 || n - i === 1) {
                    for (m3 = 0; m3 < 3 && j < k; m3++, j++) {
                        r[j] = u24 >>> (16 >>> m3 & 24) & 255;
                    }
                    u24 = 0;

                }
            }
            return r.buffer;
        },
        /**
         * Base64.encode(data) convert CryptoOperationData data to BASE64 string
         * 
         * @memberOf GostCoding.Base64
         * @param {CryptoOperationData} data Bynary data for encoding
         * @returns {String} BASE64 encoded data
         */
        encode: function (data) {
            var slen = 8, d = new Uint8Array(buffer(data));
            var m3 = 2, s = '';
            for (var n = d.length, u24 = 0, i = 0; i < n; i++) {
                m3 = i % 3;
                if (i > 0 && (i * 4 / 3) % (12 * slen) === 0)
                    s += '\r\n';
                u24 |= d[i] << (16 >>> m3 & 24);
                if (m3 === 2 || n - i === 1) {
                    for (var j = 18; j >= 0; j -= 6) {
                        var c = u24 >>> j & 63;
                        c = c < 26 ? c + 65 : c < 52 ? c + 71 : c < 62 ? c - 4 :
                                c === 62 ? 43 : c === 63 ? 47 : 65;
                        s += String.fromCharCode(c);
                    }
                    u24 = 0;
                }
            }
            return s.substr(0, s.length - 2 + m3) + (m3 === 2 ? '' : m3 === 1 ? '=' : '==');
        }
    };

    /**
     * BASE64 conversion
     * 
     * @memberOf GostCoding
     * @insnance
     * @type GostCoding.Base64
     */
    GostCoding.prototype.Base64 = Base64;

    /**
     * Text string conversion <br>
     * Methods support charsets: ascii, win1251, utf8, utf16 (ucs2, unicode), utf32 (ucs4)
     * 
     * @class GostCoding.Chars
     */
    var Chars = (function () {

        var _win1251_ = {
            0x402: 0x80, 0x403: 0x81, 0x201A: 0x82, 0x453: 0x83, 0x201E: 0x84, 0x2026: 0x85, 0x2020: 0x86, 0x2021: 0x87,
            0x20AC: 0x88, 0x2030: 0x89, 0x409: 0x8A, 0x2039: 0x8B, 0x40A: 0x8C, 0x40C: 0x8D, 0x40B: 0x8E, 0x40f: 0x8f,
            0x452: 0x90, 0x2018: 0x91, 0x2019: 0x92, 0x201C: 0x93, 0x201D: 0x94, 0x2022: 0x95, 0x2013: 0x96, 0x2014: 0x97,
            0x2122: 0x99, 0x459: 0x9A, 0x203A: 0x9B, 0x45A: 0x9C, 0x45C: 0x9D, 0x45B: 0x9E, 0x45f: 0x9f,
            0xA0: 0xA0, 0x40E: 0xA1, 0x45E: 0xA2, 0x408: 0xA3, 0xA4: 0xA4, 0x490: 0xA5, 0xA6: 0xA6, 0xA7: 0xA7,
            0x401: 0xA8, 0xA9: 0xA9, 0x404: 0xAA, 0xAB: 0xAB, 0xAC: 0xAC, 0xAD: 0xAD, 0xAE: 0xAE, 0x407: 0xAf,
            0xB0: 0xB0, 0xB1: 0xB1, 0x406: 0xB2, 0x456: 0xB3, 0x491: 0xB4, 0xB5: 0xB5, 0xB6: 0xB6, 0xB7: 0xB7,
            0x451: 0xB8, 0x2116: 0xB9, 0x454: 0xBA, 0xBB: 0xBB, 0x458: 0xBC, 0x405: 0xBD, 0x455: 0xBE, 0x457: 0xBf
        };
        var _win1251back_ = {};
        for (var from in _win1251_) {
            var to = _win1251_[from];
            _win1251back_[to] = from;
        }

        return {
            /**
             * Chars.decode(s, charset) convert string s with defined charset to CryptoOperationData 
             * 
             * @memberOf GostCoding.Chars
             * @param {string} s Javascript string
             * @param {string} charset Charset, default 'win1251'
             * @returns {CryptoOperationData} Decoded binary data
             */
            decode: function (s, charset) {
                charset = (charset || 'win1251').toLowerCase().replace('-', '');
                var r = [];
                for (var i = 0, j = s.length; i < j; i++) {
                    var c = s.charCodeAt(i);
                    if (charset === 'utf8') {
                        if (c < 0x80) {
                            r.push(c);
                        } else if (c < 0x800) {
                            r.push(0xc0 + (c >>> 6));
                            r.push(0x80 + (c & 63));
                        } else if (c < 0x10000) {
                            r.push(0xe0 + (c >>> 12));
                            r.push(0x80 + (c >>> 6 & 63));
                            r.push(0x80 + (c & 63));
                        } else if (c < 0x200000) {
                            r.push(0xf0 + (c >>> 18));
                            r.push(0x80 + (c >>> 12 & 63));
                            r.push(0x80 + (c >>> 6 & 63));
                            r.push(0x80 + (c & 63));
                        } else if (c < 0x4000000) {
                            r.push(0xf8 + (c >>> 24));
                            r.push(0x80 + (c >>> 18 & 63));
                            r.push(0x80 + (c >>> 12 & 63));
                            r.push(0x80 + (c >>> 6 & 63));
                            r.push(0x80 + (c & 63));
                        } else {
                            r.push(0xfc + (c >>> 30));
                            r.push(0x80 + (c >>> 24 & 63));
                            r.push(0x80 + (c >>> 18 & 63));
                            r.push(0x80 + (c >>> 12 & 63));
                            r.push(0x80 + (c >>> 6 & 63));
                            r.push(0x80 + (c & 63));
                        }
                    } else if (charset === 'unicode' || charset === 'ucs2' || charset === 'utf16') {
                        if (c < 0xD800 || (c >= 0xE000 && c <= 0x10000)) {
                            r.push(c >>> 8);
                            r.push(c & 0xff);
                        } else if (c >= 0x10000 && c < 0x110000) {
                            c -= 0x10000;
                            var first = ((0xffc00 & c) >> 10) + 0xD800;
                            var second = (0x3ff & c) + 0xDC00;
                            r.push(first >>> 8);
                            r.push(first & 0xff);
                            r.push(second >>> 8);
                            r.push(second & 0xff);
                        }
                    } else if (charset === 'utf32' || charset === 'ucs4') {
                        r.push(c >>> 24 & 0xff);
                        r.push(c >>> 16 & 0xff);
                        r.push(c >>> 8 & 0xff);
                        r.push(c & 0xff);
                    } else if (charset === 'win1251') {
                        if (c >= 0x80) {
                            if (c >= 0x410 && c < 0x450) // А..Яа..я
                                c -= 0x350;
                            else
                                c = _win1251_[c] || 0;
                        }
                        r.push(c);
                    } else
                        r.push(c & 0xff);
                }
                return new Uint8Array(r).buffer;
            },
            /**
             * Chars.encode(data, charset) convert CryptoOperationData data to string with defined charset
             * 
             * @memberOf GostCoding.Chars
             * @param {CryptoOperationData} data Binary data
             * @param {string} charset Charset, default win1251
             * @returns {string} Encoded javascript string
             */
            encode: function (data, charset) {
                charset = (charset || 'win1251').toLowerCase().replace('-', '');
                var r = [], d = new Uint8Array(buffer(data));
                for (var i = 0, n = d.length; i < n; i++) {
                    var c = d[i];
                    if (charset === 'utf8') {
                        c = c >= 0xfc && c < 0xfe && i + 5 < n ? // six bytes
                                (c - 0xfc) * 1073741824 + (d[++i] - 0x80 << 24) + (d[++i] - 0x80 << 18) + (d[++i] - 0x80 << 12) + (d[++i] - 0x80 << 6) + d[++i] - 0x80
                                : c >> 0xf8 && c < 0xfc && i + 4 < n ? // five bytes 
                                (c - 0xf8 << 24) + (d[++i] - 0x80 << 18) + (d[++i] - 0x80 << 12) + (d[++i] - 0x80 << 6) + d[++i] - 0x80
                                : c >> 0xf0 && c < 0xf8 && i + 3 < n ? // four bytes 
                                (c - 0xf0 << 18) + (d[++i] - 0x80 << 12) + (d[++i] - 0x80 << 6) + d[++i] - 0x80
                                : c >= 0xe0 && c < 0xf0 && i + 2 < n ? // three bytes 
                                (c - 0xe0 << 12) + (d[++i] - 0x80 << 6) + d[++i] - 0x80
                                : c >= 0xc0 && c < 0xe0 && i + 1 < n ? // two bytes 
                                (c - 0xc0 << 6) + d[++i] - 0x80
                                : c; // one byte 
                    } else if (charset === 'unicode' || charset === 'ucs2' || charset === 'utf16') {
                        c = (c << 8) + d[++i];
                        if (c >= 0xD800 && c < 0xE000) {
                            var first = (c - 0xD800) << 10;
                            c = d[++i];
                            c = (c << 8) + d[++i];
                            var second = c - 0xDC00;
                            c = first + second + 0x10000;
                        }
                    } else if (charset === 'utf32' || charset === 'ucs4') {
                        c = (c << 8) + d[++i];
                        c = (c << 8) + d[++i];
                        c = (c << 8) + d[++i];
                    } else if (charset === 'win1251') {
                        if (c >= 0x80) {
                            if (c >= 0xC0 && c < 0x100)
                                c += 0x350; // А..Яа..я
                            else
                                c = _win1251back_[c] || 0;
                        }
                    }
                    r.push(String.fromCharCode(c));
                }
                return r.join('');
            }
        };
    })();

    /**
     * Text string conversion
     * 
     * @memberOf GostCoding
     * @insnance
     * @type GostCoding.Chars
     */
    GostCoding.prototype.Chars = Chars;

    /**
     * HEX conversion
     * 
     * @class GostCoding.Hex
     */
    var Hex = {
        /**
         * Hex.decode(s, endean) convert HEX string s to CryptoOperationData in endean mode
         * 
         * @memberOf GostCoding.Hex
         * @param {string} s Hex encoded string
         * @param {boolean} endean Little or Big Endean, default Little
         * @returns {CryptoOperationData} Decoded binary data
         */
        decode: function (s, endean) {
            s = s.replace(/[^A-fa-f0-9]/g, '');
            var n = Math.ceil(s.length / 2), r = new Uint8Array(n);
            s = (s.length % 2 > 0 ? '0' : '') + s;
            if (endean && ((typeof endean !== 'string') ||
                    (endean.toLowerCase().indexOf('little') < 0)))
                for (var i = 0; i < n; i++)
                    r[i] = parseInt(s.substr((n - i - 1) * 2, 2), 16);
            else
                for (var i = 0; i < n; i++)
                    r[i] = parseInt(s.substr(i * 2, 2), 16);
            return r.buffer;
        },
        /**
         * Hex.encode(data, endean) convert CryptoOperationData data to HEX string in endean mode
         * 
         * @memberOf GostCoding.Hex 
         * @param {CryptoOperationData} data Binary data
         * @param {boolean} endean Little/Big Endean, default Little
         * @returns {string} Hex decoded string
         */
        encode: function (data, endean) {
            var s = [], d = new Uint8Array(buffer(data)), n = d.length;
            if (endean && ((typeof endean !== 'string') ||
                    (endean.toLowerCase().indexOf('little') < 0)))
                for (var i = 0; i < n; i++) {
                    var j = n - i - 1;
                    s[j] = (j > 0 && j % 32 === 0 ? '\r\n' : '') +
                            ('00' + d[i].toString(16)).slice(-2);
                }
            else
                for (var i = 0; i < n; i++)
                    s[i] = (i > 0 && i % 32 === 0 ? '\r\n' : '') +
                            ('00' + d[i].toString(16)).slice(-2);
            return s.join('');
        }
    };

    /**
     *  HEX conversion
     * @memberOf GostCoding
     * @insnance
     * @type GostCoding.Hex
     */
    GostCoding.prototype.Hex = Hex;

    /**
     * String hex-encoded integer conversion
     * 
     * @class GostCoding.Int16
     */
    var Int16 = {
        /**
         * Int16.decode(s) convert hex big insteger s to CryptoOperationData
         * 
         * @memberOf GostCoding.Int16 
         * @param {string} s Int16 string 
         * @returns {CryptoOperationData} Decoded binary data
         */
        decode: function (s) {
            s = (s || '').replace(/[^\-A-fa-f0-9]/g, '');
            if (s.length === 0)
                s = '0';
            // Signature
            var neg = false;
            if (s.charAt(0) === '-') {
                neg = true;
                s = s.substring(1);
            }
            // Align 2 chars
            while (s.charAt(0) === '0' && s.length > 1)
                s = s.substring(1);
            s = (s.length % 2 > 0 ? '0' : '') + s;
            // Padding for singanuture
            // '800000' - 'ffffff' - for positive
            // '800001' - 'ffffff' - for negative
            if ((!neg && !/^[0-7]/.test(s)) ||
                    (neg && !/^[0-7]|8[0]+$/.test(s)))
                s = '00' + s;
            // Convert hex
            var n = s.length / 2, r = new Uint8Array(n), t = 0;
            for (var i = n - 1; i >= 0; --i) {
                var c = parseInt(s.substr(i * 2, 2), 16);
                if (neg && (c + t > 0)) {
                    c = 256 - c - t;
                    t = 1;
                }
                r[i] = c;
            }
            return r.buffer;
        },
        /**
         * Int16.encode(data) convert CryptoOperationData data to big integer hex string
         * 
         * @memberOf GostCoding.Int16
         * @param {CryptoOperationData} data Binary data
         * @returns {string} Int16 encoded string
         */
        encode: function (data) {
            var d = new Uint8Array(buffer(data)), n = d.length;
            if (d.length === 0)
                return '0x00';
            var s = [], neg = d[0] > 0x7f, t = 0;
            for (var i = n - 1; i >= 0; --i) {
                var v = d[i];
                if (neg && (v + t > 0)) {
                    v = 256 - v - t;
                    t = 1;
                }
                s[i] = ('00' + v.toString(16)).slice(-2);
            }
            s = s.join('');
            while (s.charAt(0) === '0')
                s = s.substring(1);
            return (neg ? '-' : '') + '0x' + s;
        }
    };

    /**
     * String hex-encoded integer conversion
     * @memberOf GostCoding
     * @insnance
     * @type GostCoding.Int16
     */
    GostCoding.prototype.Int16 = Int16;

    /**
     * BER, DER, CER conversion
     * 
     * @class GostCoding.BER
     */
    var BER = (function () {

        // Predefenition block
        function encodeBER(source, format, onlyContent) {
            // Correct primitive type
            var object = source.object;
            if (object === undefined)
                object = source;

            // Determinate tagClass
            var tagClass = source.tagClass = source.tagClass || 0; // Universial default

            // Determinate tagNumber. Use only for Universal class
            if (tagClass === 0) {
                var tagNumber = source.tagNumber;
                if (typeof tagNumber === 'undefined') {
                    if (typeof object === 'string') {
                        if (object === '')   // NULL
                            tagNumber = 0x05;
                        else if (/^\-?0x[0-9a-fA-F]+$/.test(object)) // INTEGER
                            tagNumber = 0x02;
                        else if (/^(\d+\.)+\d+$/.test(object)) // OID
                            tagNumber = 0x06;
                        else if (/^[01]+$/.test(object)) // BIT STRING
                            tagNumber = 0x03;
                        else if (/^(true|false)$/.test(object)) // BOOLEAN
                            tagNumber = 0x01;
                        else if (/^[0-9a-fA-F]+$/.test(object)) // OCTET STRING
                            tagNumber = 0x04;
                        else
                            tagNumber = 0x13; // Printable string (later can be changed to UTF8String)
                    } else if (typeof object === 'number') { // INTEGER
                        tagNumber = 0x02;
                    } else if (typeof object === 'boolean') { // BOOLEAN
                        tagNumber = 0x01;
                    } else if (object instanceof Array) { // SEQUENCE
                        tagNumber = 0x10;
                    } else if (object instanceof Date) { // GeneralizedTime
                        tagNumber = 0x18;
                    } else if (object instanceof CryptoOperationData || (object && object.buffer instanceof CryptoOperationData)) {
                        tagNumber = 0x04;
                    } else
                        throw new DataError('Unrecognized type for ' + object);
                }
            }

            // Determinate constructed
            var tagConstructed = source.tagConstructed;
            if (typeof tagConstructed === 'undefined')
                tagConstructed = source.tagConstructed = object instanceof Array;

            // Create content
            var content;
            if (object instanceof CryptoOperationData || (object && object.buffer instanceof CryptoOperationData)) { // Direct
                content = new Uint8Array(buffer(object));
                if (tagNumber === 0x03) { // BITSTRING
                    // Set unused bits
                    var a = new Uint8Array(buffer(content));
                    content = new Uint8Array(a.length + 1);
                    content[0] = 0; // No unused bits
                    content.set(a, 1);
                }
            } else if (tagConstructed) { // Sub items coding
                if (object instanceof Array) {
                    var bytelen = 0, ba = [], offset = 0;
                    for (var i = 0, n = object.length; i < n; i++) {
                        ba[i] = encodeBER(object[i], format);
                        bytelen += ba[i].length;
                    }
                    if (tagNumber === 0x11)
                        ba.sort(function (a, b) { // Sort order for SET components
                            for (var i = 0, n = Math.min(a.length, b.length); i < n; i++) {
                                var r = a[i] - b[i];
                                if (r !== 0)
                                    return r;
                            }
                            return a.length - b.length;
                        });
                    if (format === 'CER') { // final for CER 00 00
                        ba[n] = new Uint8Array(2);
                        bytelen += 2;
                    }
                    content = new Uint8Array(bytelen);
                    for (var i = 0, n = ba.length; i < n; i++) {
                        content.set(ba[i], offset);
                        offset = offset + ba[i].length;
                    }
                } else
                    throw new DataError('Constracted block can\'t be primitive');
            } else {
                switch (tagNumber) {
                    // 0x00: // EOC
                    case 0x01: // BOOLEAN
                        content = new Uint8Array(1);
                        content[0] = object ? 0xff : 0;
                        break;
                    case 0x02: // INTEGER
                    case 0x0a: // ENUMIRATED
                        content = Int16.decode(
                                typeof object === 'number' ? object.toString(16) : object);
                        break;
                    case 0x03: // BIT STRING
                        if (typeof object === 'string') {
                            var unusedBits = 7 - (object.length + 7) % 8;
                            var n = Math.ceil(object.length / 8);
                            content = new Uint8Array(n + 1);
                            content[0] = unusedBits;
                            for (var i = 0; i < n; i++) {
                                var c = 0;
                                for (var j = 0; j < 8; j++) {
                                    var k = i * 8 + j;
                                    c = (c << 1) + (k < object.length ? (object.charAt(k) === '1' ? 1 : 0) : 0);
                                }
                                content[i + 1] = c;
                            }
                        }
                        break;
                    case 0x04:
                        content = Hex.decode(
                                typeof object === 'number' ? object.toString(16) : object);
                        break;
                        // case 0x05: // NULL
                    case 0x06: // OBJECT IDENTIFIER
                        var a = object.match(/\d+/g), r = [];
                        for (var i = 1; i < a.length; i++) {
                            var n = +a[i], r1 = [];
                            if (i === 1)
                                n = n + a[0] * 40;
                            do {
                                r1.push(n & 0x7F);
                                n = n >>> 7;
                            } while (n);
                            // reverse order
                            for (j = r1.length - 1; j >= 0; --j)
                                r.push(r1[j] + (j === 0 ? 0x00 : 0x80));
                        }
                        content = new Uint8Array(r);
                        break;
                        // case 0x07: // ObjectDescriptor
                        // case 0x08: // EXTERNAL
                        // case 0x09: // REAL
                        // case 0x0A: // ENUMERATED
                        // case 0x0B: // EMBEDDED PDV
                    case 0x0C: // UTF8String
                        content = Chars.decode(object, 'utf8');
                        break;
                        // case 0x10: // SEQUENCE
                        // case 0x11: // SET
                    case 0x12: // NumericString
                    case 0x16: // IA5String // ASCII
                    case 0x13: // PrintableString // ASCII subset
                    case 0x14: // TeletexString // aka T61String
                    case 0x15: // VideotexString
                    case 0x19: // GraphicString
                    case 0x1A: // VisibleString // ASCII subset
                    case 0x1B: // GeneralString
                        // Reflect on character encoding
                        for (var i = 0, n = object.length; i < n; i++)
                            if (object.charCodeAt(i) > 255)
                                tagNumber = 0x0C;
                        if (tagNumber === 0x0C)
                            content = Chars.decode(object, 'utf8');
                        else
                            content = Chars.decode(object, 'ascii');
                        break;
                    case 0x17: // UTCTime
                    case 0x18: // GeneralizedTime
                        var result = object.original;
                        if (!result) {
                            var date = new Date(object);
                            date.setMinutes(date.getMinutes() + date.getTimezoneOffset()); // to UTC
                            var ms = tagNumber === 0x18 ? date.getMilliseconds().toString() : ''; // Milliseconds, remove trailing zeros
                            while (ms.length > 0 && ms.charAt(ms.length - 1) === '0')
                                ms = ms.substring(0, ms.length - 1);
                            if (ms.length > 0)
                                ms = '.' + ms;
                            result = (tagNumber === 0x17 ? date.getYear().toString().slice(-2) : date.getFullYear().toString()) +
                                    ('00' + (date.getMonth() + 1)).slice(-2) +
                                    ('00' + date.getDate()).slice(-2) +
                                    ('00' + date.getHours()).slice(-2) +
                                    ('00' + date.getMinutes()).slice(-2) +
                                    ('00' + date.getSeconds()).slice(-2) + ms + 'Z';
                        }
                        content = Chars.decode(result, 'ascii');
                        break;
                    case 0x1C: // UniversalString
                        content = Chars.decode(object, 'utf32');
                        break;
                    case 0x1E: // BMPString
                        content = Chars.decode(object, 'utf16');
                        break;
                }
            }

            if (!content)
                content = new Uint8Array(0);
            if (content instanceof CryptoOperationData)
                content = new Uint8Array(content);

            if (!tagConstructed && format === 'CER') {
                // Encoding CER-form for string types
                var k;
                switch (tagNumber) {
                    case 0x03: // BIT_STRING
                        k = 1; // ingnore unused bit for bit string
                    case 0x04: // OCTET_STRING
                    case 0x0C: // UTF8String
                    case 0x12: // NumericString
                    case 0x13: // PrintableString
                    case 0x14: // TeletexString
                    case 0x15: // VideotexString
                    case 0x16: // IA5String
                    case 0x19: // GraphicString
                    case 0x1A: // VisibleString
                    case 0x1B: // GeneralString
                    case 0x1C: // UniversalString
                    case 0x1E: // BMPString
                        k = k || 0;
                        // Split content on 1000 octet len parts 
                        var size = 1000;
                        var bytelen = 0, ba = [], offset = 0;
                        for (var i = k, n = content.length; i < n; i += size - k) {
                            ba[i] = encodeBER({
                                object: new Unit8Array(content.buffer, i, Math.min(size - k, n - i)),
                                tagNumber: tagNumber,
                                tagClass: 0,
                                tagConstructed: false
                            }, format);
                            bytelen += ba[i].length;
                        }
                        ba[n] = new Uint8Array(2); // final for CER 00 00
                        bytelen += 2;
                        content = new Uint8Array(bytelen);
                        for (var i = 0, n = ba.length; i < n; i++) {
                            content.set(ba[i], offset);
                            offset = offset + ba[i].length;
                        }
                }
            }

            // Restore tagNumber for all classes
            if (tagClass === 0)
                source.tagNumber = tagNumber;
            else
                source.tagNumber = tagNumber = source.tagNumber || 0;
            source.content = content;

            if (onlyContent)
                return content;

            // Create header
            // tagNumber
            var ha = [], first = tagClass === 3 ? 0xC0 : tagClass === 2 ? 0x80 :
                    tagClass === 1 ? 0x40 : 0x00;
            if (tagConstructed)
                first |= 0x20;
            if (tagNumber < 0x1F) {
                first |= tagNumber & 0x1F;
                ha.push(first);
            } else {
                first |= 0x1F;
                ha.push(first);
                var n = tagNumber, ha1 = [];
                do {
                    ha1.push(n & 0x7F);
                    n = n >>> 7;
                } while (n)
                // reverse order
                for (var j = ha1.length - 1; j >= 0; --j)
                    ha.push(ha1[j] + (j === 0 ? 0x00 : 0x80));
            }
            // Length
            if (tagConstructed && format === 'CER') {
                ha.push(0x80);
            } else {
                var len = content.length;
                if (len > 0x7F) {
                    var l2 = len, ha2 = [];
                    do {
                        ha2.push(l2 & 0xff);
                        l2 = l2 >>> 8;
                    } while (l2);
                    ha.push(ha2.length + 0x80); // reverse order
                    for (var j = ha2.length - 1; j >= 0; --j)
                        ha.push(ha2[j]);
                } else {
                    // simple len
                    ha.push(len);
                }
            }
            var header = source.header = new Uint8Array(ha);

            // Result - complete buffer
            var block = new Uint8Array(header.length + content.length);
            block.set(header, 0);
            block.set(content, header.length);
            return block;
        }

        function decodeBER(source, offset) {

            // start pos
            var pos = offset || 0, start = pos;
            var tagNumber, tagClass, tagConstructed,
                    content, header, buffer, sub, len;

            if (source.object) {
                // Ready from source
                tagNumber = source.tagNumber;
                tagClass = source.tagClass;
                tagConstructed = source.tagConstructed;
                content = source.content;
                header = source.header;
                buffer = source.object instanceof CryptoOperationData ?
                        new Uint8Array(source.object) : null;
                sub = source.object instanceof Array ? source.object : null;
                len = buffer && buffer.length || null;
            } else {
                // Decode header
                var d = source;

                // Read tag
                var buf = d[pos++];
                tagNumber = buf & 0x1f;
                tagClass = buf >> 6;
                tagConstructed = (buf & 0x20) !== 0;
                if (tagNumber === 0x1f) { // long tag
                    tagNumber = 0;
                    do {
                        if (tagNumber > 0x1fffffffffff80)
                            throw new DataError('Convertor not supported tag number more then (2^53 - 1) at position ' + offset);
                        buf = d[pos++];
                        tagNumber = (tagNumber << 7) + (buf & 0x7f);
                    } while (buf & 0x80);
                }

                // Read len        
                buf = d[pos++];
                len = buf & 0x7f;
                if (len !== buf) {
                    if (len > 6) // no reason to use Int10, as it would be a huge buffer anyways
                        throw new DataError('Length over 48 bits not supported at position ' + offset);
                    if (len === 0)
                        len = null; // undefined
                    else {
                        buf = 0;
                        for (var i = 0; i < len; ++i)
                            buf = (buf << 8) + d[pos++];
                        len = buf;
                    }
                }

                start = pos;
                sub = null;

                if (tagConstructed) {
                    // must have valid content
                    sub = [];
                    if (len !== null) {
                        // definite length
                        var end = start + len;
                        while (pos < end) {
                            var s = decodeBER(d, pos);
                            sub.push(s);
                            pos += s.header.length + s.content.length;
                        }
                        if (pos !== end)
                            throw new DataError('Content size is not correct for container starting at offset ' + start);
                    } else {
                        // undefined length
                        try {
                            for (; ; ) {
                                var s = decodeBER(d, pos);
                                pos += s.header.length + s.content.length;
                                if (s.tagClass === 0x00 && s.tagNumber === 0x00)
                                    break;
                                sub.push(s);
                            }
                            len = pos - start;
                        } catch (e) {
                            throw new DataError('Exception ' + e + ' while decoding undefined length content at offset ' + start);
                        }
                    }
                }

                // Header and content
                header = new Uint8Array(d.buffer, offset, start - offset);
                content = new Uint8Array(d.buffer, start, len);
                buffer = content;
            }

            // Constructed types - check for string concationation
            if (sub !== null && tagClass === 0) {
                var k;
                switch (tagNumber) {
                    case 0x03: // BIT_STRING
                        k = 1; // ingnore unused bit for bit string
                    case 0x04: // OCTET_STRING
                    case 0x0C: // UTF8String
                    case 0x12: // NumericString
                    case 0x13: // PrintableString
                    case 0x14: // TeletexString
                    case 0x15: // VideotexString
                    case 0x16: // IA5String
                    case 0x19: // GraphicString
                    case 0x1A: // VisibleString
                    case 0x1B: // GeneralString
                    case 0x1C: // UniversalString
                    case 0x1E: // BMPString
                        k = k || 0;
                        // Concatination
                        if (sub.length === 0)
                            throw new DataError('No constructed encoding content of string type at offset ' + start);
                        len = k;
                        for (var i = 0, n = sub.length; i < n; i++) {
                            var s = sub[i];
                            if (s.tagClass !== tagClass || s.tagNumber !== tagNumber || s.tagConstructed)
                                throw new DataError('Invalid constructed encoding of string type at offset ' + start);
                            len += s.content.length - k;
                        }
                        buffer = new Uint8Array(len);
                        for (var i = 0, n = sub.length, j = k; i < n; i++) {
                            var s = sub[i];
                            if (k > 0)
                                buffer.set(s.content.subarray(1), j);
                            else
                                buffer.set(s.content, j);
                            j += s.content.length - k;
                        }
                        tagConstructed = false; // follow not required
                        sub = null;
                        break;
                }
            }
            // Primitive types
            var object = '';
            if (sub === null) {
                if (len === null)
                    throw new DataError('Invalid tag with undefined length at offset ' + start);

                if (tagClass === 0) {
                    switch (tagNumber) {
                        case 0x01: // BOOLEAN
                            object = buffer[0] !== 0;
                            break;
                        case 0x02: // INTEGER
                        case 0x0a: // ENUMIRATED
                            if (len > 6) {
                                object = Int16.encode(buffer);
                            } else {
                                var v = buffer[0];
                                if (buffer[0] > 0x7f)
                                    v = v - 256;
                                for (var i = 1; i < len; i++)
                                    v = v * 256 + buffer[i];
                                object = v;
                            }
                            break;
                        case 0x03: // BIT_STRING
                            if (len > 5) { // Content buffer
                                object = new Uint8Array(buffer.subarray(1)).buffer;
                            } else { // Max bit mask only for 32 bit
                                var unusedBit = buffer[0],
                                        skip = unusedBit, s = [];
                                for (var i = len - 1; i >= 1; --i) {
                                    var b = buffer[i];
                                    for (var j = skip; j < 8; ++j)
                                        s.push((b >> j) & 1 ? '1' : '0');
                                    skip = 0;
                                }
                                object = s.reverse().join('');
                            }
                            break;
                        case 0x04: // OCTET_STRING
                            object = new Uint8Array(buffer).buffer;
                            break;
                            //  case 0x05: // NULL
                        case 0x06: // OBJECT_IDENTIFIER
                            var s = '',
                                    n = 0,
                                    bits = 0;
                            for (var i = 0; i < len; ++i) {
                                var v = buffer[i];
                                n = (n << 7) + (v & 0x7F);
                                bits += 7;
                                if (!(v & 0x80)) { // finished
                                    if (s === '') {
                                        var m = n < 80 ? n < 40 ? 0 : 1 : 2;
                                        s = m + "." + (n - m * 40);
                                    } else
                                        s += "." + n.toString();
                                    n = 0;
                                    bits = 0;
                                }
                            }
                            if (bits > 0)
                                throw new DataError('Incompleted OID at offset ' + start);
                            object = s;
                            break;
                            //case 0x07: // ObjectDescriptor
                            //case 0x08: // EXTERNAL
                            //case 0x09: // REAL
                            //case 0x0A: // ENUMERATED
                            //case 0x0B: // EMBEDDED_PDV
                        case 0x10: // SEQUENCE
                        case 0x11: // SET
                            object = [];
                            break;
                        case 0x0C: // UTF8String
                            object = Chars.encode(buffer, 'utf8');
                            break;
                        case 0x12: // NumericString
                        case 0x13: // PrintableString
                        case 0x14: // TeletexString
                        case 0x15: // VideotexString
                        case 0x16: // IA5String
                        case 0x19: // GraphicString
                        case 0x1A: // VisibleString
                        case 0x1B: // GeneralString
                            object = Chars.encode(buffer, 'ascii');
                            break;
                        case 0x1C: // UniversalString
                            object = Chars.encode(buffer, 'utf32');
                            break;
                        case 0x1E: // BMPString
                            object = Chars.encode(buffer, 'utf16');
                            break;
                        case 0x17: // UTCTime
                        case 0x18: // GeneralizedTime
                            var shortYear = tagNumber === 0x17;
                            var s = Chars.encode(buffer, 'ascii'),
                                    m = (shortYear ?
                                            /^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/ :
                                            /^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/).exec(s);
                            if (!m)
                                throw new DataError('Unrecognized time format "' + s + '" at offset ' + start);
                            if (shortYear) {
                                // Where YY is greater than or equal to 50, the year SHALL be interpreted as 19YY; and
                                // Where YY is less than 50, the year SHALL be interpreted as 20YY                                
                                m[1] = +m[1];
                                m[1] += (m[1] < 50) ? 2000 : 1900;
                            }
                            var dt = new Date(m[1], +m[2] - 1, +m[3], +(m[4] || '0'), +(m[5] || '0'), +(m[6] || '0'), +(m[7] || '0')),
                                    tz = dt.getTimezoneOffset();
                            if (m[8] || tagNumber === 0x17) {
                                if (m[8].toUpperCase() !== 'Z' && m[9]) {
                                    tz = tz + parseInt(m[9]);
                                }
                                dt.setMinutes(dt.getMinutes() - tz);
                            }
                            dt.original = s;
                            object = dt;
                            break;
                    }
                } else // OCTET_STRING
                    object = new Uint8Array(buffer).buffer;
            } else
                object = sub;

            // result
            return {
                tagConstructed: tagConstructed,
                tagClass: tagClass,
                tagNumber: tagNumber,
                header: header,
                content: content,
                object: object
            };
        }

        return {
            /**
             * BER.decode(object, format) convert javascript object to ASN.1 format CryptoOperationData<br><br>
             * If object has members tagNumber, tagClass and tagConstructed
             * it is clear define encoding rules. Else method use defaul rules:
             * <ul>
             *   <li>Empty string or null - NULL</li>
             *   <li>String starts with '0x' and has 0-9 and a-f characters - INTEGER</li>
             *   <li>String like d.d.d.d (d - set of digits) - OBJECT IDENTIFIER</li>
             *   <li>String with characters 0 and 1 - BIT STRING</li>
             *   <li>Strings 'true' or 'false' - BOOLEAN</li>
             *   <li>String has only 0-9 and a-f characters - OCTET STRING</li>
             *   <li>String has only characters with code 0-255 - PrintableString</li>
             *   <li>Other strings - UTF8String</li>
             *   <li>Number - INTEGER</li>
             *   <li>Date - GeneralizedTime</li>
             *   <li>Boolean - SEQUENCE</li>
             *   <li>CryptoOperationData - OCTET STRING</li>
             * </ul>
             * SEQUENCE or SET arrays recursively encoded for each item.<br>
             * OCTET STRING and BIT STRING can presents as array with one item. 
             * It means encapsulates encoding for child element.<br>
             * 
             * If CONTEXT or APPLICATION classes item presents as array with one 
             * item we use EXPLICIT encoding for element, else IMPLICIT encoding.<br>
             * 
             * @memberOf GostCoding.BER
             * @param {Object} object Object to encoding
             * @param {string} format Encoding rule: 'DER' or 'CER', default 'DER'
             * @param {boolean} onlyContent Encode content only, without header
             * @returns {CryptoOperationData} BER encoded data
             */
            encode: function (object, format, onlyContent) {
                return encodeBER(object, format, onlyContent).buffer;
            },
            /**
             * BER.encode(data) convert ASN.1 format CryptoOperationData data to javascript object<br><br>
             * 
             * Conversion rules to javascript object:
             *  <ul>
             *      <li>BOOLEAN - Boolean object</li>
             *      <li>INTEGER, ENUMIRATED - Integer object if len <= 6 (48 bits) else Int16 encoded string</li>
             *      <li>BIT STRING - Integer object if len <= 5 (w/o unsedBit octet - 32 bits) else String like '10111100' or  Array with one item in case of incapsulates encoding</li>
             *      <li>OCTET STRING - Hex encoded string or Array with one item in case of incapsulates encoding</li>
             *      <li>OBJECT IDENTIFIER - String with object identifier</li>
             *      <li>SEQUENCE, SET - Array of encoded items</li>
             *      <li>UTF8String, NumericString, PrintableString, TeletexString, VideotexString, 
             *          IA5String, GraphicString, VisibleString, GeneralString, UniversalString,
             *          BMPString - encoded String</li>
             *      <li>UTCTime, GeneralizedTime - Date</li>
             *  </ul>
             * @memberOf GostCoding.BER
             * @param {(CryptoOperationData|GostCoding.BER)} data Binary data to decode
             * @returns {Object} Javascript object with result of decoding
             */
            decode: function (data) {
                return decodeBER(data.object ? data : new Uint8Array(buffer(data)), 0);
            }
        };
    })();

    /**
     * BER, DER, CER conversion
     * @memberOf GostCoding
     * @insnance
     * @type GostCoding.BER
     */
    GostCoding.prototype.BER = BER;

    /**
     * PEM conversion
     * @class GostCoding.PEM
     */
    var PEM = {
        /**
         * PEM.encode(data, name) encode CryptoOperationData to PEM format with name label
         * 
         * @memberOf GostCoding.PEM
         * @param {(Object|CryptoOperationData)} data Java script object or BER-encoded binary data
         * @param {string} name Name of PEM object: 'certificate', 'private key' etc.
         * @returns {string} Encoded object
         */
        encode: function (data, name) {
            return (name ? '-----BEGIN ' + name.toUpperCase() + '-----\r\n' : '') +
                    Base64.encode(data instanceof CryptoOperationData ? data : BER.encode(data)) +
                    (name ? '\r\n-----END ' + name.toUpperCase() + '-----' : '');
        },
        /**
         * PEM.decode(s, name, deep) decode PEM format s labeled name to CryptoOperationData or javascript object in according to deep parameter
         * 
         * @memberOf GostCoding.PEM
         * @param {string} s PEM encoded string
         * @param {string} name Name of PEM object: 'certificate', 'private key' etc.
         * @param {boolean} deep If true method do BER-decoding, else only BASE64 decoding
         * @param {integer} index Index of decoded value
         * @returns {(Object|CryptoOperationData)} Decoded javascript object if deep=true, else CryptoOperationData for father BER decoding
         */
        decode: function (s, name, deep, index) {
            // Try clear base64
            var re1 = /([A-Za-z0-9\+\/\s\=]+)/g,
                    valid = re1.exec(s);
            if (valid[1].length !== s.length)
                valid = false;
            if (!valid && name) {
                // Try with the name
                var re2 = new RegExp(
                        '-----\\s?BEGIN ' + name.toUpperCase() +
                        '-----([A-Za-z0-9\\+\\/\\s\\=]+)-----\\s?END ' +
                        name.toUpperCase() + '-----', 'g');
                valid = re2.exec(s);
            }
            if (!valid) {
                // Try with some name
                var re3 = new RegExp(
                        '-----\\s?BEGIN [A-Z0-9\\s]+' +
                        '-----([A-Za-z0-9\\+\\/\\s\\=]+)-----\\s?END ' +
                        '[A-Z0-9\\s]+-----', 'g');
                valid = re3.exec(s);
            }
            var r = valid && valid[1 + (index || 0)];
            if (!r)
                throw new DataError('Not valid PEM format');
            var out = Base64.decode(r);
            if (deep)
                out = BER.decode(out);
            return out;
        }
    };

    /**
     * PEM conversion
     * @memberOf GostCoding
     * @insnance
     * @type GostCoding.PEM
     */
    GostCoding.prototype.PEM = PEM;

    if (gostCrypto)
        /**
         * Coding algorithms: Base64, Hex, Int16, Chars, BER and PEM
         * 
         * @memberOf gostCrypto
         * @type GostCoding
         */
        gostCrypto.coding = new GostCoding();

module.exports = GostCoding;


/***/ }),

/***/ "./node_modules/node-gost-crypto/lib/gostCrypto.js":
/*!*********************************************************!*\
  !*** ./node_modules/node-gost-crypto/lib/gostCrypto.js ***!
  \*********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

/**
 * @file Implementation Web Crypto interfaces for GOST algorithms
 * @version 1.76
 * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved.
 */

/* 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *    
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

const GostRandom = __webpack_require__(/*! ./gostRandom */ "./node_modules/node-gost-crypto/lib/gostRandom.js");
const gostEngine = __webpack_require__(/*! ./gostEngine */ "./node_modules/node-gost-crypto/lib/gostEngine.js");

    /*
     * Algorithm normalization
     * 
     */

    var root = __webpack_require__.g;
    var rootCrypto = root.crypto || root.msCrypto;

    var SyntaxError = root.SyntaxError || root.Error,
            DataError = root.DataError || root.Error,
            NotSupportedError = root.NotSupportedError || root.Error,
            OperationError = root.OperationError || root.Error,
            InvalidStateError = root.InvalidAccessError || root.Error,
            InvalidAccessError = root.InvalidAccessError || root.Error;

    // Normalize algorithm
    function normalize(algorithm, method) {
        if (typeof algorithm === 'string' || algorithm instanceof String)
            algorithm = {name: algorithm};
        var name = algorithm.name;
        if (!name)
            throw new SyntaxError('Algorithm name not defined');
        // Extract algorithm modes from name
        var modes = name.split('/'), modes = modes[0].split('-').concat(modes.slice(1));
        // Normalize the name with default modes
        var na = {};
        name = modes[0].replace(/[\.\s]/g, '');
        modes = modes.slice(1);
        if (name.indexOf('28147') >= 0) {
            na = {
                name: 'GOST 28147',
                version: 1989,
                mode: (algorithm.mode || (// ES, MAC, KW
                        (method === 'sign' || method === 'verify') ? 'MAC' :
                        (method === 'wrapKey' || method === 'unwrapKey') ? 'KW' : 'ES')).toUpperCase(),
                length: algorithm.length || 64
            };
        } else if (name.indexOf('3412') >= 0) {
            na = {
                name: 'GOST R 34.12',
                version: 2015,
                mode: (algorithm.mode || (// ES, MAC, KW
                        (method === 'sign' || method === 'verify') ? 'MAC' :
                        (method === 'wrapKey' || method === 'unwrapKey') ? 'KW' : 'ES')).toUpperCase(),
                length: algorithm.length || 64 // 128
            };
        } else if (name.indexOf('3411') >= 0) {
            na = {
                name: 'GOST R 34.11',
                version: 2012, // 1994
                mode: (algorithm.mode || (// HASH, KDF, HMAC, PBKDF2, PFXKDF, CPKDF
                        (method === 'deriveKey' || method === 'deriveBits') ? 'KDF' :
                        (method === 'sign' || method === 'verify') ? 'HMAC' : 'HASH')).toUpperCase(),
                length: algorithm.length || 256 // 512
            };
        } else if (name.indexOf('3410') >= 0) {
            na = {
                name: 'GOST R 34.10',
                version: 2012, // 1994, 2001
                mode: (algorithm.mode || (// SIGN, DH, MASK
                        (method === 'deriveKey' || method === 'deriveBits') ? 'DH' : 'SIGN')).toUpperCase(),
                length: algorithm.length || 256 // 512
            };
        } else if (name.indexOf('SHA') >= 0) {
            na = {
                name: 'SHA',
                version: (algorithm.length || 160) === 160 ? 1 : 2, // 1, 2
                mode: (algorithm.mode || (// HASH, KDF, HMAC, PBKDF2, PFXKDF
                        (method === 'deriveKey' || method === 'deriveBits') ? 'KDF' :
                        (method === 'sign' || method === 'verify') ? 'HMAC' : 'HASH')).toUpperCase(),
                length: algorithm.length || 160
            };
        } else if (name.indexOf('RC2') >= 0) {
            na = {
                name: 'RC2',
                version: 1,
                mode: (algorithm.mode || (// ES, MAC, KW
                        (method === 'sign' || method === 'verify') ? 'MAC' :
                        (method === 'wrapKey' || method === 'unwrapKey') ? 'KW' : 'ES')).toUpperCase(),
                length: algorithm.length || 32 // 1 - 1024
            };
        } else if (name.indexOf('PBKDF2') >= 0) {
            na = normalize(algorithm.hash, 'digest');
            na.mode = 'PBKDF2';
        } else if (name.indexOf('PFXKDF') >= 0) {
            na = normalize(algorithm.hash, 'digest');
            na.mode = 'PFXKDF';
        } else if (name.indexOf('CPKDF') >= 0) {
            na = normalize(algorithm.hash, 'digest');
            na.mode = 'CPKDF';
        } else if (name.indexOf('HMAC') >= 0) {
            na = normalize(algorithm.hash, 'digest');
            na.mode = 'HMAC';
        } else
            throw new NotSupportedError('Algorithm not supported');

        // Compile modes
        modes.forEach(function (mode) {
            mode = mode.toUpperCase();
            if (/^[0-9]+$/.test(mode)) {
                if ((['8', '16', '32'].indexOf(mode) >= 0) || (na.length === '128' && mode === '64')) { // Shift bits
                    if (na.mode === 'ES')
                        na.shiftBits = parseInt(mode);
                    else if (na.mode === 'MAC')
                        na.macLength = parseInt(mode);
                    else
                        throw new NotSupportedError('Algorithm ' + na.name + ' mode ' + mode + ' not supported');
                } else if (['89', '94', '01', '12', '15', '1989', '1994', '2001', '2012', '2015'].indexOf(mode) >= 0) { // GOST Year
                    var version = parseInt(mode);
                    version = version < 1900 ? (version < 80 ? 2000 + version : 1900 + version) : version;
                    na.version = version;
                } else if (['1'].indexOf(mode) >= 0 && na.name === 'SHA') { // SHA-1
                    na.version = 1;
                    na.length = 160;
                } else if (['256', '384', '512'].indexOf(mode) >= 0 && na.name === 'SHA') { // SHA-2
                    na.version = 2;
                    na.length = parseInt(mode);
                } else if (['40', '128'].indexOf(mode) >= 0 && na.name === 'RC2') { // RC2
                    na.version = 1;
                    na.length = parseInt(mode); // key size
                } else if (['64', '128', '256', '512'].indexOf(mode) >= 0) // block size
                    na.length = parseInt(mode);
                else if (['1000', '2000'].indexOf(mode) >= 0) // Iterations
                    na.iterations = parseInt(mode);
                // Named Paramsets
            } else if (['E-TEST', 'E-A', 'E-B', 'E-C', 'E-D', 'E-SC', 'E-Z', 'D-TEST', 'D-A', 'D-SC'].indexOf(mode) >= 0) {
                na.sBox = mode;
            } else if (['S-TEST', 'S-A', 'S-B', 'S-C', 'S-D', 'X-A', 'X-B', 'X-C'].indexOf(mode) >= 0) {
                na.namedParam = mode;
            } else if (['S-256-TEST', 'S-256-A', 'S-256-B', 'S-256-C', 'P-256', 'T-512-TEST', 'T-512-A',
                'T-512-B', 'X-256-A', 'X-256-B', 'T-256-TEST', 'T-256-A', 'T-256-B', 'S-256-B', 'T-256-C', 'S-256-C'].indexOf(mode) >= 0) {
                na.namedCurve = mode;
            } else if (['SC', 'CP', 'VN'].indexOf(mode) >= 0) {
                na.procreator = mode;

                // Encription GOST 28147 or GOST R 34.12
            } else if (na.name === 'GOST 28147' || na.name === 'GOST R 34.12' || na.name === 'RC2') {
                if (['ES', 'MAC', 'KW', 'MASK'].indexOf(mode) >= 0) {
                    na.mode = mode;
                } else if (['ECB', 'CFB', 'OFB', 'CTR', 'CBC'].indexOf(mode) >= 0) {
                    na.mode = 'ES';
                    na.block = mode;
                } else if (['CPKW', 'NOKW', 'SCKW'].indexOf(mode) >= 0) {
                    na.mode = 'KW';
                    na.keyWrapping = mode.replace('KW', '');
                } else if (['ZEROPADDING', 'PKCS5PADDING', 'NOPADDING', 'RANDOMPADDING', 'BITPADDING'].indexOf(mode) >= 0) {
                    na.padding = mode.replace('PADDING', '');
                } else if (['NOKM', 'CPKM'].indexOf(mode) >= 0) {
                    na.keyMeshing = mode.replace('KM', '');
                } else
                    throw new NotSupportedError('Algorithm ' + na.name + ' mode ' + mode + ' not supported');

                // Digesting GOST 34.11
            } else if (na.name === 'GOST R 34.11' || na.name === 'SHA') {
                if (['HASH', 'KDF', 'HMAC', 'PBKDF2', 'PFXKDF', 'CPKDF'].indexOf(mode) >= 0)
                    na.mode = mode;
                else
                    throw new NotSupportedError('Algorithm ' + na.name + ' mode ' + mode + ' not supported');

                // Signing GOST 34.10
            } else if (na.name === 'GOST R 34.10') {
                var hash = mode.replace(/[\.\s]/g, '');
                if (hash.indexOf('GOST') >= 0 && hash.indexOf('3411') >= 0)
                    na.hash = mode;
                else if (['SIGN', 'DH', 'MASK'].indexOf(mode))
                    na.mode = mode;
                else
                    throw new NotSupportedError('Algorithm ' + na.name + ' mode ' + mode + ' not supported');
            }
        });

        // Procreator
        na.procreator = algorithm.procreator || na.procreator || 'CP';

        // Key size
        switch (na.name) {
            case 'GOST R 34.10':
                na.keySize = na.length / (na.version === 1994 ? 4 : 8);
                break;
            case 'GOST R 34.11':
                na.keySize = 32;
                break;
            case 'GOST 28147':
            case 'GOST R 34.12':
                na.keySize = 32;
                break;
            case 'RC2':
                na.keySize = Math.ceil(na.length / 8);
                break;
            case 'SHA':
                na.keySize = na.length / 8;
                break;
        }

        // Encrypt additional modes 
        if (na.mode === 'ES') {
            if (algorithm.block)
                na.block = algorithm.block; // ECB, CFB, OFB, CTR, CBC
            if (na.block)
                na.block = na.block.toUpperCase();
            if (algorithm.padding)
                na.padding = algorithm.padding; // NO, ZERO, PKCS5, RANDOM, BIT
            if (na.padding)
                na.padding = na.padding.toUpperCase();
            if (algorithm.shiftBits)
                na.shiftBits = algorithm.shiftBits; // 8, 16, 32, 64
            if (algorithm.keyMeshing)
                na.keyMeshing = algorithm.keyMeshing; // NO, CP
            if (na.keyMeshing)
                na.keyMeshing = na.keyMeshing.toUpperCase();
            // Default values
            if (method !== 'importKey' && method !== 'generateKey') {
                na.block = na.block || 'ECB';
                na.padding = na.padding || (na.block === 'CBC' || na.block === 'ECB' ? 'ZERO' : 'NO');
                if (na.block === 'CFB' || na.block === 'OFB')
                    na.shiftBits = na.shiftBits || na.length;
                na.keyMeshing = na.keyMeshing || 'NO';
            }
        }
        if (na.mode === 'KW') {
            if (algorithm.keyWrapping)
                na.keyWrapping = algorithm.keyWrapping; // NO, CP, SC
            if (na.keyWrapping)
                na.keyWrapping = na.keyWrapping.toUpperCase();
            if (method !== 'importKey' && method !== 'generateKey')
                na.keyWrapping = na.keyWrapping || 'NO';
        }

        // Paramsets
        ['sBox', 'namedParam', 'namedCurve', 'curve', 'param', 'modulusLength'].forEach(function (name) {
            algorithm[name] && (na[name] = algorithm[name]);
        });
        // Default values
        if (method !== 'importKey' && method !== 'generateKey') {
            if (na.name === 'GOST 28147') {
                na.sBox = na.sBox || (na.procreator === 'SC' ? 'E-SC' : 'E-A'); // 'E-A', 'E-B', 'E-C', 'E-D', 'E-SC'
            } else if (na.name === 'GOST R 34.12' && na.length === 64) {
                na.sBox = 'E-Z';
            } else if (na.name === 'GOST R 34.11' && na.version === 1994) {
                na.sBox = na.sBox || (na.procreator === 'SC' ? 'D-SC' : 'D-A'); // 'D-SC'
            } else if (na.name === 'GOST R 34.10' && na.version === 1994) {
                na.namedParam = na.namedParam || (na.mode === 'DH' ? 'X-A' : 'S-A'); // 'S-B', 'S-C', 'S-D', 'X-B', 'X-C'
            } else if (na.name === 'GOST R 34.10' && na.version === 2001) {
                na.namedCurve = na.namedCurve || (na.length === 256 ?
                        na.procreator === 'SC' ? 'P-256' : (na.mode === 'DH' ? 'X-256-A' : 'S-256-A') : // 'S-256-B', 'S-256-C', 'X-256-B', 'T-256-A', 'T-256-B', 'T-256-C', 'P-256'
                        na.mode === 'T-512-A'); // 'T-512-B', 'T-512-C'
            } else if (na.name === 'GOST R 34.10' && na.version === 2012) {
                na.namedCurve = na.namedCurve || (na.length === 256 ?
                        na.procreator === 'SC' ? 'P-256' : (na.mode === 'DH' ? 'X-256-A' : 'S-256-A') : // 'S-256-B', 'S-256-C', 'X-256-B', 'T-256-A', 'T-256-B', 'T-256-C', 'P-256'
                        na.mode === 'T-512-A'); // 'T-512-B', 'T-512-C'
            }
        }

        // Vectors
        switch (na.mode) {
            case 'DH':
                algorithm.ukm && (na.ukm = algorithm.ukm);
                algorithm['public'] && (na['public'] = algorithm['public']);
                break;
            case 'SIGN':
            case 'KW':
                algorithm.ukm && (na.ukm = algorithm.ukm);
                break;
            case 'ES':
            case 'MAC':
                algorithm.iv && (na.iv = algorithm.iv);
                break;
            case 'KDF':
                algorithm.label && (na.label = algorithm.label);
                algorithm.contex && (na.context = algorithm.contex);
                break;
            case 'PBKDF2':
                algorithm.salt && (na.salt = algorithm.salt);
                algorithm.iterations && (na.iterations = algorithm.iterations);
                algorithm.diversifier && (na.diversifier = algorithm.diversifier);
                break;
            case 'PFXKDF':
                algorithm.salt && (na.salt = algorithm.salt);
                algorithm.iterations && (na.iterations = algorithm.iterations);
                algorithm.diversifier && (na.diversifier = algorithm.diversifier);
                break;
            case 'CPKDF':
                algorithm.salt && (na.salt = algorithm.salt);
                algorithm.iterations && (na.iterations = algorithm.iterations);
                break;
        }

        // Verification method and modes
        if (method && (
                ((na.mode !== 'ES' && na.mode !== 'SIGN' && na.mode !== 'MAC' &&
                        na.mode !== 'HMAC' && na.mode !== 'KW' && na.mode !== 'DH'
                        && na.mode !== 'MASK') &&
                        (method === 'generateKey')) ||
                ((na.mode !== 'ES') &&
                        (method === 'encrypt' || method === 'decrypt')) ||
                ((na.mode !== 'SIGN' && na.mode !== 'MAC' && na.mode !== 'HMAC') &&
                        (method === 'sign' || method === 'verify')) ||
                ((na.mode !== 'HASH') &&
                        (method === 'digest')) ||
                ((na.mode !== 'KW' && na.mode !== 'MASK') &&
                        (method === 'wrapKey' || method === 'unwrapKey')) ||
                ((na.mode !== 'DH' && na.mode !== 'PBKDF2' && na.mode !== 'PFXKDF' &&
                        na.mode !== 'CPKDF' && na.mode !== 'KDF') &&
                        (method === 'deriveKey' || method === 'deriveBits'))))
            throw new NotSupportedError('Algorithm mode ' + na.mode + ' not valid for method ' + method);

        // Normalize hash algorithm
        algorithm.hash && (na.hash = algorithm.hash);
        if (na.hash) {
            if ((typeof na.hash === 'string' || na.hash instanceof String)
                    && na.procreator)
                na.hash = na.hash + '/' + na.procreator;
            na.hash = normalize(na.hash, 'digest');
        }

        // Algorithm object identirifer
        algorithm.id && (na.id = algorithm.id);

        return na;
    }

    // Check for possibility use native crypto.subtle
    function checkNative(algorithm) {
        if (!rootCrypto || !rootCrypto.subtle || !algorithm)
            return false;
        // Prepare name
        var name = (typeof algorithm === 'string' || algorithm instanceof String) ?
                name = algorithm : algorithm.name;
        if (!name)
            return false;
        name = name.toUpperCase();
        // Digest algorithm for key derivation
        if ((name.indexOf('KDF') >= 0 || name.indexOf('HMAC') >= 0) && algorithm.hash)
            return checkNative(algorithm.hash);
        // True if no supported names
        return name.indexOf('GOST') === -1 &&
                name.indexOf('SHA-1') === -1 &&
                name.indexOf('RC2') === -1 &&
                name.indexOf('?DES') === -1;
    }


    /*
     * Key conversion methods
     * 
     */

    // Check key parameter
    function checkKey(key, method) {
        if (!key.algorithm)
            throw new SyntaxError('Key algorithm not defined');

        if (!key.algorithm.name)
            throw new SyntaxError('Key algorithm name not defined');

        var name = key.algorithm.name,
                gostCipher = name === 'GOST 28147' || name === 'GOST R 34.12' || name === 'RC2',
                gostDigest = name === 'GOST R 34.11' || name === 'SHA',
                gostSign = name === 'GOST R 34.10';

        if (!gostCipher && !gostSign && !gostDigest)
            throw new NotSupportedError('Key algorithm ' + name + ' is unsupproted');

        if (!key.type)
            throw new SyntaxError('Key type not defined');

        if (((gostCipher || gostDigest) && key.type !== 'secret') ||
                (gostSign && !(key.type === 'public' || key.type === 'private')))
            throw new DataError('Key type ' + key.type + ' is not valid for algorithm ' + name);

        if (!key.usages || !key.usages.indexOf)
            throw new SyntaxError('Key usages not defined');

        for (var i = 0, n = key.usages.length; i < n; i++) {
            var md = key.usages[i];
            if (((md === 'encrypt' || md === 'decrypt') && key.type !== 'secret') ||
                    (md === 'sign' && key.type === 'public') ||
                    (md === 'verify' && key.type === 'private'))
                throw new InvalidStateError('Key type ' + key.type + ' is not valid for ' + md);
        }

        if (method)
            if (key.usages.indexOf(method) === -1)
                throw new InvalidAccessError('Key usages is not contain method ' + method);

        if (!key.buffer)
            throw new SyntaxError('Key buffer is not defined');

        var size = key.buffer.byteLength * 8, keySize = 8 * key.algorithm.keySize;
        if ((key.type === 'secret' && size !== (keySize || 256) &&
                (key.usages.indexOf('encrypt') >= 0 || key.usages.indexOf('decrypt') >= 0)) ||
                (key.type === 'private' && !(size === 256 || size === 512)) ||
                (key.type === 'public' && !(size === 512 || size === 1024)))
            throw new SyntaxError('Key buffer has wrong size ' + size + ' bit');
    }

    // Extract key and enrich cipher algorithm
    function extractKey(method, algorithm, key) {
        checkKey(key, method);
        if (algorithm) {
            var params;
            switch (algorithm.mode) {
                case 'ES':
                    params = ['sBox', 'keyMeshing', 'padding', 'block'];
                    break;
                case 'SIGN':
                    params = ['namedCurve', 'namedParam', 'sBox', 'curve', 'param', 'modulusLength'];
                    break;
                case 'MAC':
                    params = ['sBox'];
                    break;
                case 'KW':
                    params = ['keyWrapping', 'ukm'];
                    break;
                case 'DH':
                    params = ['namedCurve', 'namedParam', 'sBox', 'ukm', 'curve', 'param', 'modulusLength'];
                    break;
                case 'KDF':
                    params = ['context', 'label'];
                    break;
                case 'PBKDF2':
                    params = ['sBox', 'iterations', 'salt'];
                    break;
                case 'PFXKDF':
                    params = ['sBox', 'iterations', 'salt', 'diversifier'];
                    break;
                case 'CPKDF':
                    params = ['sBox', 'salt'];
                    break;
            }
            if (params)
                params.forEach(function (name) {
                    key.algorithm[name] && (algorithm[name] = key.algorithm[name]);
                });
        }
        return key.buffer;
    }

    // Make key definition
    function convertKey(algorithm, extractable, keyUsages, keyData, keyType) {
        var key = {
            type: keyType || (algorithm.name === 'GOST R 34.10' ? 'private' : 'secret'),
            extractable: extractable || 'false',
            algorithm: algorithm,
            usages: keyUsages || [],
            buffer: keyData
        };
        checkKey(key);
        return key;
    }

    function convertKeyPair(publicAlgorithm, privateAlgorithm, extractable, keyUsages, publicBuffer, privateBuffer) {

        if (!keyUsages || !keyUsages.indexOf)
            throw new SyntaxError('Key usages not defined');

        var publicUsages = keyUsages.filter(function (value) {
            return value !== 'sign';
        });
        var privateUsages = keyUsages.filter(function (value) {
            return value !== 'verify';
        });

        return {
            publicKey: convertKey(publicAlgorithm, extractable, publicUsages, publicBuffer, 'public'),
            privateKey: convertKey(privateAlgorithm, extractable, privateUsages, privateBuffer, 'private')
        };
    }

    // Swap bytes in buffer
    function swapBytes(src) {
        if (src instanceof CryptoOperationData)
            src = new Uint8Array(src);
        var dst = new Uint8Array(src.length);
        for (var i = 0, n = src.length; i < n; i++)
            dst[n - i - 1] = src[i];
        return dst.buffer;
    }


    /**
     * Promise stub object (not fulfill specification, only for internal use)
     * Class not defined if Promise class already defined in root context<br><br>
     * 
     * The Promise object is used for deferred and asynchronous computations. A Promise is in one of the three states:
     *  <ul>
     *      <li>pending: initial state, not fulfilled or rejected.</li>
     *      <li>fulfilled: successful operation</li>
     *      <li>rejected: failed operation.</li>
     *  </ul>
     * Another term describing the state is settled: the Promise is either fulfilled or rejected, but not pending.<br><br>
     * @class Promise
     * @global
     * @param {function} executor Function object with two arguments resolve and reject. 
     * The first argument fulfills the promise, the second argument rejects it. 
     * We can call these functions, once our operation is completed.
     */
    if (!root.Promise) {

        root.Promise = (function () {

            function mswrap(value) {
                if (value && value.oncomplete === null && value.onerror === null) {
                    return new Promise(function (resolve, reject) {
                        value.oncomplete = function () {
                            resolve(value.result);
                        };
                        value.onerror = function () {
                            reject(new OperationError(value.toString()));
                        };
                    });
                } else
                    return value;
            }

            function Promise(executor) {

                var state = 'pending', result,
                        resolveQueue = [], rejectQueue = [];

                function call(callback) {
                    try {
                        callback();
                    } catch (e) {
                    }
                }

                try {
                    executor(function (value) {
                        if (state === 'pending') {
                            state = 'fulfilled';
                            result = value;
                            resolveQueue.forEach(call);
                        }
                    }, function (reason) {
                        if (state === 'pending') {
                            state = 'rejected';
                            result = reason;
                            rejectQueue.forEach(call);
                        }
                    });
                } catch (error) {
                    if (state === 'pending') {
                        state = 'rejected';
                        result = error;
                        rejectQueue.forEach(call);
                    }
                }
                /**
                 * The then() method returns a Promise. It takes two arguments, both are 
                 * callback functions for the success and failure cases of the Promise.
                 * 
                 * @method then
                 * @memberOf Promise
                 * @instance
                 * @param {function} onFulfilled A Function called when the Promise is fulfilled. This function has one argument, the fulfillment value.
                 * @param {function} onRejected A Function called when the Promise is rejected. This function has one argument, the rejection reason.
                 * @returns {Promise} 
                 */
                this.then = function (onFulfilled, onRejected) {

                    return new Promise(function (resolve, reject) {

                        function asyncOnFulfilled() {
                            var value;
                            try {
                                value = onFulfilled ? onFulfilled(result) : result;
                            } catch (error) {
                                reject(error);
                                return;
                            }
                            value = mswrap(value);
                            if (value && value.then && value.then.call) {
                                value.then(resolve, reject);
                            } else {
                                resolve(value);
                            }
                        }

                        function asyncOnRejected() {
                            var reason;
                            try {
                                reason = onRejected ? onRejected(result) : result;
                            } catch (error) {
                                reject(error);
                                return;
                            }
                            reason = mswrap(reason);
                            if (reason && reason.then && reason.then.call) {
                                reason.then(resolve, reject);
                            } else {
                                reject(reason);
                            }
                        }

                        if (state === 'fulfilled') {
                            asyncOnFulfilled();
                        } else if (state === 'rejected') {
                            asyncOnRejected();
                        } else {
                            resolveQueue.push(asyncOnFulfilled);
                            rejectQueue.push(asyncOnRejected);
                        }

                    });

                };
                /**
                 * The catch() method returns a Promise and deals with rejected cases only. 
                 * It behaves the same as calling Promise.prototype.then(undefined, onRejected).
                 * 
                 * @method catch
                 * @memberOf Promise
                 * @instance
                 * @param {function} onRejected A Function called when the Promise is rejected. This function has one argument, the rejection reason.
                 * @returns {Promise} 
                 */
                this['catch'] = function (onRejected) {
                    return this.then(undefined, onRejected);
                };
            }

            /**
             * The Promise.all(iterable) method returns a promise that resolves when all 
             * of the promises in the iterable argument have resolved.<br><br>
             * 
             * The result is passed as an array of values from all the promises. 
             * If something passed in the iterable array is not a promise, it's converted to 
             * one by Promise.resolve. If any of the passed in promises rejects, the 
             * all Promise immediately rejects with the value of the promise that rejected, 
             * discarding all the other promises whether or not they have resolved.
             * 
             * @method all
             * @memberOf Promise
             * @static
             * @param {KeyUsages} promises Array with promises.
             * @returns {Promise}
             */
            Promise.all = function (promises) {
                return new Promise(function (resolve, reject) {
                    var result = [], count = 0;
                    function asyncResolve(k) {
                        count++;
                        return function (data) {
                            result[k] = data;
                            count--;
                            if (count === 0)
                                resolve(result);
                        };
                    }

                    function asyncReject(reason) {
                        if (count > 0)
                            reject(reason);
                        count = 0;
                    }

                    for (var i = 0, n = promises.length; i < n; i++) {
                        var data = promises[i];
                        if (data.then && data.then.call)
                            data.then(asyncResolve(i), asyncReject);
                        else
                            result[i] = data;
                    }

                    if (count === 0)
                        resolve(result);
                });
            };

            return Promise;
        })();
    }

    // Executor for any method
    function execute(algorithm, method, args) {
        return new Promise(function (resolve, reject) {
            try {
                if (gostEngine)
                    resolve(gostEngine.execute(algorithm, method, args));
                else
                    reject(new OperationError('Module gostEngine not found'));
            } catch (error) {
                reject(error);
            }
        });
    }

    // Self resolver
    function call(callback) {
        try {
            callback();
        } catch (e) {
        }
    }



    /*
     * WebCrypto common class references
     * 
     */
    /**
     * The Algorithm object is a dictionary object [WebIDL] which is used to 
     * specify an algorithm and any additional parameters required to fully 
     * specify the desired operation.<br>
     * <pre>
     *  dictionary Algorithm {
     *      DOMString name;
     *  };
     * </pre>
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#algorithm-dictionary}
     * @class Algorithm
     * @param {DOMString} name The name of the registered algorithm to use.
     */

    /**
     * AlgorithmIdentifier - Algorithm or DOMString name of algorithm<br>
     * <pre>
     *  typedef (Algorithm or DOMString) AlgorithmIdentifier;
     * </pre>
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#algorithm-dictionary}
     * @class AlgorithmIdentifier
     */

    /**
     * The KeyAlgorithm interface represents information about the contents of a 
     * given Key object.
     * <pre>
     *  interface KeyAlgorithm {
     *      readonly attribute DOMString name
     *  };
     * </pre>
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#key-algorithm-interface}
     * @class KeyAlgorithm 
     * @param {DOMString} name The name of the algorithm used to generate the Key
     */

    /**
     * The type of a key. The recognized key type values are "public", "private" 
     * and "secret". Opaque keying material, including that used for symmetric 
     * algorithms, is represented by "secret", while keys used as part of asymmetric 
     * algorithms composed of public/private keypairs will be either "public" or "private".
     * <pre>
     *  typedef DOMString KeyType;
     * </pre>
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#key-interface}
     * @class KeyType
     */

    /**
     * Sequence of operation type that may be performed using a key. The recognized 
     * key usage values are "encrypt", "decrypt", "sign", "verify", "deriveKey", 
     * "deriveBits", "wrapKey" and "unwrapKey".
     * <pre>
     *  typedef DOMString[] KeyUsages;
     * </pre>
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#key-interface}
     * @class KeyUsages
     */

    /**
     * The Key object represents an opaque reference to keying material that is 
     * managed by the user agent.<br>
     * This specification provides a uniform interface for many different kinds of 
     * keying material managed by the user agent. This may include keys that have 
     * been generated by the user agent, derived from other keys by the user agent, 
     * imported to the user agent through user actions or using this API, 
     * pre-provisioned within software or hardware to which the user agent has 
     * access or made available to the user agent in other ways. The term key refers 
     * broadly to any keying material including actual keys for cryptographic 
     * operations and secret values obtained within key derivation or exchange operations.<br>
     * The Key object is not required to directly interface with the underlying key 
     * storage mechanism, and may instead simply be a reference for the user agent 
     * to understand how to obtain the keying material when needed, eg. when performing 
     * a cryptographic operation.
     * <pre>
     *  interface Key {
     *      readonly attribute KeyType type;
     *      readonly attribute boolean extractable;
     *      readonly attribute KeyAlgorithm algorithm;
     *      readonly attribute KeyUsages usages;
     *  };     
     * </pre>
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#key-interface}
     * @class Key
     * @param {KeyType} type The type of a key. The recognized key type values are "public", "private" and "secret".
     * @param {boolean} extractable Whether or not the raw keying material may be exported by the application.
     * @param {KeyAlgorithm} algorithm The Algorithm used to generate the key.
     * @param {KeyUsages} usages Key usage array: type of operation that may be performed using a key. 
     */

    /**
     * The KeyPair interface represents an asymmetric key pair that is comprised of both public and private keys.
     * <pre>
     *  interface KeyPair {
     *      readonly attribute Key publicKey;
     *      readonly attribute Key privateKey;
     *  };     
     * </pre>
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#keypair}
     * @class KeyPair
     * @param {Key} privateKey Private key
     * @param {Key} publicKey Public key
     */

    /**
     * Specifies a serialization format for a key. The recognized key format values are:
     *  <ul>
     *      <li>'raw' - An unformatted sequence of bytes. Intended for secret keys.</li>
     *      <li>'pkcs8' - The DER encoding of the PrivateKeyInfo structure from RFC 5208.</li>
     *      <li>'spki' - The DER encoding of the SubjectPublicKeyInfo structure from RFC 5280.</li>
     *      <li>'jwk' - The key is represented as JSON according to the JSON Web Key format.</li>
     *  </ul>
     *  <pre>
     *  typedef DOMString KeyFormat;
     *  </pre>
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#key-interface}
     *  @class KeyFormat
     */

    /**
     * Binary data 
     *  <pre>
     *  typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData;
     *  </pre>
     * @class CryptoOperationData
     */
    var CryptoOperationData = root.ArrayBuffer;

    /**
     * DER-encoded ArrayBuffer or PEM-encoded DOMString constains ASN.1 object<br>
     * <pre>
     *  typedef (ArrayBuffer or DOMString) FormatedData;
     * </pre>
     * @class FormatedData
     */


    /**
     * The gostCrypto provide general purpose cryptographic functionality for
     * GOST standards including a cryptographically strong pseudo-random number 
     * generator seeded with truly random values.
     * 
     * @namespace gostCrypto
     */
    var gostCrypto = {};

    /**
     * The SubtleCrypto class provides low-level cryptographic primitives and algorithms.
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#subtlecrypto-interface}
     * 
     * @class SubtleCrypto
     */
    function SubtleCrypto() {
    }

    /**
     * The encrypt method returns a new Promise object that will encrypt data 
     * using the specified algorithm identifier with the supplied Key.
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-encrypt}<br><br>
     * 
     * Supported algorithm names:
     *  <ul>
     *      <li><b>GOST 28147-ECB</b> "prostaya zamena" (ECB) mode (default)</li>
     *      <li><b>GOST 28147-CFB</b> "gammirovanie s obratnoj svyaziyu po shifrotekstu" (CFB) mode</li>
     *      <li><b>GOST 28147-OFB</b> "gammirovanie s obratnoj svyaziyu po vyhodu" (OFB) mode</li>
     *      <li><b>GOST 28147-CTR</b> "gammirovanie" (counter) mode</li>
     *      <li><b>GOST 28147-CBC</b> Cipher-Block-Chaining (CBC) mode</li>
     *      <li><b>GOST R 34.12-ECB</b> "prostaya zamena" (ECB) mode (default)</li>
     *      <li><b>GOST R 34.12-CFB</b> "gammirovanie s obratnoj svyaziyu po shifrotekstu" (CFB) mode</li>
     *      <li><b>GOST R 34.12-OFB</b> "gammirovanie s obratnoj svyaziyu po vyhodu" (OFB) mode</li>
     *      <li><b>GOST R 34.12-CTR</b> "gammirovanie" (counter) mode</li>
     *      <li><b>GOST R 34.12-CBC</b> Cipher-Block-Chaining (CBC) mode</li>
     *  </ul>
     *  For more information see {@link GostCipher} 
     * 
     * @memberOf SubtleCrypto
     * @method encrypt
     * @instance
     * @param {AlgorithmIdentifier} algorithm Algorithm identifier
     * @param {Key} key Key object
     * @param {CryptoOperationData} data Operation data
     * @returns {Promise} Promise that resolves with {@link CryptoOperationData}
     */
    SubtleCrypto.prototype.encrypt = function (algorithm, key, data)
    {
        return new Promise(call).then(function () {
            if (checkNative(algorithm))
                return rootCrypto.subtle.encrypt(algorithm, key, data);

            algorithm = normalize(algorithm, 'encrypt');
            return execute(algorithm, 'encrypt',
                    [extractKey('encrypt', algorithm, key), data]);
        });
    };

    /**
     * The decrypt method returns a new Promise object that will decrypt data 
     * using the specified algorithm identifier with the supplied Key. 
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-decrypt}<br><br>
     * 
     * Supported algorithm names:
     *  <ul>
     *      <li><b>GOST 28147-ECB</b> "prostaya zamena" (ECB) mode (default)</li>
     *      <li><b>GOST 28147-CFB</b> "gammirovanie s obratnoj svyaziyu po shifrotekstu" (CFB) mode</li>
     *      <li><b>GOST 28147-OFB</b> "gammirovanie s obratnoj svyaziyu po vyhodu" (OFB) mode</li>
     *      <li><b>GOST 28147-CTR</b> "gammirovanie" (counter) mode</li>
     *      <li><b>GOST 28147-CBC</b> Cipher-Block-Chaining (CBC) mode</li>
     *      <li><b>GOST R 34.12-ECB</b> "prostaya zamena" (ECB) mode (default)</li>
     *      <li><b>GOST R 34.12-CFB</b> "gammirovanie s obratnoj svyaziyu po shifrotekstu" (CFB) mode</li>
     *      <li><b>GOST R 34.12-OFB</b> "gammirovanie s obratnoj svyaziyu po vyhodu" (OFB) mode</li>
     *      <li><b>GOST R 34.12-CTR</b> "gammirovanie" (counter) mode</li>
     *      <li><b>GOST R 34.12-CBC</b> Cipher-Block-Chaining (CBC) mode</li>
     *  </ul>
     *  For additional modes see {@link GostCipher} 
     * 
     * @memberOf SubtleCrypto
     * @method decrypt
     * @instance
     * @param {AlgorithmIdentifier} algorithm Algorithm identifier
     * @param {Key} key Key object
     * @param {CryptoOperationData} data Operation data
     * @returns {Promise} Promise that resolves with {@link CryptoOperationData}
     */
    SubtleCrypto.prototype.decrypt = function (algorithm, key, data)
    {
        return new Promise(call).then(function () {
            if (checkNative(algorithm))
                return rootCrypto.subtle.decrypt(algorithm, key, data);

            algorithm = normalize(algorithm, 'decrypt');
            return execute(algorithm, 'decrypt',
                    [extractKey('decrypt', algorithm, key), data]);
        });
    };

    /**
     * The sign method returns a new Promise object that will sign data using 
     * the specified algorithm identifier with the supplied Key.
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-sign}<br><br>
     * 
     * Supported algorithm names:
     *  <ul>
     *      <li><b>GOST R 34.10-94</b> GOST Signature</li>
     *      <li><b>GOST R 34.10-94/GOST R 34.11-94</b> GOST Signature with Hash</li>
     *      <li><b>GOST R 34.10</b> ECGOST Signature</li>
     *      <li><b>GOST R 34.10/GOST R 34.11-94</b> ECGOST Signature with Old-Style Hash</li>
     *      <li><b>GOST R 34.10/GOST R 34.11</b> ECGOST Signature with Streebog Hash</li>
     *      <li><b>GOST 28147-MAC</b> MAC base on GOST 28147</li>
     *      <li><b>GOST R 34.12-MAC</b> MAC base on GOST R 43.12</li>
     *      <li><b>GOST R 34.11-HMAC</b> HMAC base on GOST 34.11</li>
     *      <li><b>SHA-HMAC</b> HMAC base on SHA</li>
     *  </ul>
     *  For additional modes see {@link GostSign}, {@link GostDigest} and {@link GostCipher}
     * 
     * @memberOf SubtleCrypto
     * @method sign
     * @instance
     * @param {AlgorithmIdentifier} algorithm Algorithm identifier
     * @param {Key} key Key object 
     * @param {CryptoOperationData} data Operation data
     * @returns {Promise} Promise that resolves with {@link CryptoOperationData}
     */
    SubtleCrypto.prototype.sign = function (algorithm, key, data)
    {
        return new Promise(call).then(function () {
            if (checkNative(algorithm))
                return rootCrypto.subtle.sign(algorithm, key, data);

            algorithm = normalize(algorithm, 'sign');
            var value = execute(algorithm, 'sign',
                    [extractKey('sign', algorithm, key), data]).then(function (data) {
                if (algorithm.procreator === 'SC' && algorithm.mode === 'SIGN') {
                    data = gostCrypto.asn1.GostSignature.encode(data);
                }
                return data;
            });
            return value;
        });
    };

    /**
     * The verify method returns a new Promise object that will verify data 
     * using the specified algorithm identifier with the supplied Key.
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-verify}<br><br>
     * 
     * Supported algorithm names:
     *  <ul>
     *      <li><b>GOST R 34.10-94</b> GOST Signature</li>
     *      <li><b>GOST R 34.10-94/GOST R 34.11-94</b> GOST Signature with Hash</li>
     *      <li><b>GOST R 34.10</b> ECGOST Signature</li>
     *      <li><b>GOST R 34.10/GOST R 34.11-94</b> ECGOST Signature with Old-Style Hash</li>
     *      <li><b>GOST R 34.10/GOST R 34.11</b> ECGOST Signature with Streebog Hash</li>
     *      <li><b>GOST 28147-MAC</b> MAC base on GOST 28147</li>
     *      <li><b>GOST R 34.12-MAC</b> MAC base on GOST R 34.12</li>
     *      <li><b>GOST R 34.11-HMAC</b> HMAC base on GOST 34.11</li>
     *      <li><b>SHA-HMAC</b> HMAC base on SHA</li>
     *  </ul>
     *  For additional modes see {@link GostSign}, {@link GostDigest} and {@link GostCipher}
     * 
     * @memberOf SubtleCrypto
     * @method verify
     * @instance
     * @param {AlgorithmIdentifier} algorithm Algorithm identifier
     * @param {Key} key Key object
     * @param {CryptoOperationData} signature Signature data
     * @param {CryptoOperationData} data Operation data
     * @returns {Promise} Promise that resolves with boolean value of verification result
     */
    SubtleCrypto.prototype.verify = function (algorithm, key, signature, data)
    {
        return new Promise(call).then(function () {
            if (checkNative(algorithm))
                return rootCrypto.subtle.verify(algorithm, key, signature, data);

            algorithm = normalize(algorithm, 'verify');
            if (algorithm.procreator === 'SC' && algorithm.mode === 'SIGN') {
                var obj = gostCrypto.asn1.GostSignature.decode(signature);
                signature = {r: obj.r, s: obj.s};
            }
            return execute(algorithm, 'verify',
                    [extractKey('verify', algorithm, key), signature, data]);
        });
    };

    /**
     * The digest method returns a new Promise object that will digest data 
     * using the specified algorithm identifier. 
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-digest}<br><br>
     * 
     * Supported algorithm names:
     *  <ul>
     *      <li><b>GOST R 34.11-94</b> Old-Style GOST Hash</li>
     *      <li><b>GOST R 34.11</b> GOST Streebog Hash</li>
     *      <li><b>SHA</b> SHA Hash</li>
     *  </ul>
     *  For additional modes see {@link GostDigest}
     * 
     * @memberOf SubtleCrypto
     * @method digest
     * @instance
     * @param {AlgorithmIdentifier} algorithm Algorithm identifier
     * @param {CryptoOperationData} data Operation data
     * @returns {Promise} Promise that resolves with {@link CryptoOperationData}
     */
    SubtleCrypto.prototype.digest = function (algorithm, data)
    {
        return new Promise(call).then(function () {
            if (checkNative(algorithm))
                return rootCrypto.subtle.digest(algorithm, data);

            algorithm = normalize(algorithm, 'digest');
            return execute(algorithm, 'digest', [data]);
        });
    };

    /**
     * The generateKey method returns a new Promise object that will key(s) using
     * the specified algorithm identifier. Key can be used in according with
     * KeyUsages sequence. The recognized key usage values are "encrypt", "decrypt", 
     * "sign", "verify", "deriveKey", "deriveBits", "wrapKey" and "unwrapKey".
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-generateKey}<br><br>
     * 
     * Supported algorithm names:
     *  <ul>
     *      <li><b>GOST R 34.10</b> ECGOST Key Pairs</li>
     *      <li><b>GOST 28147</b> Key for encryption GOST 28147 modes</li>
     *      <li><b>GOST 28147-KW</b> Key for wrapping GOST 28147 modes</li>
     *      <li><b>GOST R 34.12</b> Key for encryption GOST R 34.12 modes</li>
     *      <li><b>GOST R 34.12-KW</b> Key for wrapping GOST R 34.12 modes</li>
     *      <li><b>GOST R 34.11-KDF</b> Key for Derivation Algorithm</li>
     *  </ul>
     *  For additional modes see {@link GostSign}, {@link GostDigest} and {@link GostCipher}<br>
     *  Note: Generation key for GOST R 34.10-94 not supported.
     * 
     * @memberOf SubtleCrypto
     * @method generateKey
     * @instance
     * @param {AlgorithmIdentifier} algorithm Key algorithm identifier
     * @param {boolean} extractable Whether or not the raw keying material may be exported by the application
     * @param {KeyUsages} keyUsages Key usage array: type of operation that may be performed using a key
     * @returns {Promise} Promise that resolves with {@link Key} or {@link KeyPair} in according to key algorithm
     */
    SubtleCrypto.prototype.generateKey = function (algorithm, extractable, keyUsages)
    {
        return new Promise(call).then(function () {
            if (checkNative(algorithm))
                return rootCrypto.subtle.generateKey(algorithm, extractable, keyUsages);

            var privateAlgorithm = algorithm.privateKey,
                    publicAlgorithm = algorithm.publicKey;
            algorithm = normalize(algorithm, 'generateKey');
            if (privateAlgorithm)
                privateAlgorithm = normalize(privateAlgorithm, 'generateKey');
            else
                privateAlgorithm = algorithm;
            if (publicAlgorithm)
                publicAlgorithm = normalize(publicAlgorithm, 'generateKey');
            else
                publicAlgorithm = algorithm;
            return execute(algorithm, 'generateKey', []).then(function (data) {
                if (data.publicKey && data.privateKey)
                    return convertKeyPair(publicAlgorithm, privateAlgorithm, extractable, keyUsages, data.publicKey, data.privateKey);
                else
                    return convertKey(algorithm, extractable, keyUsages, data);
            });
        });
    };

    /**
     * The deriveKey method returns a new Promise object that will key(s) using
     * the specified algorithm identifier. Key can be used in according with
     * KeyUsage sequence. The recognized key usage values are "encrypt", "decrypt", 
     * "sign", "verify", "deriveKey", "deriveBits", "wrapKey" and "unwrapKey".
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-deriveKey}<br><br>
     * 
     * Supported algorithm names:
     *  <ul>
     *      <li><b>GOST R 34.10-DH</b> ECDH Key Agreement mode</li>
     *      <li><b>GOST R 34.11-KDF</b> Key for Derivation Algorithm</li>
     *      <li><b>GOST R 34.11-PBKDF2</b> Password Based Key for Derivation Algorithm</li>
     *      <li><b>GOST R 34.11-PFXKDF</b> PFX Key for Derivation Algorithm</li>
     *      <li><b>GOST R 34.11-CPKDF</b> Password Based Key for CryptoPro Derivation Algorithm</li>
     *      <li><b>SHA-PBKDF2</b> Password Based Key for Derivation Algorithm</li>
     *      <li><b>SHA-PFXKDF</b> PFX Key for Derivation Algorithm</li>
     *  </ul>
     *  For additional modes see {@link GostSign} and {@link GostDigest}
     * 
     * @memberOf SubtleCrypto
     * @method deriveKey
     * @instance
     * @param {AlgorithmIdentifier} algorithm Algorithm identifier
     * @param {Key} baseKey Derivation key object
     * @param {AlgorithmIdentifier} derivedKeyType Derived key algorithm identifier
     * @param {boolean} extractable Whether or not the raw keying material may be exported by the application
     * @param {KeyUsages} keyUsages Key usage array: type of operation that may be performed using a key 
     * @returns {Promise} Promise that resolves with {@link Key}
     */
    SubtleCrypto.prototype.deriveKey = function (algorithm, baseKey,
            derivedKeyType, extractable, keyUsages)
    {
        return new Promise(call).then(function () {
            if (checkNative(algorithm))
                return rootCrypto.subtle.deriveKey(algorithm, baseKey,
                        derivedKeyType, extractable, keyUsages);

            algorithm = normalize(algorithm, 'deriveKey');
            derivedKeyType = normalize(derivedKeyType, 'generateKey');
            algorithm.keySize = derivedKeyType.keySize;
            if (algorithm['public']) {
                algorithm['public'].algorithm = normalize(algorithm['public'].algorithm);
                algorithm['public'] = extractKey('deriveKey', algorithm, algorithm['public']);
            }
            return execute(algorithm, 'deriveKey', [extractKey('deriveKey', algorithm, baseKey)]).then(function (data) {
                return convertKey(derivedKeyType, extractable, keyUsages, data);
            });
        });
    };

    /**
     * The deriveBits method returns length bits on baseKey using the 
     * specified algorithm identifier. 
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-deriveBits}<br><br>
     * 
     * Supported algorithm names:
     *  <ul>
     *      <li><b>GOST R 34.10-DH</b> ECDH Key Agreement mode</li>
     *      <li><b>GOST R 34.11-KDF</b> Key for Derivation Algorithm</li>
     *      <li><b>GOST R 34.11-PBKDF2</b> Password Based Key for Derivation Algorithm</li>
     *      <li><b>GOST R 34.11-PFXKDF</b> PFX Key for Derivation Algorithm</li>
     *      <li><b>GOST R 34.11-CPKDF</b> Password Based Key for CryptoPro Derivation Algorithm</li>
     *      <li><b>SHA-PBKDF2</b> Password Based Key for Derivation Algorithm</li>
     *      <li><b>SHA-PFXKDF</b> PFX Key for Derivation Algorithm</li>
     *  </ul>
     *  For additional modes see {@link GostSign} and {@link GostDigest}
     * 
     * @memberOf SubtleCrypto
     * @method deriveBits
     * @instance
     * @param {AlgorithmIdentifier} algorithm Algorithm identifier
     * @param {Key} baseKey Derivation key object
     * @param {number} length Length bits
     * @returns {Promise} Promise that resolves with {@link CryptoOperationData}
     */
    SubtleCrypto.prototype.deriveBits = function (algorithm, baseKey, length)
    {
        return new Promise(call).then(function () {
            if (checkNative(algorithm))
                return rootCrypto.subtle.deriveBits(algorithm, baseKey, length);

            algorithm = normalize(algorithm, 'deriveBits');
            if (algorithm['public'])
                algorithm['public'] = extractKey('deriveBits', algorithm, algorithm['public']);
            return execute(algorithm, 'deriveBits', [extractKey('deriveBits', algorithm, baseKey), length]);
        });
    };

    /**
     * The importKey method returns a new Promise object that will key(s) using
     * the specified algorithm identifier. Key can be used in according with
     * KeyUsage sequence. The recognized key usage values are "encrypt", "decrypt", 
     * "sign", "verify", "deriveKey", "deriveBits", "wrapKey" and "unwrapKey".<br><br>
     * Parameter keyData contains data in defined format.
     * The suppored key format values are:
     *  <ul>
     *      <li>'raw' - An unformatted sequence of bytes. Intended for secret keys.</li>
     *      <li>'pkcs8' - The DER encoding of the PrivateKeyInfo structure from RFC 5208.</li>
     *      <li>'spki' - The DER encoding of the SubjectPublicKeyInfo structure from RFC 5280.</li>
     *  </ul>
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-importKey}<br><br>
     * 
     * Supported algorithm names:
     *  <ul>
     *      <li><b>GOST R 34.10-94</b> GOST Private and Public keys</li>
     *      <li><b>GOST R 34.10</b> ECGOST Private and Public keys</li>
     *      <li><b>GOST 28147</b> Key for encryption GOST 28147 modes</li>
     *      <li><b>GOST 28147-KW</b> Key for key wrapping GOST 28147 modes</li>
     *      <li><b>GOST R 34.12</b> Key for encryption GOST 34.12 modes</li>
     *      <li><b>GOST R 34.12-KW</b> Key for key wrapping GOST 34.12 modes</li>
     *      <li><b>GOST R 34.11-KDF</b> Key for Derivation Algorithm</li>
     *  </ul>
     *  For additional modes see {@link GostSign}, {@link GostDigest} and {@link GostCipher}<br>
     * 
     * @memberOf SubtleCrypto
     * @method importKey
     * @instance
     * @param {KeyFormat} format Key format Format specifies a serialization format for a key
     * @param {CryptoOperationData} keyData
     * @param {AlgorithmIdentifier} algorithm Key algorithm identifier
     * @param {boolean} extractable Whether or not the raw keying material may be exported by the application
     * @param {KeyUsages} keyUsages Key usage array: type of operation that may be performed using a key
     * @returns {Promise} Promise that resolves with {@link Key}
     */
    SubtleCrypto.prototype.importKey = function (format, keyData, algorithm, extractable, keyUsages)
    {
        var type;
        return new Promise(call).then(function () {
            if (checkNative(algorithm))
                return rootCrypto.subtle.importKey(format, keyData, algorithm, extractable, keyUsages);

            if (format === 'raw') {
                algorithm = normalize(algorithm, 'importKey');
                if (keyUsages && keyUsages.indexOf) {
                    var name = algorithm.name.toUpperCase().replace(/[\.\s]/g, '');
                    if (name.indexOf('3410') >= 0 && keyUsages.indexOf('sign') >= 0)
                        type = 'private';
                    else if (name.indexOf('3410') >= 0 && keyUsages.indexOf('verify') >= 0)
                        type = 'public';
                }
                return keyData;
            } else {
                var key;
                if (format === 'pkcs8')
                    key = gostCrypto.asn1.GostPrivateKeyInfo.decode(keyData).object;
                else if (format === 'spki')
                    key = gostCrypto.asn1.GostSubjectPublicKeyInfo.decode(keyData).object;
                else
                    throw new NotSupportedError('Key format not supported');

                algorithm = normalize(key.algorithm, 'importKey');
                type = key.type;
                if (extractable !== false)
                    extractable = extractable || key.extractable;
                if (keyUsages) {
                    for (var i = 0; i < keyUsages.length; i++) {
                        if (key.usages.indexOf(keyUsages[i]) < 0)
                            throw DataError('Key usage not valid for this key');
                    }
                } else
                    keyUsages = key.usages;
                var data = key.buffer, keySize = algorithm.keySize, dataLen = data.byteLength;
                if (type === 'public' || keySize === dataLen)
                    return data;
                else {
                    // Remove private key masks
                    if (dataLen % keySize > 0)
                        throw new DataError('Invalid key size');
                    algorithm.mode = 'MASK';
                    algorithm.procreator = 'VN';
                    var chain = [];
                    for (var i = keySize; i < dataLen; i += keySize) {
                        chain.push((function (mask) {
                            return function (data) {
                                return execute(algorithm, 'unwrapKey', [mask, data]).then(function (data) {
                                    var next = chain.pop();
                                    if (next)
                                        return next(data);
                                    else {
                                        delete algorithm.mode;
                                        return data;
                                    }
                                });
                            };
                        })(new Uint8Array(data, i, keySize)));
                    }
                    return chain.pop()(new Uint8Array(data, 0, keySize));
                }
            }
        }).then(function (data) {
            return convertKey(algorithm, extractable, keyUsages, data, type);
        });
    };

    /**
     * The exportKey method returns a new Promise object that will key data in
     * defined format. <br><br>
     * The suppored key format values are:
     *  <ul>
     *      <li>'raw' - An unformatted sequence of bytes. Intended for secret keys.</li>
     *      <li>'pkcs8' - The DER encoding of the PrivateKeyInfo structure from RFC 5208.</li>
     *      <li>'spki' - The DER encoding of the SubjectPublicKeyInfo structure from RFC 5280.</li>
     *  </ul>
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-exportKey}<br><br>
     * 
     * Supported algorithm names:
     *  <ul>
     *      <li><b>GOST R 34.10-94</b> GOST Private and Public keys</li>
     *      <li><b>GOST R 34.10</b> ECGOST Private and Public keys</li>
     *      <li><b>GOST 28147</b> Key for encryption GOST 28147 modes</li>
     *      <li><b>GOST 28147-KW</b> Key for key wrapping GOST 28147 modes</li>
     *      <li><b>GOST R 34.12</b> Key for encryption GOST R 34.12 modes</li>
     *      <li><b>GOST R 34.12-KW</b> Key for key wrapping GOST R 34.12 modes</li>
     *      <li><b>GOST R 34.11-KDF</b> Key for Derivation Algorithm</li>
     *      <li><b>GOST R 34.11-PBKDF2</b> Import Password for Key for Derivation Algorithm</li>
     *      <li><b>GOST R 34.11-PFXKDF</b> Import PFX Key for Derivation Algorithm</li>
     *      <li><b>GOST R 34.11-CPKDF</b> Import Password Key for CryptoPro Derivation Algorithm</li>
     *      <li><b>SHA-PBKDF2</b> Import Password for Key for Derivation Algorithm</li>
     *      <li><b>SHA-PFXKDF</b> Import PFX Key for Derivation Algorithm</li>
     *  </ul>
     *  For additional modes see {@link GostSign}, {@link GostDigest} and {@link GostCipher}<br>
     * 
     * @memberOf SubtleCrypto
     * @method exportKey
     * @instance
     * @param {KeyFormat} format Format specifies a serialization format for a key
     * @param {Key} key Key object
     * @returns {Promise} Promise that resolves with {@link CryptoOperationData}
     */
    SubtleCrypto.prototype.exportKey = function (format, key)
    {
        return new Promise(call).then(function () {
            if (key && checkNative(key.algorithm))
                return rootCrypto.subtle.exportKey(format, key);

            if (!key.extractable)
                throw new InvalidAccessError('Key not extractable');

            var raw = extractKey(null, null, key);
            if (format === 'raw')
                return raw;
            else if (format === 'pkcs8' && key.algorithm && key.algorithm.id) {
                if (key.algorithm.procreator === 'VN') {
                    // Add masks for ViPNet
                    var algorithm = key.algorithm, mask;
                    algorithm.mode = 'MASK';
                    return execute(algorithm, 'generateKey').then(function (data) {
                        mask = data;
                        return execute(algorithm, 'wrapKey', [mask, key.buffer]);
                    }).then(function (data) {
                        delete algorithm.mode;
                        var d = new Uint8Array(data.byteLength + mask.byteLength);
                        d.set(new Uint8Array(data, 0, data.byteLength));
                        d.set(new Uint8Array(mask, 0, mask.byteLength), data.byteLength);
                        var buffer = d.buffer;
                        buffer.enclosed = true;
                        return gostCrypto.asn1.GostPrivateKeyInfo.encode({
                            algorithm: algorithm,
                            buffer: buffer
                        });
                    });
                } else
                    return gostCrypto.asn1.GostPrivateKeyInfo.encode(key);
            } else if (format === 'spki' && key.algorithm && key.algorithm.id)
                return gostCrypto.asn1.GostSubjectPublicKeyInfo.encode(key);
            else
                throw new NotSupportedError('Key format not supported');
        });
    };

    /**
     * The wrapKey method returns a new Promise object that will wrapped key(s).
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-wrapKey}<br><br>
     * 
     * Supported algorithm names:
     *  <ul>
     *      <li><b>GOST 28147-KW</b> Key Wrapping GOST 28147 modes</li>
     *      <li><b>GOST R 34.12-KW</b> Key Wrapping GOST R 34.12 modes</li>
     *      <li><b>GOST 28147-MASK</b> Key Mask GOST 28147 modes</li>
     *      <li><b>GOST R 34.12-MASK</b> Key Mask GOST R 34.12 modes</li>
     *      <li><b>GOST R 34.10-MASK</b> Key Mask GOST R 34.10 modes</li>
     *  </ul>
     *  For additional modes see {@link GostCipher}<br>
     * 
     * @memberOf SubtleCrypto
     * @method wrapKey
     * @instance
     * @param {KeyFormat} format Format specifies a serialization format for a key. Now suppored only 'raw' key format.
     * @param {Key} key Key object
     * @param {Key} wrappingKey Wrapping key object
     * @param {AlgorithmIdentifier} wrapAlgorithm Algorithm identifier
     * @returns {Promise} Promise that resolves with {@link CryptoOperationData}
     */
    SubtleCrypto.prototype.wrapKey = function (format, key, wrappingKey, wrapAlgorithm)
    {
        return new Promise(call).then(function () {
            if (checkNative(wrapAlgorithm))
                return rootCrypto.subtle.wrapKey(format, key, wrappingKey, wrapAlgorithm);

            wrapAlgorithm = normalize(wrapAlgorithm, 'wrapKey');
            var keyData = extractKey(null, null, key);
            if (wrapAlgorithm.procreator === 'SC' && key.type === 'private')
                keyData = swapBytes(keyData);
            return execute(wrapAlgorithm, 'wrapKey',
                    [extractKey('wrapKey', wrapAlgorithm, wrappingKey), keyData]).then(function (data) {
                if (format === 'raw')
                    return data;
                else
                    throw new NotSupportedError('Key format not supported');
            });
        });
    };

    /**
     * The unwrapKey method returns a new Promise object that will unwrapped key(s).
     * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-unwrapKey}<br><br>
     * 
     * Supported algorithm names:
     *  <ul>
     *      <li><b>GOST 28147-KW</b> Key Wrapping GOST 28147 modes</li>
     *      <li><b>GOST R 34.12-KW</b> Key Wrapping GOST R 34.12 modes</li>
     *      <li><b>GOST 28147-MASK</b> Key Mask GOST 28147 modes</li>
     *      <li><b>GOST R 34.12-MASK</b> Key Mask GOST R 34.12 modes</li>
     *      <li><b>GOST R 34.10-MASK</b> Key Mask GOST R 34.10 modes</li>
     *  </ul>
     *  For additional modes see {@link GostCipher}<br>
     * 
     * @memberOf SubtleCrypto
     * @method unwrapKey
     * @instance
     * @param {KeyFormat} format Format specifies a serialization format for a key. Now suppored only 'raw' key format.
     * @param {CryptoOperationData} wrappedKey Wrapped key data
     * @param {Key} unwrappingKey Unwrapping key object
     * @param {AlgorithmIdentifier} unwrapAlgorithm Algorithm identifier
     * @param {AlgorithmIdentifier} unwrappedKeyAlgorithm Key algorithm identifier
     * @param {boolean} extractable Whether or not the raw keying material may be exported by the application
     * @param {KeyUsages} keyUsages Key usage array: type of operation that may be performed using a key
     * @returns {Promise} Promise that resolves with {@link Key}
     */
    SubtleCrypto.prototype.unwrapKey = function (format, wrappedKey, unwrappingKey,
            unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages)
    {
        return new Promise(call).then(function () {
            if (checkNative(unwrapAlgorithm))
                return rootCrypto.subtle.unwrapKey(format, wrappedKey, unwrappingKey,
                        unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages);

            unwrapAlgorithm = normalize(unwrapAlgorithm, 'unwrapKey');
            unwrappedKeyAlgorithm = normalize(unwrappedKeyAlgorithm, 'importKey');
            if (format !== 'raw')
                throw new NotSupportedError('Key format not supported');

            return execute(unwrapAlgorithm, 'unwrapKey', [extractKey('unwrapKey', unwrapAlgorithm, unwrappingKey), wrappedKey]).then(function (data) {
                var type;
                if (unwrappedKeyAlgorithm && unwrappedKeyAlgorithm.name) {
                    var name = unwrappedKeyAlgorithm.name.toUpperCase().replace(/[\.\s]/g, '');
                    if (name.indexOf('3410') >= 0 && keyUsages.indexOf('sign') >= 0)
                        type = 'private';
                    else if (name.indexOf('3410') >= 0 && keyUsages.indexOf('verify') >= 0)
                        type = 'public';
                }
                if (unwrapAlgorithm.procreator === 'SC' && type === 'private')
                    data = swapBytes(data);
                return convertKey(unwrappedKeyAlgorithm, extractable, keyUsages, data, type);
            });
        });
    };

    /**
     * The subtle attribute provides an instance of the SubtleCrypto 
     * interface which provides low-level cryptographic primitives and 
     * algorithms.
     * 
     * @memberOf gostCrypto
     * @type SubtleCrypto
     */
    gostCrypto.subtle = new SubtleCrypto();

    /**
     * The getRandomValues method generates cryptographically random values. 
     * 
     * First try to use Web Crypto random genereator. Next make random
     * bytes based on standart Math.random mixed with time and mouse pointer
     * 
     * @memberOf gostCrypto
     * @param {(CryptoOperationData)} array Destination buffer for random data
     */
    gostCrypto.getRandomValues = function (array)
    {
        // Execute randomizer
        var randomSource = new GostRandom();
        if (randomSource.getRandomValues)
            randomSource.getRandomValues(array);
        else
            throw new NotSupportedError('Random generator not found');
    };


module.exports = gostCrypto;



/***/ }),

/***/ "./node_modules/node-gost-crypto/lib/gostDigest.js":
/*!*********************************************************!*\
  !*** ./node_modules/node-gost-crypto/lib/gostDigest.js ***!
  \*********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

/**
 * @file GOST R 34.11-94 / GOST R 34.11-12 implementation
 * @version 1.76
 * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *    
 * Converted to JavaScript from source https://www.streebog.net/
 * Copyright (c) 2013, Alexey Degtyarev.
 * All rights reserved.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

const GostRandom = __webpack_require__(/*! ./gostRandom */ "./node_modules/node-gost-crypto/lib/gostRandom.js");
const GostCipher = __webpack_require__(/*! ./gostCipher */ "./node_modules/node-gost-crypto/lib/gostCipher.js");

    /*
     * GOST R 34.11
     * Common methods 
     * 
     */

    var root = __webpack_require__.g;
    var rootCrypto = root.crypto || root.msCrypto;

    var DataError = root.DataError || Error,
            NotSupportedError = root.NotSupportedError || Error;

    // Copy len values from s[sOfs] to d[dOfs]
    function arraycopy(s, sOfs, d, dOfs, len) {
        for (var i = 0; i < len; i++)
            d[dOfs + i] = s[sOfs + i];
    }

    // Swap bytes in buffer
    function swap(s) {
        var src = new Uint8Array(s),
                dst = new Uint8Array(src.length);
        for (var i = 0, n = src.length; i < n; i++)
            dst[n - i - 1] = src[i];
        return dst.buffer;
    }

    // Convert BASE64 string to Uint8Array
    // for decompression of constants and precalc values
    function b64decode(s) {
        // s = s.replace(/[^A-Za-z0-9\+\/]/g, '');
        var n = s.length,
                k = n * 3 + 1 >> 2, r = new Uint8Array(k);

        for (var m3, m4, u24 = 0, j = 0, i = 0; i < n; i++) {
            m4 = i & 3;
            var c = s.charCodeAt(i);

            c = c > 64 && c < 91 ?
                    c - 65 : c > 96 && c < 123 ?
                    c - 71 : c > 47 && c < 58 ?
                    c + 4 : c === 43 ?
                    62 : c === 47 ?
                    63 : 0;

            u24 |= c << 18 - 6 * m4;
            if (m4 === 3 || n - i === 1) {
                for (m3 = 0; m3 < 3 && j < k; m3++, j++) {
                    r[j] = u24 >>> (16 >>> m3 & 24) & 255;
                }
                u24 = 0;

            }
        }
        return r.buffer;
    }

    // Random seed
    function getSeed(length) {
        var randomSource = new GostRandom();
        if (randomSource.getRandomValues) {
            var d = new Uint8Array(Math.ceil(length / 8));
            randomSource.getRandomValues(d);
            return d;
        } else
            throw new NotSupportedError('Random generator not found');
    }

    // Check buffer
    function buffer(d) {
        if (d instanceof ArrayBuffer)
            return d;
        else if (d && d.buffer && d.buffer instanceof ArrayBuffer)
            return d.byteOffset === 0 && d.byteLength === d.buffer.byteLength ?
                    d.buffer : new Uint8Array(new Uint8Array(d, d.byteOffset, d.byteLength)).buffer;
        else
            throw new DataError('ArrayBuffer or ArrayBufferView required');
    }

    /**
     * Algorithm name GOST R 34.11 or GOST R 34.11-12<br><br>
     * 
     * http://tools.ietf.org/html/rfc6986
     * 
     * The digest method returns digest data in according to GOST R 4311-2012.<br>
     * Size of digest also defines in algorithm name. 
     *  <ul>
     *      <li>GOST R 34.11-256-12 - 256 bits digest</li>
     *      <li>GOST R 34.11-512-12 - 512 bits digest</li>
     *  </ul>
     *  
     * @memberOf GostDigest
     * @method digest
     * @instance
     * @param {(ArrayBuffer|TypedArray)} data Data
     * @returns {ArrayBuffer} Digest of data
     */
    var digest2012 = (function ()
    {
        // Constants 
        var buffer0 = new Int32Array(16); // [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];  

        var buffer512 = new Int32Array(16); // [512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 
        buffer512[0] = 512;

        // Constant C 
        var C = (function (s) {
            var h = new Int32Array(b64decode(s)),
                    r = new Array(12);
            for (var i = 0; i < 12; i++)
                r[i] = new Int32Array(h.buffer, i * 64, 16);
            return r;
        })(
                'B0Wm8lllgN0jTXTMNnR2BRXTYKQIKkKiAWlnkpHgfEv8xIV1jbhOcRbQRS5DdmovH3xlwIEvy+vp2soe2lsIsbebsSFwBHnmVs3L1xui3VXKpwrbwmG1XFiZ1hJrF7WaMQG1Fg9e1WGYKyMKcur+89e1cA9GneNPGi+dqYq1o2+yCroK9ZYemTHbeoZD9LbCCdtiYDc6ycGxnjWQ5A/i03t7KbEUderyix+cUl9e8QY1hD1qKPw5Cscvzius3HT1LtHjhLy+DCLxN+iToepTNL4DUpMzE7fYddYD7YIs16k/NV5orRxynX08XDN+hY5I3eRxXaDhSPnSZhXos98f71f+bHz9WBdg9WPqqX6iVnoWGicjtwD/36P1OiVHF82/vf8PgNc1njVKEIYWHxwVf2MjqWwMQT+amUdHraxr6ktufWRGekBo+jVPkDZyxXG/tsa+wmYf8gq0t5oct6b6z8aO8Jq0mn8YbKRCUfnEZi3AOTB6O8Okb9nTOh2urk+uk9QUOk1WhojzSjyiTEUXNQQFSiiDaUcGNyyCLcWrkgnJk3oZMz5H08mHv+bHxp45VAkkv/6GrFHsxaruFg7H9B7nAr/UDX+k' +
                '2ahRWTXCrDYvxKXRK43RaZAGm5LLK4n0msTbTTtEtIke3jaccfi3TkFBbgwCqucDp8mTTUJbH5vbWiODUURhcmAqH8uS3DgOVJwHppqKK3uxzrLbC0QKgIQJDeC3Vdk8JEKJJRs6fTreXxbs2JpMlJsiMRZUWo837ZxFmPvHtHTDtjsV0fqYNvRSdjswbB56SzNprwJn558DYTMbiuH/H9t4iv8c50GJ8/PkskjlKjhSbwWApt6+qxst84HNpMprXdhvwEpZot6Ybkd9Hc2678q5SOrvcR2KeWaEFCGAASBhB6vru2v62JT+WmPNxgIw+4nI79CezXsg1xvxSpK8SJkbstnVF/T6UijhiKqkHeeGzJEYne+AXZufITDUEiD4dx3fvDI8pM16sUkEsIAT0roxFvFn5443');

        // Precalc Ax 
        var Ax = (function (s) {
            return new Int32Array(b64decode(s));
        })(
                '5vh+XFtxH9Alg3eACST6FshJ4H6FLqSoW0aGoY8GwWoLMumi13tBbqvaN6RngVxm9heWqBpoZnb13AtwY5GVS0hi84235kvx/1ximmi9hcXLgn2m/NdXlWbTba9pufCJNWyfdEg9g7B8vOyxI4yZoTanAqwxxHCNnrao0C+839aLGfpR5bOuN5zPtUCKEn0LvAx4tQggj1rlM+OEIojs7c7Cx9N3wV/S7HgXtlBdD165TMLAgzaHHYwgXbTLCwStdjyFWyigiS9YjRt59v8yVz/s9p5DEZM+D8DTn4A6GMnuAQom9fOtgxDv6PRBGXmmXc2hDH3pOhBKG+4dEkjpLFO/8tshhHM5tPUMz6aiPQlftLyc2EeYzeiKLYsHHFb5f3dxaVp1apzF8C5xoLoevKZj+atCFeZyLrGeIt5fu3gNuc4PJZS6FIJSDmOXZk2ELwMeagII6phcfyFEob5r8Ho3yxzRY2Lbg+COK0sxHGTPcEebq5YOMoVrqYa53ucetUeMh3r1bOm4/kKIX2HW/RvdAVaWYjjIYiFXkj74qS78l/9CEUR2+J19NQhWRSzrTJDJsOCnElYjCFAt+8sBbC16A/qnpkhF' +
                '9G6LOL/GxKu9vvj91HfeujqsTOvIB5t58JyxBeiHnQwn+moQrIpYy4lg58FAHQzqGm+BHko1aSiQxPsHc9GW/0NQGi9gnQqf96UW4MY/N5Yc5KazuNqSUhMkdSw44IqbpahkczvsFU8r8SRXVUmzP9dm2xVEDcXHp9F5455Ct5La3xUaYZl/04agNF7AJxQjONVRe22pOaRlGPB3EEADtAJ5HZClrqLdiNJniZxKXQqTD2bfCihlwk7p1CBFCbCLMlU4kWaFKSpBKQe/xTOoQrJ+K2JUTcZzbFMERWKV4Ada9AbpU1GQih8vO2vBI2Fvw3sJ3FJV5cY5Z9Ezsf5oRCmIOcfw5xHiQJuH9xlk+aLpOK3D20sHGQwLTkf5w+v0VTTVdtNriENGEKBa64sC2CDDzfWCMvJRbeGEDb7Cseeg6N4GsPodCHuFS1QNNDM7QuKaZ7zKW3/YpgiKxDfdDsY7s6nZQ+2BIXFNvV5lo7FnYe3nte6haSQx98jVc6v21R/GheGjZxpeBjzUBBDJLSg6uY8ssEACj+vAbLLy95AX1k8Rb6HTPOBzWfGpnuSqeE7WjHTNwAZuKhnVxztC2ocStBYccEXD' +
                'NxWC5O2TIW2s45BBSTn2/H7F8SGGIjt8wLCUBCusFvv510U3mlJ+v3N8Py6jtoFoM+e42brSeMqpoyo0wi/+u+SBY8z+370NjllAJG6lpnBRxu9LhCrR5CK60GUnnFCM2RSIwhhgjO4xnqVJH3zaF9OU4SgTTJxgCUv0MnLV47Ob9hKlpKrXkcy72kPSb/0PNN4fPJRq0lBPW1RomV7ha9+fr2/qj3eUJkjqWHDdCSu/x+Vtcdl8Z93msv9PIdVJPCdrRjroYAORdntPr4bHH2ihPng11LmgtowRXwMMn9QUHdLJFlggAZg9j33dUySsZKpwP8wXUlTCyYmUjgK0Jj5edtafRsLeUHRvA1h9gARF2z2CknLx5WBYSgKbVgvz+65Ypz/83GKhWl5ObK1M6EupblXOH7jMCPl0eq6CslPBAhRM9/tHG58EKJjz6442BosnrfLv+3rtypf+jApevneOBRP099jPMCwlAcMri/eNkt38F1xVTfhlxX9GBS9f6vMwG6Ky9CSqaLfsu9YNhpmPDzUBBHVMAAAAAAAAAADxLjFNNNDM7HEFIr4GGCO1rygNmTDABcGX/VziXWk8ZRmkHMYzzJoV' +
                'lYRBcvjHnrjcVDK3k3aEqZQ2wTokkM9YgCsT8zLI71nEQq45fO1PXPoc2O/jq42C8uWslU0pP9Fq2CPokHobfU0iSfg88EO2A8ud2Hn58z3eLS8nNtgmdCpDpB+JHuLfb5iZnRtsEzrUrUbNPfQ2+rs131AmmCXAlk/cqoE+bYXrQbBTfuWlxAVAunWLFghHpBrkO+e7RK/juMQp0GcXl4GZk7vun765rpqN0eyXVCHzVyzdkX5uMWOT19rir/jOR6IgEjfcUzijI0PeyQPuNXn8VsSompHmAbKASNxXUeASlvVk5Lfbe3X3GINRWXoS222VUr3OLjMenbsjHXQwj1INcpP90yLZ4gpEYQwwRnf+7uLStOrUJcow/e4ggAZ1YerKSkcBWhPnSv4UhyZOMCzIg7J78RmlFmTPWbP2gtyoEap8HnivWx1WJvtkjcOytz6RF99bzjTQX3zwarVvXf0lfwrNEycYV03I5nbFKp4HOaflLriqmlSGVT4PPNmjVv9IrqqSe36+dWUlrY4th30ObPn/28hBOx7MoxRQyplpE74w6YPoQK1REAmVbqccsbW2ui20NU5Eab3KTiWgBRWvUoHKD3Hh' +
                'dEWYy40OK/JZP5sxKqhjt++zim4ppPxja2qjoEwtSp09lesO5r8x46KRw5YVVL/VGBacju+by/URXWi8nU4oRrqHXxj6z3Qg0e38uLbiPr2wBzby8eNkroTZKc5libb+cLei9tpPclUOclPXXG1JKQTyOj1XQVmnCoBp6gssEI5J0HPFa7EaEYqrehk55P/XzQlaCw44rO/J+2A2WXn1SJK95pfWfzQix4kz4QUUvGHhwdm5dcm1StImYWDPG82AmkSS7Xj9hnGzzKsqiBqXk3LOv2Z/4dCI1tRbXZhalCfIEagFjD9V3mX1tDGWtQYZ90+WsdZwbkOFnR6Ly0PTNlqrioXM+j2E+ce/mcKV/P2iH9Wh3ktjD82z73Y7i0VtgD9Z+Hz3w4WyfHO+XzGRPJjjrGYzsEghv2FnTCa4+BgP+8mVxMEwyKqghiAQdhqYYFfzQiEBFqr2PHYMBlTMNS3bRcxmfZBCvPRalkvUA4Jo6KDD7zxvPae9ktJp/3O8KQriAgHtIoe33jTN6IWBj9kB7qfdYQWb1vonMhmgNVPVbxrodMzOyeoxJFwug/VUcDRVXaB75JnOJtKsVue+9/0WGFelBU44' +
                'ag59pFJ0NtFb2Go4HN6f8sr3dWIxdwwysJqu2eJ5yNBd7xCRxgZ02xEQRqJRXlBFI1Ns5HKYAvzFDLz39bY8+nOhaIfNFx8DfSlBr9nyjb0/Xj60Wk87nYTu/jYbZ3FAPbjj0+cHYnEaOij58g/SSH68fHW0nnYndOXyk8frVlwY3PWeT0eLpAxu9E+prctSxpmBLZjax2B4iwbcbkadDvxl+Op1IexOMKX3IZ6OC1Ur7D9lvKV7a93QSWm68bdemZBM2+OU6lcUsgHR5upA9ruwwIJBKErdUPIEY7+PHf/o1/k7k8usuE2Mto5HfIbowd0bOZImjj98WqESCdYvyy89mKvbNcmuZxNpViv9X/UVweFsNs7igB1+su3485sX2pTTfbAN/gGHe8PsdguK2suEld/hU65EBaJHc7e0ELMShXt4PDKr3463cNBoElE7U2c5udLj5mVYTVficbJkaNeJx4/JhJclqTW7+n0a4QKLFTej36ZBiNDNXZvDeN56Ssgsmk2Az7dCd38bg722IHLSiDodM711XnotS6tqj0H02qtruxyV2ZBc/+f9jTG2g6pkIhGbOB/ArvuEQgIsSaD5CMZjAzrj' +
                'pCivCASTiCat5Bw0GopTx65xIe535qhdxH9cSiWSnoy1OOmqVc3YYwY3eqna2OspoYroe7MnmJVu39pqNeSEFGt9nRmCUJSn1Bz6VaTobL/lyu3J6kLFnKNsNRwOb8F5UYHk3m+rv4n/8MUwGE0X1J1B6xWEBFiSHA1SUCjXOWHxeOwYDKiFapoFcQGO+BHNQJGifD7178wZrxUjn2Mp0jR0UO/5HrmQ4RtKB43Sd1m5Vh3l/GATMZEvH1otqZPAFlTctluiGRo+Ld4JimuZ64pm1x4PguP+jFGtt9VaCNdFM+UPiUH/fwLm3We9SFns4Giqul321S/CSCbj/0p1pWw5Bw2IrN34ZIZUjEaRpG/Rvr0mE1x8DLMPkwOPFTNKgtmEn8G/mmmcMguoVCD65PpSgkOv+QdnntTWz+loowi4Jf1YLESxR5t2kbxe3LO7x+phkEj+ZRYQY6YfgXryM0fVOGg0CaaTY8LOmExt7TAqn9/YbIHZHXseOwYDKmaUZmCJ6/vZ/YMKWY7mc3UgewdEmhQK/ElfLKilcbZZMjQfmG+KRbvC+zgapKBQs3LCVCOjrdgfrzoXJzwLi4a7bP6DJY3IabWi' +
                'KHkCv9HJgPH1qUvWazg3r4iACnmyyroSVVBDEAg7DUzfNpQOB7nusgTRp85nkLLFYSQT//EltNwm8SuXxSwST4YII1GmLyis75NjL5k35ec1B7BSKTob5ucsMK5XCpxw01hgQa4UJeDeRXSz151MxJK6IoBAxWha8AsMpdyMJxy+Eofx9pxabvOeMX+x4NyGSV0RQCDsNC1pm0B+PxjNS9yjqdRq1RUoDR0U8nmJaSQAAAAAAAAAAFk+t1+hlsYeLk54FgsRa9htSuewWIh/juZf0BOHLj4Gem3bu9MOxOKsl/yJyq7xsQnMszweGdvhifPqxGLuGGR3cM9JqoetxlbFfsplV/bWA5U92m1s+5o2ko2IRFbgfB7rjzeVn2CNMdYXnE6qqSNvrDrX5cAmYkMEn6ZTmRRWq9NmncBSuO6vAsFTp8IKKzzLA243I8AHk8nCPZDhyizDO8ZeL27X00z/VjOXWCSeselOZDJdaqY34W01lHJCCnn45mG+Yj94UhTZBALHRBNILvH98MiWWxP2m8XsFgmpDogpKBTlkr5OGYtUKhB9cszAD8vrr+cbG0nIRCIrcD4lZBZNqEDp1SDGUT4f9Plm' +
                'usMgP5EM6Kvy7dHCYcR+8IFMuUWs02Hzlf64lEo5IQVcnPAsFiLWrZcYZfP3cXjpvYe6K5vwofREQAWyWWVdCe11vkgkf7wLdZYSLhfP9Cq0SwkXhel6FZZrhU4nVdqf7uCDkkkTR5EyQypGI8ZSuahGW0etPkN0+LRfJBKxXoskF/bweGRLo/shYv5/3aURS7vMJ52kbcEBc+C90CSidiIgjFmivKCKj8SQbbg2803kuQ10OmZn6nFHteBwX0bvJ4LLKhUIsDnsBl719FsefSG1sYPP0FsQ2+czwGApXHefpzZyOUwBfs9VMhGGwxyB2HIOGg1Fp+07j5l6Pd+JWDr8ecft+ysu6aQZhkPvDs5fCc32e04tN09qa+n6NN8Etq3UcDihI/mNIk0KBX6qocliSLhcG/eo4/2XYDCaLrULKm5bo1GCDetCxOH+p1cilI1YKZodg3N/z5zIZLrUUaVbT7XUtypQCL9Tgc49eZdGptjV5C0E5dIrgPx+MIeWV7aed7VzVKA5aUQdgJfQtDMwyvvz4vDP4o533eC+jMNisS4lnElPRqbOcm+529HKQeJCwe7RTbp2Ay/0eqMPsEWyaKk6zeTM' +
                'r38L6IRUnQgEg1SzwUaCY5JUNcLIDv7S7k438n/f+6cWejOSDGDxTfsSO1LqA+WESgyrU/27kAed6vY4D3iKGctI7FWPDLMqtZ3Estb+9+Dc28oi9PPsthHfWBNUmpxA4z/e31aKztOgwcgSQyLpwwela4FY+m0NdyeVebHh893ZsYt0QirABLjsLZ//q8KU9Kz4qC11kU97v2mx7ytoeMT2L69Iesfhds6AnMZ+XQxnEdiPkuTBTGJ7mdkkPe3+I0qlw9+2i1GQmx8VJi2/bU9m6gVLYry1GuLPWlKqaui+oFP70M4BSO1oCMDmYxTJQ/4WzRWoJxDNBJIxoGlw9ue8imyXzEywM3zoNfyzucBl3vJYfMeA81IhTt5BMrtQlfFeQ5D0k9+HCDliXdLg8UExPBr7i2avkXIK8FGyEbxHfUJ+1O6lcy47TO72474lgmJ4NOsLzEOcA+PdeOckyCh3MorZhn35FLUZReJDsPJXSw+I9+uX4oi2+piapJQ6GcTwaMsWhYZQ7mQJrxH6733zF9XATqukelZ8VJi0xqm2u/uAT0IYjjzCK887xc0L0EM26qo5dxPwL6wb7DMTLCUG26fw00iN' +
                '1+Zda/LDGh5eubIWH/gg9YQuBlDEbg+fcWvrHZ6EMAGpM3WMqzFe1D/kFP2ieSJlJ8nxcB7wCTJzpMHKcKdxvpQYS6bnaz0OQNgp/4wUyH4PvsP6x3Z0yzYWqWNKapVyjxORGcJe+Tf1Re1NWuo/nugCSZZQujh7ZDfnvQtYLiLmVZ+J4FPiYYCtUuMFKI38bcVaI+NLmTXeFOD1GtCtCcY5BXimWYZeltdhcQlIfLHi1ss6IRVgAgHpFeV3n67RrbAhP2p33LeYgLduuaGmq12fjSSGRM+b/V5FNsVmJljxxrn+m6y9/erNY0G+mXnE76ciFwhAVXZRB3Hs2I5UPsK6UctnHwQ9CtSCrHGvWHn+eHoEXNrJNrI4rzOOBJrtvYZsyUly7iZhXabrvYECkDKV/dCLLBcR+DQEYHO/CurzCZMpdY/8QhyusT59z6k0uiMHSBGIgysk785Ch0zmXA5X1h+w6doas9G61vmbNDzAdXsciTxFgitRDbhAOpKXXHaYwfHbYUo+DQEY1eaMtNYPSI6FXLTPrpYeDfPLM9k6jlWrFKAO10IXAyhiN4nBg4tt0ZyUYpKJX+997Ts668/LuOZOSjFJ' +
                'Bkx+ZC9lw9w9Kz4qTFpj2lvT80CpIQxHtHTRV6FhWTGsWTTaHehyZm7jZRF693ZbyG7TZxawXESbpohcIB1JxbkFOHqINGxFExByxLq53f+/SUYep1GvmdUpd7wc4FuhsPeF5GAn21JUbTC6bld4jDBa1wdlD1auyYfGgmEv8pWlq4lE9fvFcX7VKOdZ8kTKjdy7zix9uIiqFUq+Mo2xuh5hm+mT7OiLCfK9nugTtxd0AapLKF0csyGFjxQxlcruSMOBhBOY0bj8t1DTsvmIiTmoapmNHOG5H4iODORzRlp4mVaDdpeHFgLPKtfuI0G/hccTtbPxoU7/kW/hK0Vn53waAjC30QV1DJj8yF7Km6Wj5/cg2p4GrWpgMaK7sfQ4lz50lH7X0mAs9GY5GMD/ml9Qp/NoZ44kNNmDtKRJ1M1orxt1VZK1h388PQIubeobq/xfW0USH2sNcektKVU1dN/99RBtTwPYCBuoe5+MGcbbfqGjrAmBu7vKEq1mFy36eXBDZgEIKccXkyZ3e/9fnAAAAAAAAAAA6yR2pMkG1xVyTdQvBzjfb7dS7mU43bZfN/+8hj31O6OO+oT8tcFX5unrXHMnJZaq' +
                'GwvavyU1xDmG4SyHKk1OIJlpoovOPgh6+vsut52cS1UFakFWttksslo65qXevqKWIqOwJqgpJYBTyFs7Nq0VgbEekAEXuHWDxR86Sj/laTDgGeHtzzYhveyBHSWR/LoYRFt9TE1SSh2o2mBp3K7wBVj1zHIwneMp1MBiWWt/9XDOIq0DOdWfmFkc2ZdHAk34i5DFqgMYe1T2Y9J/w1bQ8NhYnpE1tW7VNTCWUdPWehwS+WchzSZzLtKMHD1EGjasSSqUYWQHf2ktHXPcb19RS28KcPQNaNiKYLSzDsoerEHTZQnYM4WYfQs9l0kGMPaonszJCpbEZXeiDuLFrQGofOSatV4OcKPepEKcoYJka6Dal7RG25Yvaszth9TX9t4nKrgYXTelPEafJdzv4VvLpsGcbvn+o+tTp2SjkxvYhM4v0lkLgXwQ9FaiGm2AdDkz5XOgu3nvDQ8VXAygldweI2wsT8aU1DfkEDZN9iMFMpHdMt/Hg2xCZwMmPzKZvO9uZvjNauV7b52MNa4rW+IWWTGzwuISkPh/k70gJ7+RUANpRg6QIg0bVimeJ2+uGdMoY5KMPFOiQy9wgv746Rue0LxveSw+7UD3' +
                'TEDVN9LeU9t16L+uX8KyYk2pwNKlQf0KTo//4Dz9EmQmIOSVaW+n4+Hw9Ai4qY9s0aojD92m2cLH0BCd0cYoj4p50E90h9WFRpRXm6NxC6I4QX98+oNPaB1HpNsKUAflIGya8UYKZD+hKN33NL1HEoFERwZytyMt8uCGzAIQUpMYLeWNvIkrV8qh+bD4kx37a4kkR8wuWun53RGFBCCkO0vlvraKJD7WVYQlXxnI1l07Z0BOYz+gBqaNtnZsRyof94rHmrTJfiHDU0QuEICq7JpPnblXgucUBbp7yCybMiAxpUZl+LZeT7G2Ufd1R/TUi/oNhXukZoKFqWxaoWqYu5kPrvkI63nJoV43okf0pi12hX3NXSd0HvjFC4AKGCC8vmXcsgH3orRmbRuYb5Qm50zJIb9TxOZIlUEKD5PZykIgzcyqZHuk70KaQGCJChhxDE6k9psys4vM2jYt3jVM05bcI7x8Wy+pwwm7aKqFGrPSYTGnNkjgEwIdxSlB/E2yzVrat3BL5IqneWXZhO1x5jI4b9YXNLuk6C1t1TirckVcIUfqYXe0sV2hq3DPCRzorJB/znK4vf9XyF39lyJ4qKTkTGprb5QN' +
                'OFGZW08f3+RiV4zK7XG8ntmIK7DAHSwKkXudXRE8UDuiwx4RqHZDxuRjySOjmcHO9xaGxX6odtyHtKlz4JbVCa8NVn2dOlgUtAwqP1ncxvQ2AviEldEh3dPh3T2YNkhK+UXnGqRmiOV1GFR+sqWR9ZNmWHRQwB2JnqgQGGWMBltPVAgMvEYDoy0DhMZRN7893DJQeOyGHirqMKj8eVc/9yFNIDDKBQy2ZfAyK4AWwwxpvpbdGyRwh9uV7pmB4WG40fwYFNnKBfiCDtK7zA3nKWPXYFBDDxTHO8yw6KCdOg+OQHZNVz9UojnRdcHhYXe9EvWjfHNPH0urN8EvH9/CbVZIsWc5XNDxbATtFTe/QqftlxYdFDBAZX1sZ9qrcrgH7Bf6h7pO6Dzfr3nLAwT7wXM/BgVxvEY+eNYcEofpiifQfPSOd7StobnCYlNskN0m4kSbWGCAFgWPwJrX+UH8+/rYzqlL5G0Oo0PyiwYI65+bEmvQSRc0e5qSh0rnaZwiGwF8QsTmnuA6TFxyDuOSVktun14+o5naa6NT9FrYPTXn/uCQTBskJSLQCYMlh+ldhCmAwA8UMOLGs8Cghh4okwh0M6QZ1yny' +
                'NB89rdQtbG/uCj+u+7Kljkruc8SQ3TGDqrcttbGhajSpKgQGXiOP33tLNaFoa2/MaiO/bvSmlWwZHLlrhRrTUlXVmNTW3jUayWBN5fKufvMcpsKjqYHhct4vlVGtelOYMCWq/1bI9hYVUh2dHihg2VBv4xz6RQc6GJxV8StkewsBgOyarn6oWXzsi0AFDBBeI1DlGYv5QQTvitM0VcwN1wenvuFtZ3+S5eMluQ3naZdaBhWRom5jerYR7xYYIItGCfTfPrepgaseuweK6H2swLeRA4y2XiMfD9ONRXSwVmBn7fcCweqOvrpfS+CDEjjN48R3ws7+vlwNzkhsNUwb0oxds2QWwxkQJuqe0adicyQDnSmz74Ll658o/ILL8q4CqKronPBdJ4ZDGqz6J3SwKM9HH54xt6k4WBvQuOOSLsi8eBmbQAvvBpD7cce/QvhiHzvrEEYDBJloPnpHtVrY3piPQmOmldGQ2AjHKm5jhFMGJ1J7wxnXy+uwRGbXKZeu5n4MCuJljHwU0vEHsFbIgHEiwywwQAuMinrhH9Xaztug3ts46YoOdK0Qk1TcxhWmC+kaF/ZVzBmN3V/+uL2xSb/lMCiviQrt' +
                '1lum9bStemp5VvCIKZcifhDoZlUys1L5DlNh39rO/jnOx/MEn8kBYf9itWFnf18ul1zPJtIlh/BR7w+GVDuvYy8eQe8Qy/KPUnImNbu5SoiujbrnM0TwTUEHadNmiP2as6uU3jS7uWaAExeSjfGqm6VkoPDFETxU8THUvr2xoRd/caLz6o71tUCHhUnI9lXDfvFOaUTwXezURmPc9VE32PKs/Q1SM0T8AAAAAAAAAABfvG5ZjvVRWhbPNC7xqoUysDa9bds5XI0TdU/m3TG3Ervfp3otbJCUiefIrDpYKzA8aw4JzfpFncSuBYnH4mUhSXNad39f1GjK/WRWHSybGNoVAgMvn8nhiGckNpQmg2k3ghQeO6+JhJy11TEkcEvp19tKbxrT0jOm+YlDKpPZv501OauKDuOwU/LKrxXH4tFuGSg8dkMPFT3r4pNjhO3EXjyCwyCL+QMzuINMuUoT/WRw3rEuaGtVNZ/RN3pTxDZhyqV5AvNZdQQ6l1KC5Zp5/X9wSCaDEpzFLukTaZzNeCi5/w59rI0dVFV0TnignUPLfYjMs1IzQUS9EhtKE8+6TUnNJf26ThE+dssgjAYILz/2J7oieKB2' +
                'wolX8gT7supFPf6B5G1n45TB5pU9p2IbLINoXP9JF2TzLBGX/E3spSsk1r2SLmj2sit4RJrFET9I87bt0SF8MS6erXW+tVrWF0/YtF/ULWtO1OSWEjir+pLmtO7+vrXQRqDXMgvvgghHIDuopZEqUST3W/jmnj6W8LE4JBPPCU7+4ln7yQH3dydqcksJHNt9vfj1Ae51R19ZmzwiTeyGkW2EAY+Zwer+dJi45BzbOazgWV5xIXxbtyqkOic8UMCv9QtD7D9UO26Djj4hYnNPcMCUkttFB/9Ycr/qn9/C7mcRaIrPnM36oBqBkNhqmDa5esvZO8YVx5XHMyw6KGCAyoY0RelO6H1Q9pZqX9DW3oXprYFPltXaHHCiL7aePqPVCmn2jVgrZEC4Qo7Jwu51f2BKSeOsjfEsW4b5CwwQyyPh2bLrjwLz7ik5E5TT0iVEyOChf1zQ1qq1jMal96JurYGT+wgjjwLC1caPRlsvn4H8/5zSiP26xXcFkVfzWdxHHSYuOQf/SSv7WCIz5ZrFV92yvOJC+LZzJXe3Ykjgls9vmcSm2D2nTMEUfkHreVcB9IuvdpEqkzc+8p0kmywKGenhYyK2+GIv' +
                'VTaZQEd1f3qfTVbVpHsLM4IlZ0ZqoRdMuPUFfesIL7LMSMEL9EdfUzcwiNQnXew6lo9DJRgK7RAXPSMs9wFhUa5O0J+Ub8wT/UtHQcRTmHMbWz8N2ZM3ZS/8sJZ7ZEBS4CN20gqJhAyjrjpwMpsY10GcvSM13oUm+v6/EVt8MZkDlwdPhaqbDcWK1PtINrlwvsYL4/xBBKge/zbcS3CHchMf3DPthFO2CETjPjQXZNMP8RtuqzjNOWQ1Hwp3YbhaO1aU9QnPug4whXCEuHJF0Eevs70il6488rpcL29rVUp0vcR2H09w4c/fxkRx7cRe5hB4TB3ArxZ6yinWPBE/KC3tQRd2qFmvrF8hHpmj1e7UhPlJqH7zOzzjbKWW4BPk0SDwmDqdQyxrxARk3Fl1Y2nV9eXRlWyemulfBDaYuyTJ7MjaZqTvRNaVCMilsurGxAwiNcBQO4A4wZO6jGUhAxzux11GvJ6P0zEBGTdRWtHY4uVohuylD7E3EI1XecmRcJ87aQXKQgZP61CDFoDK7+xFavMkG9I4WNZzr+GBq74kL1Tnytm/jAIR8YENzBn9kLxNuw9DxgqVGERqnaB2HaG/y/E/VwEq' +
                'K95PiWHhcrUnuFOoT3MkgbCx5kPfH0thGMw4Qlw5rGjSt/fXvzfYITEDhkowFMcgFKokY3Kr+lxuYA21TrrFdDlHZXQEA6PzCcIV8Lxx5iMqWLlH6YfwRXtM3xi0d73Ylwm165Bsb+BzCDwmgGDZC/7cQA5B+QN+KElIxuRL6bhyjsroCAZb+wYzDp4XSSsaWVCFYWnnKU665PT85sQ2T8p7z5XjDnRJfX/RhqM+lsJSg2EQ2FrWkE36oQIbTNMSkTq7dYclRPrdRuy5FA8VGD1lmmsehpEUwj8sq9cZEJrXE/4GLdRoNtCmBlay+8HcIhxaed2QlJbv0m28obFJNQ537aAjXk/Jy/05W2to9rkN4OrvpvTUxAQi/x8ahTLn+Wm4Xt7WqpR/biAHrvKPPzrQYjuBqTj+ZiTui3qtoae2gujdyFZge6eMxW8oHiowx5slekX6oI1bQXTgZCsws19ji/9+rgJUS8mvnAwF+AjOWTCK+YtGro/FjanMVcOIgDSWx2dtDrHzPKrh5w3XurtiAjJuorS/1QIPhyAYccudXKdUqbcSzoQWadh96DxWimGEeF62c59CC7pssHQeK/EtW2Dqwc5H' +
                'dqw19xKDaRwsa7fZ/s7bX/zNsY9MNRqDH3nAEsMWBYLwq62uYqdMt+GlgByC7wb8Z6IYRfLLI1dRFGZfXfBNnb9A/S10J4ZYoDk9P7cxg9oFpAnRkuOwF6n7KM8LQGX5JamiKUK/PXzbdeInA0Y+ArMm4QxatdBs55aOgpWmLea5c/OzY26tQt9XHTgZwwzl7lSbcinXy8USmSr9ZeLRRvjvTpBWsChktwQeE0Aw4ovALt0q2tUJZ5MrSvSK6V0Hb+b7e8bcR4Qjmqy3VfYWZkAaS+29uAfWSF6o04mvYwWkG8IgrbSxPXU7MriXKfIRmX5YS7MyICkdaDGTztocf/9atsDJn4GOFrvV4n9n46GlnTTuJdIzzZj4roU7VKLZbfcK+ssQXnl5XS6ZubukJY5De2dEM0F4AYb2zohmgvDr8JKjuzR70rzX+mLxjR1VrdnX0BHFVx4L0+Rxsb3/3qpsL4CO6v70XuV9MfbIgKT1D6R/8ET8oBrdycNR9bWV6nZkbTNS+SIAAAAAAAAAAIWQnxb1jr6mRilFc6rxLMwKVRK/Odt9Lnjb2Fcx3SbVKc++CGwta0ghi102WDoPmxUs0q36zXis' +
                'g6ORiOLHlbzDudplX3+Sap7LoBssHYnDB7X4UJ8vqep+6NbJJpQNzza2fhqvO27KhgeYWXAkJav7eEnf0xqzaUx8V8yTKlHi2WQTpg6KJ/8mPqVmxxWmcWxx/DRDdtyJSk9ZUoRjevja8xTpiyC88lcnaMFKuWaHEIjbfGguyLuIcHX5U3pqYi56RljzAsKiYZEW2+WCCE2ofd4BgybnCdzAGnecaZfo7cOcPax9UMimCjOhoHiowMGoK+RSs4uXP3Rr6hNKiOmiKMy+uv2aJ6vq2U4GjHwE9IlSsXgiflBc9Iyw+wSZWWAX4BVt5Iq9RDi08qc9NTGMUormSf9YhbUV75JN/Pt2DGYcIS6SVjS0kxlcxZp5hpzaUZoh0ZA+MpSBBbW+XC0ZSs6M1F8umEONTKI4Epzbm2+pyr7+OdSBsmAJ7wuMQd7R6/aRpY4VTm2mTZ7mSB9UsG+OzxP9iknYXh0ByeH1r8gmURwJTuP2mKMwde5nrVrHgi7sTbJDjdR8KMGZ2nWJ9oM32xzoks3ON8V8Id2jUwWX3lA8VGBqQvKqVD/3k11yen5zYhup4jKHUwdFnfFWoZ4Pwt/kd8Yd07TNnCJ9' +
                '5Yd/A5hqNBuUnrKkFcb07WIGEZRgKJNAY4DnWuhOEbCL53K21tDxb1CSkJHVls9t6GeV7D6e4N98+SdIK1gUMshqPhTuwm20cRnNp42swPbkAYnNEAy265KtvDoCj9/3sqAXwtLTUpwgDav40FyNazSnj5ui93c347RxnY8jHwFFvkI8L1u3wfceVf79iOVdaFMDK1nz7m5ls+nE/wc6qncqwzma5evsh4Ful/hCp1sRDi2y4EhKSzMSd8s92N7dvVEMrHnrn6U1IXlVKpH1x4qwqWhG4GptQ8foC0vwszoIybNUaxYe5TnxwjXrqZC+wb7yN2YGx7IsIJIzYUVpqusBUjtvwyialGlTq5Nazt0nKDj2PhM0DosEVeyhK6BSd6GyxJeP+KKlUSLKE+VAhiJ2E1hi0/HN243f3gi3bP5dHhLInkoXig5WgWsDlphn7l95lTMD7Vmv7XSLq3jXHW2Sny35PlPu9dio+Lp5jCr2GbFpjjnPa5Xdry90kQTi7CqcgOCIZCfOXI/YgluV6sTg2Zk6xgJxRpnDpRcwdvk9GxUfUKKfQp7VBeorx1lGNGZaz9x/S5hhsftTKSNC98chwAgOhkEw' +
                'hpPNFpb9e3SHJzGScTaxS9NEbIpjoXIbZpo16KZoDkrKtljyOVCaFqTl3k70Loq5N6dDXug/CNkTTmI54mx/loJ5Gjwt9nSIP27wCoMpFjyOWn5C/etlkVyq7kx5gd21GfI0eFrx6A0lXd3j7Zi9cFCJijKpnMysKMpFGdpOZlauWYgPTLMdIg2XmPo31tsmMvlo8LT/zRqgDwlkTyWFRfo61RdeJN5y9GxUfF2yRhVxPoD7/w9+IHhDzytz0qr6vRfqNq7fYrT9ERus0W+Sz0q6p9vHLWfgs0FrXa1J+tO8oxaySRSoixXRUAaK7PkU4nwd6+Me/EBP5Ix1m+2iI37c/RQbUix4TlBw8XwmaBzmlsrBWBXzvDXSpks7tIGngAz/Kf59/fYe2frD1bqksGwmY6ke9ZnRA8EZkTRAQ0H3rU3tafIFVM2dlkm2G9aryMO95+rbE2jRMYmfsCr7ZR0Y41Lh+ufx2jkjWu98psGhu/XgqO5PepE3eAXPmgseMThxYYC/jlvZ+DrL2zzlgAJ15RXTi4l+Ry0/IfD7vMYtlG63ho6jlbo8JI0hlC4J5yI2Rb/eOYP/ZP65AuQbscl3QWMNENlX' +
                'w8sXIrWNTsyieuxxnK4MO5n+y1GkjBX7FGWsgm0nMyvhvQR6116/AXn3M6+UGWDFZy7JbEGjxHXCf+umUkaE82Tv0P1144c07Z5gBAdDrhj7jimTue8UTThFPrEMYlqBaXhIB0I1XBJIz0LOFKbunhysH9YGMS3Oe4LWukeS6budFBx7H4caB1YWuA3BHEouuEnBmPIfp3d8qRgByNmlBrE0jkh+wnOtQbINHph7OkR0YKtVo8+744TmKANFdvIKG4fRbYl6YXMP4n3v5F1SWIPN5rjKPb63DCNkftAdERl6Nio+oFkjhLYfQPPxiT8QddRX0UQEcdxFWNo0I3A1uNymEWWH/CBDjZtn08mrJtArC1yI7g4lF2/nejgqtdqQJpzEctnY/jFjxB5G+qjLibervHcWQvUvfR3khS8SbzmoxrowJDOboGAFB9fO6IjIj+6Cxhogr65XokSJJteAEfyl5yg2pFjwByvOu49LTL1Je75K820koTyv6Zu3aVV9EvqevQWntanowEuqW4Nr20JzFI+sO3kFkIOEgShRwSHlV9NQbFWw/XL/mWrLTz1hPtoMjmTi3APwhoNW5rlJ6QTq1yq7Cw/8' +
                'F6S1E1lncGrjyOFvBNU2f/hPMAKNr1cMGEbI/L06IjJbgSD39sqRCNRvojHs6j6mM02UdFM0ByVYQDlmworSSb7W86eanyH1aMy0g6X+li3QhXUbV+ExWv7QAj3lL9GOSw5bXyDmrd8aMy3pbrGrTKPOEPV7ZcYEEI97qNYsPNerB6OhEHPY4WsNrRKRvtVs8vNmQzUywJcuVXcmss7g1AAAAAAAAAAAywKkdt6bUCnk4y/Ui556wnNLZe4shPdeblOGvM1+EK8BtPyE58vKP8/oc1xlkF/VNhO/2g/0wuYRO4csMef26C/hi6JVBSrr6XS3LrxIoeQKvFZBuJ2Xm7RqpeYiArZuROwmsMS7/4emkDtbJ6UDx39oAZD8meZHl6hKOqcajZzdEu3hYDfqfMVUJR3dDchOiMVMfZVr4xNNkWlgSGYrXbCAcsyZCbmStd5ZYsXJfFGBuAOtGbY3ybL1l9lKgjDsCwiqxV9WXaTxMn/SAXKD1q2YkZ54815jarlRlnZ1H1Mk6SFnClN3T7n9PRwV1G1IkvZhlPvaSF9aNdxzEQFbN97T9HBUd6k9wAoOs4HNDY27iNgJxl/kNhYQSZe+rLpV' +
                'IbcKyVaTsoxZ9MXiJUEYdtXbXrULIfSZVdehnPVcCW+pcka0w/hRn4VS1IeivTg1VGNdGBKXw1Ajwu/chRg78p9h+W7MDJN5U0iTo53cj+1e3wtZqgpUy6wsbRqfOJRc1667oNiqfecqv6AMCcXvKNhMxk889y+/IAP2TbFYeLOnJMffwG7J+AafMj9ogIaCzClqzVHQHJQFXiuuXMDFw2Jw4sIdYwG2O4QnIDgiGcDS8JAOhGq4JFL8byd6F0XSxpU8jOlNiw/gCfj+MJV1PmVbLHmSKE0LmEo31UNH38Tqta6/iAjipZo/0sCQzFa6nKDg//hM0DhMJZXkr63hYt9nCPSzvGMCv2IPI31U68qTQp0QHBGCYAl9T9CM3dTajC+bVy5g7O9winx/GMS0Hzow26Tf6dP/QAbxmn+w8Htfa/fdTcGe9B9tBkcycW6P+fvMhmpknTMwjI3lZ3REZIlxsPlyoCks1hpHJD9ht9jv64UR1MgnZpYctr5A0UejqrNfJfe4Et52FU5AcEQynVE9drZOVwaT80eax9L5Cqibiy5EdwechSl+uZ09haxpfjfmLfx9QMN3byWk7pOeW+BFyFDdj7Wt' +
                'hu1bpxH/GVLpHQvZz2FrNTfgqyVuQI/7lgf2wDECWnoLAvXhFtI8nfPYSGv7UGUMYhz/J8QIdfV9QMtx+l/TSm2qZhbaopBin181SSPshOLshHw9xQfDswJaNmgEPOIFqL+ebE2sCxn6gIvi6b67lLW5nFJ3x0+jeNm8lfA5e8zjMuUM260mJMdPzhKTMnl+Fyns6y6nCavC1rn2mVTR+F2JjL+6uFUahZp2+xfditsb6FiGNi9/tfZBP4/xNs2K0xEPpbu341wKL+7VFMxNEegwEO3Nfxq5oedd5V9C1YHu3kpVwTshtvL1U1/5ThSADMG0bRiIdh684V/bZSmROy0l6JdacYHCcYF/HOLXpVQuUsXLXFMSS/n3pr7vnCgdnnIufSHy9W7OFw2bgdyn5g6bggUctJQbHnEvYjxJ1zMh5Fz6Qvn33MuOen+Lug9gjpiDGgEPtkZHTM8NjolbI6mShVhPsnqVjMK1cgUzVENC1bjphO/zpQEtGzQCHnGMV6Ziaq50GAv/GfwG49gTEjW6nU1qfG3+ydRMF4+G7WVQZSPmoC5SiAN3LVwGIpOJiwH0/gtpHsD42r2K7YJZkUxOOuyYW2e+' +
                'sQ3wgn+/lqlqaSea1Pja4eeGidzT1f8ugS4aKx+lU9H7rZDW66DKGBrFQ7I0MQ45FgT33yy5eCemJBxpURifAnU1E8zqr3xeZPKln8hMTvokfSseSJ9fWttk1xirR0xIefSnofInCkAVc9qDKpvrrjSXhnloYhxyUUg40qIwIwTwr2U3/XL2hR0GAj46a0S6Z4WIw85u3XNmqJP3zHCs/9TSTim17anfOFYyFHDqamwHw0GMDlpKgyvLsi9WNbrNBLRs0Ah42QoG7lq4DEQ7DzshH0h2yPnlCVjDiRLu3pjRSznNv4sBWTl7KSBy9Bvgh8BAkxPhaN6tJumIR8qjn04UDIScZ4W71f9VHbfz2FOgykbRXVykDc1gIMeH/jRvhLdtzxXD+1fe/aD8oSHkzkuNe2CWAS09msZCrSmKLGQIddi9EPCvFLNXxup7g3SsTWMh2JpFFjLtqWcJxxmyP/dsJLvzKLwGxmLVJpEsCPI84l7EeJKzZrl4KD9vTzm9wIyPnp1oM/1PORewnnn0N1k94G+ywIwQ1oh4QbHRS9oZsm7uMhOdsLSUh2Z12T4vglk3dxmHwFiQ6ax4PUZhdfGCfgP/bIcJ' +
                'lF3AqDU+uH9FFvllirW5Jj+Vc5h+sCDvuFUzC21RSDEq5qkbVCvLQWMx5BPGFgR5QI+OgYDTEaDv81FhwyVQOtBmIvm9lXDViHbZog1LjUmlUzE1VzoMi+Fo02TfkcQh9BsJ5/UKL48SsJsPJMGhLdpJzCypWT3EH1w0Vj5Xpr9U0U82qFaLgq983+BD9kGa6momhclD+Lzl3L+01+kdK7J63d55nQUga0Q8rtbmq217rpHJ9hvoRT64aKx8rlFjEce2UyLjMqTSPBSRuamS0I+1mC4DEcfKcKxkKODJ1NiJW8KWD1X8xXZCPpDsje/Xb/BQft6ecmc9z0XweozC6kqgYFSUH1yxWBD7W7De/Zxe/qHjvJrGk27dS0rcgAPrdBgI+OixDdIUXsG3KIWaIii8n3NQFylEJwoGQk69zNOXKu30Mxwr9gWZd+QKZqiGJVAwKkqBLtbdio2gpwN3R8UV+HqXDpt7MCPqqWAaxXi346o6c/utpg+2mTEequWXAAAAAAAAAAAxDvGdYgS09CKTcaZE22RVDeyvWRqWB5JcpJeLuKYklhwrGQo4dTU2QaKVtYLNYCwyedzBZCYnfcGhlKqfdkJx' +
                'E52AOybf0KGuUcTUQegwFtgT+kStZd/BrAvyvEXU0hMjvmqSRsUV2UnXTQiSPc84nQUDISfQZucvf97/Xk1jx6R+KgFVJH0HmbFv8S+ov+1GYdQ5jJcqr9/Qu8ijP5VC3KeWlKUdBsuwIOu2faHnJboPBWNpbao05PGkgNX3bKfEOONOlRDq95OegSQ7ZPL8je+uRgctJc8sCPOjWG/wTtelY3WzzzpWIMlHzkDnhlBD+KPdhvGCKVaLeV6sammHgAMBHx27Il31NhLT9xReAxifddowDew8lXDbnDcgyfO7Ih5Xa3PbuHL2UkDk9TbdRDviUYiryKriH/442bNXqP1Dym7n5PEXyqNhS4mkfuz+NOcy4cZinoN0LEMbmbHUzzoWr4PC1mqq5agESZDpHCYnHXZMo71fkcS3TD9YEPl8bdBF+EGixn8a/Rn+YzFPyPlXI42YnOmnCQddUwbujlX8VAKqSPoOSPpWPJAjvrRl376rylI/dmyHfSLYvOHuzE0784XgReO+u2mzYRVzPhDqrWcg/UMots6xDnHl3Cq9zETvZzfgt1I/FY6kErCNmJx0xS22zmGb61mZK5Rd6Ios78oJd29M' +
                'o71rjVt+N4TrRz2xy12JMMP7osKbSqB0nCgYFSXOF2toMxHy0MQ45F/Tute+hLcf/G7RWuX6gJs2zbARbF7+dymRhEdSCVjIopBwuVlgRghTEg66pgzBAToMBHx01ohpaR4KxtLaSWhz20l05utHUXqDiv30BZnJWkrNM7TiH5lgRslPwDSX8OarkujRy46iM1TH9WY4VvHZPuFwr3uuTWFr0nvCKuZ8krOaEDl6g3CryLMwS46YkL+WcodjCwKyW2fWB7b8bhXQMcOXzlU/5ha6WwGwBrUlqJut5ilucMhqH1Jdd9NDW24QNXBXPfoLZg77Khf8lat2Mnqel2NL9kutnWRiRYv18YMMrtvD90jFyPVCZpEx/5UEShzcSLDLiSli3zz4uGawueII6TDBNaFPs/BhGnZ8jSYF8hwWATbWtxki/sxUnjcIlDilkH2LC12jjlgD1JxaW8yc6m88vO2uJG07c//l0rh+D94i7c5eVKuxyoGF7B3n+I/oBWG5rV4ahwE1oIwvKtvWZc7MdleAtaeC9YNYPtyKLu3kez/J2Vw1Br7nD4O+ER1sTgXupgO5CVk2dBAQPIG0gJ/eXSxptgJ9DHdK' +
                'OZCA19XIeVMJ1B4WSHQGtM3WOxgmUF5f+Z3C9JsCmOic0FQKlDy2f7yoS3+JHxfFcj0ds7eN8qZ4qm5x5ztPLhQz5pmgcWcNhPIb5FRiB4KY3zMntNIPL/BJ3OLTdp5c22xgGZZW63pkh0ayB4tHgzLNI1mNy63PHqSVW/DH2oXpoUNAG51Gtf2Spdm77CG4yBOMeQ4Ljhsu4AuabXulYvhXEriTt/H86yj+2AvqlJ1WSmXrikDqTGyZiOhHSigjRTWJixIdjy2r2MAyMazL9Loukcq5hny9eWC+Pe+OJjoMEal3YC/W8MtQ4a0WyTUn6uIulANf/YkoZtEvXeLOGv8bGEGrm/OQn5M53oz+DUOWRyfIxIoL91JFAsaqrlMcm5xe86wQtBNPovpJQqsypT8WWmLlURIrx0FI2nbm49eSSEDl5GSyp9NyrkPWl4TaIztyoQXhGoakigSRSUGmOLS2hSXJ3nhl3eq6rKbPgAIKl3PCULa9iMKE/7tevTOTi6DfRyyPak4q72y3TZUcMkJ5g3IqMY1Bc/fN/784m7IHTAr5OCwCbIpqDwskOgNab9rlPF+Ikx/Gi5iWflOKw0T/WccaqOY5' +
                '4vzgzkOekimiDN4kedjNQBnon6LI69jp9Ea7z/OYJwxDs1M+IoTkVdgvDc2OlFBGUQZvErJs6CDnOVeva8VCbQgezlpAwW+gOxk9T8W/q3t/5mSI3xdNQg6YFO9wWATYgTeshXw518axczJE4YWoIWlcP4lvEfhn9s8GV+Pv9SQaq/J20Clj1S2jZk51uR5eAom9mBB30iiQwf199BNgjzxVN7b9k6kXqhIQfjkZouAGhtq1MJlreNqmsFWe44Juw04v91YIWodtU1ikT/9BN/xYdZWzWUisfKUJXMfV9n77FH9si3VKwL/rJquR3az5aJbvxWekkXPKmjHhHnxcM7vkQYaxMxWpDdt5O2iav+RwtKArp/ogjuR6OntzB/lRjOzVvhSjaCLu7Um5I7FE2Rdwi024s9wxYIghnydl/tOz+o/c8fJ6CZELLTH8pgmbD1LEo3jtbcxQzL9eutmBNGvVghF/ZipPlM6aUNT92d8rJbz7RSB1JmfEK2YfSfy/SSQg/HIyWd0DQ23UGMK7PB9uRRf4crORoIVjvGmvH2jUPqS67ruGtgHK0EwItWkUrJTKywmAyZhUw9hzmjc4ZCb+xcAtusrC' +
                '3qnXeL4NOz4ED2ctIO65UOWw6jd7spBF8wqxNsu0JWBiAZwHNxIs++hrkwwTKC+hzBzrVC7lN0tTj9KKohs6CBthIjrYnArBNsJEdK0lFJ96I9Pp90ydBr4h9ueZaMXtz1+GgDYnjHf3BdYb61qcME0rR9FS3OCNX557/cI07Pgkd3hYPc0Y6oZ7pnxEFdWqTOGXnVppiZkAAAAAAAAAAOxk9CEzxpbxtXxVacFrEXHBx5JvRn+Ir2VNlv4PPi6XFfk21ajEDhm4pyxSqfGulalRfaoh2xncWNJxBPoY7pRZGKFI8q2HgFzdFina9lfEgnTBUWT7bPrR+xPbxuBW8n1v2RDPYJ9qtj84vdmpqk09n+f69SbAA3S7xwaHFJne32MHNLa4Uio60+0DzQrCb/reryCDwCPUwA1CI07K4buFOMuoXNdulsQCJQ5uJFjrR7w0EwJqXQWv16cfEUJypJeN94TMP2LjuW38HqFEx4Ehss85FZbIrjGOTo2VCRbzzpVWzD6S5WM4WlCb3X0QRzWBKaC156+j5vOH42NwK3ngdV1WU+lAAXvpA6X/+fQSErU8LJDoDHUzB/MVhX7E24+vuGoMYdMe' +
                '2eXdgYYhOVJ3+KrSn9Yi4iW9qBQ1eHH+dXEXSo+h8MoTf+xgmF1lYTBEnsGdvH/npUDU3UH0zyzcIGrgrnrpFluRHNDi2lWosjBfkPlHEx00S/nsvVLGt10XxmXSQz7QGCJP7sBesf2eWemShEtkV5pWjr+kpd0Ho8YOaHFtpFR+LLTE16IkVoexdjBMoLy+QTrupjLzNn2ZFeNrvGdmO0DwPuo6Rl9pHC0ow+CwCK1OaCoFSh5bsQXFt2EoW9BE4b+NGltcKRXywGF6wwFMdLf16PHRHMNZY8tMSz+nRe+dGoRGnInfa+M2MIJLK/s91fR09uYO76L1jGuD+y1OGEZ25F8K3zQRIHgfdR0jobq9Ypszgap+0a4dd1MZ9xuw/tHIDaMumoRVCQg/koJRcCmsAWNVV6cOp8lpRVGDHQSOZWgmBNS6ChH2UfiIKrdJ133JbvZ5PYrvJ5n1KwQtzUju8LB6hzDJIvGi7Q1Uc5JhQvHTL9CXx0pnTShq8OLhgP18yXSMvtJxfnBnr09JmpOCkKns0duziOOykzRN0XInNBWMJQ+j1g'); //==

        // Variables
        var sigma, N, h;

        // 64bit tools 
        function get8(x, i) {
            return (x[i >> 2] >> ((i & 3) << 3)) & 0xff;
        }

        // 512bit tools 
        function add512(x, y) {
            var CF = 0, w0, w1;
            for (var i = 0; i < 16; i++) {
                w0 = (x[i] & 0xffff) + (y[i] & 0xffff) + (CF || 0);
                w1 = (x[i] >>> 16) + (y[i] >>> 16) + (w0 >>> 16);
                x[i] = (w0 & 0xffff) | (w1 << 16);
                CF = (w1 >>> 16);
            }
        }

        function get512(d) {
            return new Int32Array(d.buffer, d.byteOffset, 16);
        }


        function copy512(r, d) {
            for (var i = 0; i < 16; i++)
                r[i] = d[i];
        }

        function new512() {
            return new Int32Array(16);
        }

        // Core private algorithms
        function xor512(x, y) {
            for (var i = 0; i < 16; i++)
                x[i] = x[i] ^ y[i];
        }


        var r = new512();
        function XLPS(x, y) {
            copy512(r, x);
            xor512(r, y);
            for (var i = 0; i < 8; i++) {
                var z0, z1, k = get8(r, i) << 1;
                z0 = Ax[k];
                z1 = Ax[k + 1];
                for (var j = 1; j < 8; j++) {
                    k = (j << 9) + (get8(r, (j << 3) + i) << 1);
                    z0 = z0 ^ Ax[k];
                    z1 = z1 ^ Ax[k + 1];
                }
                x[i << 1] = z0;
                x[(i << 1) + 1] = z1;
            }
        }

        var data = new512(), Ki = new512();
        function g(h, N, m)
        {
            var i;

            copy512(data, h);
            XLPS(data, N);

            /* Starting E() */
            copy512(Ki, data);
            XLPS(data, m);

            for (i = 0; i < 11; i++) {
                XLPS(Ki, C[i]);
                XLPS(data, Ki);
            }

            XLPS(Ki, C[11]);
            xor512(data, Ki);
            /* E() done */

            xor512(h, data);
            xor512(h, m);
        }

        // Stages
        function stage2(d) {
            var m = get512(d);
            g(h, N, m);

            add512(N, buffer512);
            add512(sigma, m);
        }

        function stage3(d) {
            var n = d.length;
            if (n > 63)
                return;

            var b0 = new Int32Array(16);
            b0[0] = n << 3;

            var b = new Uint8Array(64);
            for (var i = 0; i < n; i++)
                b[i] = d[i];
            b[n] = 0x01;

            var m = get512(b), m0 = get512(b0);
            g(h, N, m);

            add512(N, m0);
            add512(sigma, m);

            g(h, buffer0, N);
            g(h, buffer0, sigma);
        }

        return function (data) {

            // Cleanup 
            sigma = new512();
            N = new512();

            // Initial vector
            h = new512();
            for (var i = 0; i < 16; i++)
                if (this.bitLength === 256)
                    h[i] = 0x01010101;

            // Make data
            var d = new Uint8Array(buffer(data));

            var n = d.length;
            var r = n % 64, q = (n - r) / 64;

            for (var i = 0; i < q; i++)
                stage2.call(this, new Uint8Array(d.buffer, i * 64, 64));

            stage3.call(this, new Uint8Array(d.buffer, q * 64, r));

            var digest;
            if (this.bitLength === 256) {
                digest = new Int32Array(8);
                for (var i = 0; i < 8; i++)
                    digest[i] = h[8 + i];
            } else {
                digest = new Int32Array(16);
                for (var i = 0; i < 16; i++)
                    digest[i] = h[i];
            }
            // Swap hash for SignalCom
            if (this.procreator === 'SC' || this.procreator === 'VN')
                return swap(digest.buffer);
            else
                return digest.buffer;
        };
    }
    )();

    /**
     * Algorithm name GOST R 34.11-94<br><br>
     * 
     * http://tools.ietf.org/html/rfc5831
     * 
     * The digest method returns digest data in according to GOST R 34.11-94.
     * @memberOf GostDigest
     * @method digest
     * @instance
     * @param {(ArrayBuffer|TypedArray)} data Data
     * @returns {ArrayBuffer} Digest of data
     */
    var digest94 = (function ()
    {
        var C, H, M, Sum;

        // (i + 1 + 4(k - 1)) = 8i + k      i = 0-3, k = 1-8
        function P(d) {
            var K = new Uint8Array(32);

            for (var k = 0; k < 8; k++) {
                K[4 * k] = d[k];
                K[1 + 4 * k] = d[ 8 + k];
                K[2 + 4 * k] = d[16 + k];
                K[3 + 4 * k] = d[24 + k];
            }

            return K;
        }

        //A (x) = (x0 ^ x1) || x3 || x2 || x1
        function A(d)
        {
            var a = new Uint8Array(8);

            for (var j = 0; j < 8; j++)
            {
                a[j] = (d[j] ^ d[j + 8]);
            }

            arraycopy(d, 8, d, 0, 24);
            arraycopy(a, 0, d, 24, 8);

            return d;
        }

        // (in:) n16||..||n1 ==> (out:) n1^n2^n3^n4^n13^n16||n16||..||n2
        function fw(d) {
            var wS = new Uint16Array(d.buffer, 0, 16);
            var wS15 = wS[0] ^ wS[1] ^ wS[2] ^ wS[3] ^ wS[12] ^ wS[15];
            arraycopy(wS, 1, wS, 0, 15);
            wS[15] = wS15;
        }

        //Encrypt function, ECB mode
        function encrypt(key, s, sOff, d, dOff) {
            var t = new Uint8Array(8);
            arraycopy(d, dOff, t, 0, 8);
            var r = new Uint8Array(this.cipher.encrypt(key, t));
            arraycopy(r, 0, s, sOff, 8);
        }

        // block processing
        function process(d, dOff) {
            var S = new Uint8Array(32), U = new Uint8Array(32),
                    V = new Uint8Array(32), W = new Uint8Array(32);

            arraycopy(d, dOff, M, 0, 32);

            //key step 1

            // H = h3 || h2 || h1 || h0
            // S = s3 || s2 || s1 || s0
            arraycopy(H, 0, U, 0, 32);
            arraycopy(M, 0, V, 0, 32);
            for (var j = 0; j < 32; j++)
            {
                W[j] = (U[j] ^ V[j]);
            }
            // Encrypt GOST 28147-ECB
            encrypt.call(this, P(W), S, 0, H, 0); // s0 = EK0 [h0]

            //keys step 2,3,4
            for (var i = 1; i < 4; i++) {
                var tmpA = A(U);
                for (var j = 0; j < 32; j++) {
                    U[j] = (tmpA[j] ^ C[i][j]);
                }
                V = A(A(V));
                for (var j = 0; j < 32; j++) {
                    W[j] = (U[j] ^ V[j]);
                }
                // Encrypt GOST 28147-ECB
                encrypt.call(this, P(W), S, i * 8, H, i * 8); // si = EKi [hi]
            }

            // x(M, H) = y61(H^y(M^y12(S)))
            for (var n = 0; n < 12; n++) {
                fw(S);
            }
            for (var n = 0; n < 32; n++) {
                S[n] = (S[n] ^ M[n]);
            }

            fw(S);

            for (var n = 0; n < 32; n++) {
                S[n] = (H[n] ^ S[n]);
            }
            for (var n = 0; n < 61; n++) {
                fw(S);
            }
            arraycopy(S, 0, H, 0, H.length);
        }


        //  256 bitsblock modul -> (Sum + a mod (2^256))
        function summing(d)
        {
            var carry = 0;
            for (var i = 0; i < Sum.length; i++)
            {
                var sum = (Sum[i] & 0xff) + (d[i] & 0xff) + carry;

                Sum[i] = sum;

                carry = sum >>> 8;
            }
        }

        // reset the chaining variables to the IV values.
        var C2 = new Uint8Array([
            0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
            0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
            0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF,
            0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF
        ]);

        return function (data) {

            // Reset buffers
            H = new Uint8Array(32);
            M = new Uint8Array(32);
            Sum = new Uint8Array(32);

            // Reset IV value
            C = new Array(4);
            for (var i = 0; i < 4; i++)
                C[i] = new Uint8Array(32);
            arraycopy(C2, 0, C[2], 0, C2.length);

            // Make data
            var d = new Uint8Array(buffer(data));

            var n = d.length;
            var r = n % 32, q = (n - r) / 32;

            // Proccess full blocks 
            for (var i = 0; i < q; i++) {
                var b = new Uint8Array(d.buffer, i * 32, 32);

                summing.call(this, b); // calc sum M
                process.call(this, b, 0);
            }

            // load d the remadder with padding zero;
            if (r > 0) {
                var b = new Uint8Array(d.buffer, q * 32),
                        c = new Uint8Array(32);
                arraycopy(b, 0, c, 0, r);
                summing.call(this, c); // calc sum M
                process.call(this, c, 0);

            }

            // get length into L (byteCount * 8 = bitCount) in little endian.
            var L = new Uint8Array(32), n8 = n * 8, k = 0;
            while (n8 > 0) {
                L[k++] = n8 & 0xff;
                n8 = Math.floor(n8 / 256);
            }
            process.call(this, L, 0);
            process.call(this, Sum, 0);

            var h = H.buffer;

            // Swap hash for SignalCom
            if (this.procreator === 'SC')
                h = swap(h);

            return h;
        };

    }
    )();

    /**
     * Algorithm name SHA-1<br><br>
     * 
     * https://tools.ietf.org/html/rfc3174
     * 
     * The digest method returns digest data in according to SHA-1.<br>
     *  
     * @memberOf GostDigest
     * @method digest
     * @instance
     * @param {(ArrayBuffer|TypedArray)} data Data
     * @returns {ArrayBuffer} Digest of data
     */
    var digestSHA1 = (function ()
    {

        // Create a buffer for each 80 word block.
        var state, block = new Uint32Array(80);

        function common(a, e, w, k, f) {
            return (f + e + w + k + ((a << 5) | (a >>> 27))) >>> 0;
        }

        function f1(a, b, c, d, e, w) {
            return common(a, e, w, 0x5A827999, d ^ (b & (c ^ d)));
        }

        function f2(a, b, c, d, e, w) {
            return common(a, e, w, 0x6ED9EBA1, b ^ c ^ d);
        }

        function f3(a, b, c, d, e, w) {
            return common(a, e, w, 0x8F1BBCDC, (b & c) | (d & (b | c)));
        }

        function f4(a, b, c, d, e, w) {
            return common(a, e, w, 0xCA62C1D6, b ^ c ^ d);
        }

        function cycle(state, block) {
            var a = state[0],
                    b = state[1],
                    c = state[2],
                    d = state[3],
                    e = state[4];

            // Partially unroll loops so we don't have to shift variables.
            var fn = f1;
            for (var i = 0; i < 80; i += 5) {
                if (i === 20) {
                    fn = f2;
                }
                else if (i === 40) {
                    fn = f3;
                }
                else if (i === 60) {
                    fn = f4;
                }
                e = fn(a, b, c, d, e, block[i]);
                b = ((b << 30) | (b >>> 2)) >>> 0;
                d = fn(e, a, b, c, d, block[i + 1]);
                a = ((a << 30) | (a >>> 2)) >>> 0;
                c = fn(d, e, a, b, c, block[i + 2]);
                e = ((e << 30) | (e >>> 2)) >>> 0;
                b = fn(c, d, e, a, b, block[i + 3]);
                d = ((d << 30) | (d >>> 2)) >>> 0;
                a = fn(b, c, d, e, a, block[i + 4]);
                c = ((c << 30) | (c >>> 2)) >>> 0;
            }
            state[0] += a;
            state[1] += b;
            state[2] += c;
            state[3] += d;
            state[4] += e;
        }

        // Swap bytes for 32bits word
        function swap32(b) {
            return ((b & 0xff) << 24)
                    | ((b & 0xff00) << 8)
                    | ((b >> 8) & 0xff00)
                    | ((b >> 24) & 0xff);
        }

        // input is a Uint8Array bitstream of the data
        return function (data) {
            var d = new Uint8Array(buffer(data)), dlen = d.length;

            // Pad the input string length.
            var len = dlen + 9;
            if (len % 64) {
                len += 64 - (len % 64);
            }

            state = new Uint32Array(5);
            state[0] = 0x67452301;
            state[1] = 0xefcdab89;
            state[2] = 0x98badcfe;
            state[3] = 0x10325476;
            state[4] = 0xc3d2e1f0;

            for (var ofs = 0; ofs < len; ofs += 64) {

                // Copy input to block and write padding as needed
                for (var i = 0; i < 64; i++) {
                    var b = 0,
                            o = ofs + i;
                    if (o < dlen) {
                        b = d[o];
                    }
                    else if (o === dlen) {
                        b = 0x80;
                    }
                    else {
                        // Write original bit length as a 64bit big-endian integer to the end.
                        var x = len - o - 1;
                        if (x >= 0 && x < 4) {
                            b = (dlen << 3 >>> (x * 8)) & 0xff;
                        }
                    }

                    // Interpret the input bytes as big-endian per the spec
                    if (i % 4 === 0) {
                        block[i >> 2] = b << 24;
                    }
                    else {
                        block[i >> 2] |= b << ((3 - (i % 4)) * 8);
                    }
                }

                // Extend the block
                for (var i = 16; i < 80; i++) {
                    var w = block[i - 3] ^ block[i - 8] ^ block[i - 14] ^ block[i - 16];
                    block[i] = (w << 1) | (w >>> 31);
                }

                cycle(state, block);

            }

            // Swap the bytes around since they are big endian internally
            for (var i = 0; i < 5; i++)
                state[i] = swap32(state[i]);
            return state.buffer;
        };

    }
    )();

    /** 
     * Algorithm name GOST R 34.11-HMAC<br><br>
     * 
     * HMAC with the specified hash function.
     * @memberOf GostDigest
     * @method sign
     * @instance
     * @param {ArrayBuffer} key The key for HMAC.
     * @param {Hash} data Data
     */
    function signHMAC(key, data)
    {
        // GOST R 34.11-94 - B=32b, L=32b
        // GOST R 34.11-256 - B=64b, L=32b
        // GOST R 34.11-512 - B=64b, L=64b
        var b = (this.digest === digest94) ? 32 : 64,
                l = this.bitLength / 8,
                k = buffer(key),
                d = buffer(data), k0;
        if (k.byteLength === b)
            k0 = new Uint8Array(k);
        else {
            var k0 = new Uint8Array(b);
            if (k.byteLength > b) {
                k0.set(new Uint8Array(this.digest(k)));
            } else {
                k0.set(new Uint8Array(k));
            }
        }
        var s0 = new Uint8Array(b + d.byteLength),
                s1 = new Uint8Array(b + l);
        for (var i = 0; i < b; i++) {
            s0[i] = k0[i] ^ 0x36;
            s1[i] = k0[i] ^ 0x5C;
        }
        s0.set(new Uint8Array(d), b);
        s1.set(new Uint8Array(this.digest(s0)), b);
        return this.digest(s1);
    }

    /**
     * Algorithm name GOST R 34.11-HMAC<br><br>
     * 
     * Verify HMAC based on GOST R 34.11 hash
     * 
     * @memberOf GostDigest
     * @method verify
     * @instance
     * @param {(ArrayBuffer|TypedArray)} key Key which used for HMAC generation
     * @param {(ArrayBuffer|TypedArray)} signature generated HMAC
     * @param {(ArrayBuffer|TypedArray)} data Data
     * @returns {boolean} HMAC verified = true
     */
    function verifyHMAC(key, signature, data)
    {
        var hmac = new Uint8Array(this.sign(key, data)),
                test = new Uint8Array(signature);
        if (hmac.length !== test.length)
            return false;
        for (var i = 0, n = hmac.length; i < n; i++)
            if (hmac[i] !== test[i])
                return false;
        return true;
    }


    /**
     * Algorithm name GOST R 34.11-KDF<br><br>
     * 
     * Simple generate key 256/512 bit random seed for derivation algorithms
     * 
     * @memberOf GostDigest
     * @method generateKey
     * @instance
     * @returns {ArrayBuffer} Generated key
     */
    function generateKey()
    {
        return getSeed(this.bitLength).buffer;
    }

    /**
     * Algorithm name GOST R 34.11-PFXKDF<br><br>
     * 
     * Derive bits from password (PKCS12 mode)
     *  <ul>
     *      <li>algorithm.salt - random value, salt</li>
     *      <li>algorithm.iterations - number of iterations</li>
     *  </ul>
     * @memberOf GostDigest
     * @method deriveBits
     * @instance
     * @param {ArrayBuffer} baseKey - password after UTF-8 decoding
     * @param {number} length output bit-length
     * @returns {ArrayBuffer} result
     */
    function deriveBitsPFXKDF(baseKey, length)
    {
        if (length % 8 > 0)
            throw new DataError('Length must multiple of 8');
        var u = this.bitLength / 8, v = (this.digest === digest94) ? 32 : 64,
                n = length / 8, r = this.iterations;
        //   1.  Construct a string, D (the "diversifier"), by concatenating v/8
        //       copies of ID.
        var ID = this.diversifier, D = new Uint8Array(v);
        for (var i = 0; i < v; i++)
            D[i] = ID;
        //   2.  Concatenate copies of the salt together to create a string S of
        //       length v(ceiling(s/v)) bits (the final copy of the salt may be
        //       truncated to create S).  Note that if the salt is the empty
        //       string, then so is S.
        var S0 = new Uint8Array(buffer(this.salt)), s = S0.length,
                slen = v * Math.ceil(s / v), S = new Uint8Array(slen);
        for (var i = 0; i < slen; i++)
            S[i] = S0[i % s];
        //   3.  Concatenate copies of the password together to create a string P
        //       of length v(ceiling(p/v)) bits (the final copy of the password
        //       may be truncated to create P).  Note that if the password is the
        //       empty string, then so is P.
        var P0 = new Uint8Array(buffer(baseKey)), p = P0.length,
                plen = v * Math.ceil(p / v), P = new Uint8Array(plen);
        for (var i = 0; i < plen; i++)
            P[i] = P0[i % p];
        //   4.  Set I=S||P to be the concatenation of S and P.
        var I = new Uint8Array(slen + plen);
        arraycopy(S, 0, I, 0, slen);
        arraycopy(P, 0, I, slen, plen);
        //   5.  Set c=ceiling(n/u).
        var c = Math.ceil(n / u);
        //   6.  For i=1, 2, ..., c, do the following:
        var A = new Uint8Array(c * u);
        for (var i = 0; i < c; i++) {
            //  A.  Set A2=H^r(D||I). (i.e., the r-th hash of D||1,
            //      H(H(H(... H(D||I))))
            var H = new Uint8Array(v + slen + plen);
            arraycopy(D, 0, H, 0, v);
            arraycopy(I, 0, H, v, slen + plen);
            for (var j = 0; j < r; j++)
                H = new Uint8Array(this.digest(H));
            arraycopy(H, 0, A, i * u, u);
            //  B.  Concatenate copies of Ai to create a string B of length v
            //      bits (the final copy of Ai may be truncated to create B).
            var B = new Uint8Array(v);
            for (var j = 0; j < v; j++)
                B[j] = H[j % u];
            //  C.  Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit
            //      blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by
            //      setting I_j=(I_j+B+1) mod 2^v for each j.
            var k = (slen + plen) / v;
            for (j = 0; j < k; j++) {
                var cf = 1, w;
                for (var l = v - 1; l >= 0; --l) {
                    w = I[v * j + l] + B[l] + cf;
                    cf = w >>> 8;
                    I[v * j + l] = w & 0xff;
                }
            }
        }
        //   7.  Concatenate A_1, A_2, ..., A_c together to form a pseudorandom
        //       bit string, A.
        //   8.  Use the first n bits of A as the output of this entire process.
        var R = new Uint8Array(n);
        arraycopy(A, 0, R, 0, n);
        return R.buffer;
    }

    /**
     * Algorithm name GOST R 34.11-KDF<br><br>
     * 
     * Derive bits for KEK deversification in 34.10-2012 algorithm
     * KDF(KEK, UKM, label) = HMAC256 (KEK,  0x01|label|0x00|UKM|0x01|0x00) 
     * Default label = 0x26|0xBD|0xB8|0x78 
     * 
     * @memberOf GostDigest
     * @method deriveBits
     * @instance
     * @param {(ArrayBuffer|TypedArray)} baseKey base key for deriviation
     * @param {number} length output bit-length 
     * @returns {ArrayBuffer} result
     */
    function deriveBitsKDF(baseKey, length)
    {
        if (length % 8 > 0)
            throw new DataError('Length must be multiple of 8');
        var rlen = length / 8, label, context = new Uint8Array(buffer(this.context)),
                blen = this.bitLength / 8, n = Math.ceil(rlen / blen);
        if (this.label)
            label = new Uint8Array(buffer(this.label));
        else
            label = new Uint8Array([0x26, 0xBD, 0xB8, 0x78]);
        var result = new Uint8Array(rlen);
        for (var i = 0; i < n; i++) {
            var data = new Uint8Array(label.length + context.length + 4);
            data[0] = i + 1;
            data.set(label, 1);
            data[label.length + 1] = 0x00;
            data.set(context, label.length + 2);
            data[data.length - 2] = length >>> 8;
            data[data.length - 1] = length & 0xff;
            result.set(new Uint8Array(signHMAC.call(this, baseKey, data), 0,
                    i < n - 1 ? blen : rlen - i * blen), i * blen);
        }
        return result.buffer;
    }

    /**
     * Algorithm name GOST R 34.11-PBKDF1<br><br>
     * 
     * Derive bits from password
     *  <ul>
     *      <li>algorithm.salt - random value, salt</li>
     *      <li>algorithm.iterations - number of iterations</li>
     *  </ul>
     * @memberOf GostDigest
     * @method deriveBits
     * @instance
     * @param {ArrayBuffer} baseKey - password after UTF-8 decoding
     * @param {number} length output bit-length
     * @returns {ArrayBuffer} result
     */
    function deriveBitsPBKDF1(baseKey, length)
    {
        if (length < this.bitLength / 2 || length % 8 > 0)
            throw new DataError('Length must be more than ' + this.bitLength / 2 + ' bits and multiple of 8');
        var hLen = this.bitLength / 8, dkLen = length / 8,
                c = this.iterations,
                P = new Uint8Array(buffer(baseKey)),
                S = new Uint8Array(buffer(this.salt)),
                slen = S.length, plen = P.length,
                T = new Uint8Array(plen + slen),
                DK = new Uint8Array(dkLen);
        if (dkLen > hLen)
            throw new DataError('Invalid parameters: Length value');
        arraycopy(P, 0, T, 0, plen);
        arraycopy(S, 0, T, plen, slen);
        for (var i = 0; i < c; i++)
            T = new Uint8Array(this.digest(T));
        arraycopy(T, 0, DK, 0, dkLen);
        return DK.buffer;
    }

    /**
     * Algorithm name GOST R 34.11-PBKDF2<br><br>
     * 
     * Derive bits from password
     *  <ul>
     *      <li>algorithm.salt - random value, salt</li>
     *      <li>algorithm.iterations - number of iterations</li>
     *  </ul>
     * @memberOf GostDigest
     * @method deriveBits
     * @instance
     * @param {ArrayBuffer} baseKey - password after UTF-8 decoding
     * @param {number} length output bit-length
     * @returns {ArrayBuffer} result
     */
    function deriveBitsPBKDF2(baseKey, length)
    {
        var diversifier = this.diversifier || 1; // For PKCS12 MAC required 3*length
        length = length * diversifier;
        if (length < this.bitLength / 2 || length % 8 > 0)
            throw new DataError('Length must be more than ' + this.bitLength / 2 + ' bits and multiple of 8');
        var hLen = this.bitLength / 8, dkLen = length / 8,
                c = this.iterations,
                P = new Uint8Array(buffer(baseKey)),
                S = new Uint8Array(buffer(this.salt));
        var slen = S.byteLength,
                data = new Uint8Array(slen + 4);
        arraycopy(S, 0, data, 0, slen);

        if (dkLen > (0xffffffff - 1) * 32)
            throw new DataError('Invalid parameters: Length value');
        var n = Math.ceil(dkLen / hLen),
                DK = new Uint8Array(dkLen);
        for (var i = 1; i <= n; i++) {
            data[slen] = i >>> 24 & 0xff;
            data[slen + 1] = i >>> 16 & 0xff;
            data[slen + 2] = i >>> 8 & 0xff;
            data[slen + 3] = i & 0xff;

            var U = new Uint8Array(signHMAC.call(this, P, data)), Z = U;
            for (var j = 1; j < c; j++) {
                U = new Uint8Array(signHMAC.call(this, P, U));
                for (var k = 0; k < hLen; k++)
                    Z[k] = U[k] ^ Z[k];
            }
            var ofs = (i - 1) * hLen;
            arraycopy(Z, 0, DK, ofs, Math.min(hLen, dkLen - ofs));
        }
        if (diversifier > 1) {
            var rLen = dkLen / diversifier, R = new Uint8Array(rLen);
            arraycopy(DK, dkLen - rLen, R, 0, rLen);
            return R.buffer;
        } else
            return DK.buffer;
    }

    /**
     * Algorithm name GOST R 34.11-CPKDF<br><br>
     * 
     * Derive bits from password. CryptoPro algorithm
     *  <ul>
     *      <li>algorithm.salt - random value, salt</li>
     *      <li>algorithm.iterations - number of iterations</li>
     *  </ul>
     * @memberOf GostDigest
     * @method deriveBits
     * @instance
     * @param {ArrayBuffer} baseKey - password after UTF-8 decoding
     * @param {number} length output bit-length
     * @returns {ArrayBuffer} result
     */
    function deriveBitsCP(baseKey, length) {
        if (length > this.bitLength || length % 8 > 0)
            throw new DataError('Length can\'t be more than ' + this.bitLength + ' bits and multiple of 8');
        // GOST R 34.11-94 - B=32b, L=32b
        // GOST R 34.11-256 - B=64b, L=32b
        // GOST R 34.11-512 - B=64b, L=64b
        var b = (this.digest === digest94) ? 32 : 64,
                l = this.bitLength / 8,
                p = baseKey && baseKey.byteLength > 0 ? new Uint8Array(buffer(baseKey)) : false,
                plen = p ? p.length : 0,
                iterations = this.iterations,
                salt = new Uint8Array(buffer(this.salt)),
                slen = salt.length,
                d = new Uint8Array(slen + plen);
        arraycopy(salt, 0, d, 0, slen);
        if (p)
            arraycopy(p, 0, d, slen, plen);

        var h = new Uint8Array(this.digest(d)),
                k = new Uint8Array(b),
                s0 = new Uint8Array(b),
                s1 = new Uint8Array(b);
        var c = 'DENEFH028.760246785.IUEFHWUIO.EF';
        for (var i = 0; i < c.length; i++)
            k[i] = c.charCodeAt(i);

        d = new Uint8Array(2 * (b + l));
        for (var j = 0; j < iterations; j++) {
            for (var i = 0; i < b; i++) {
                s0[i] = k[i] ^ 0x36;
                s1[i] = k[i] ^ 0x5C;
                k[i] = 0;
            }
            arraycopy(s0, 0, d, 0, b);
            arraycopy(h, 0, d, b, l);
            arraycopy(s1, 0, d, b + l, b);
            arraycopy(h, 0, d, b + l + b, l);
            arraycopy(new Uint8Array(this.digest(d)), 0, k, 0, l);
        }
        for (var i = 0; i < l; i++) {
            s0[i] = k[i] ^ 0x36;
            s1[i] = k[i] ^ 0x5C;
            k[i] = 0;
        }
        d = new Uint8Array(2 * l + slen + plen);
        arraycopy(s0, 0, d, 0, l);
        arraycopy(salt, 0, d, l, slen);
        arraycopy(s1, 0, d, l + slen, l);
        if (p)
            arraycopy(p, 0, d, l + slen + l, plen);
        h = this.digest(this.digest(d));
        if (length === this.bitLength)
            return h;
        else {
            var rlen = length / 8, r = new Uint8Array(rlen);
            arraycopy(h, 0, r, 0, rlen);
            return r.buffer;
        }
    }

    /**
     * Algorithm name GOST R 34.11-KDF or GOST R 34.11-PBKDF2 or other<br><br>
     * 
     * Derive key from derive bits subset
     * 
     * @memberOf GostDigest
     * @method deriveKey
     * @instance
     * @param {ArrayBuffer} baseKey
     * @returns {ArrayBuffer}
     */
    function deriveKey(baseKey)
    {
        return this.deriveBits(baseKey, this.keySize * 8);
    }

    /**
     * GOST R 34.11 Algorithm<br><br>
     * 
     * References: {@link http://tools.ietf.org/html/rfc6986} and {@link http://tools.ietf.org/html/rfc5831}<br><br>
     * 
     * Normalized algorithm identifier common parameters:
     * 
     *  <ul>
     *      <li><b>name</b> Algorithm name 'GOST R 34.11'</li>
     *      <li><b>version</b> Algorithm version
     *          <ul>
     *              <li><b>1994</b> old-style 256 bits digest based on GOST 28147-89</li>
     *              <li><b>2012</b> 256 ro 512 bits digest algorithm "Streebog" GOST R 34.11-2012 (default)</li>
     *          </ul>
     *      </li>
     *      <li><b>length</b> Digest length
     *          <ul>
     *              <li><b>256</b> 256 bits digest</li>
     *              <li><b>512</b> 512 bits digest, valid only for algorithm "Streebog"</li>
     *          </ul>
     *      </li>
     *      <li><b>mode</b> Algorithm mode
     *          <ul>
     *              <li><b>HASH</b> simple digest mode (default)</li>
     *              <li><b>HMAC</b> HMAC algorithm based on GOST R 34.11</li>
     *              <li><b>KDF</b> Derive bits for KEK deversification</li>
     *              <li><b>PBKDF2</b> Password based key dirivation algorithms PBKDF2 (based on HMAC)</li>
     *              <li><b>PFXKDF</b> Password based PFX key dirivation algorithms</li>
     *              <li><b>CPKDF</b> CpyptoPro Password based key dirivation algorithms</li>
     *          </ul>
     *      </li>
     *      <li><b>sBox</b> Paramset sBox for GOST 28147-89. Used only if version = 1994</li>
     *  </ul>
     * 
     * Supported algorithms, modes and parameters:
     * 
     *  <ul>
     *      <li>Digest HASH mode (default)</li>
     *      <li>Sign/Verify HMAC modes parameters depends on version and length
     *          <ul>
     *              <li><b>version: 1994</b> HMAC parameters (B = 32, L = 32)</li>
     *              <li><b>version: 2012, length: 256</b> HMAC parameters (B = 64, L = 32)</li>
     *              <li><b>version: 2012, length: 512</b> HMAC parameters  (B = 64, L = 64)</li>
     *          </ul>
     *      </li>
     *      <li>DeriveBits/DeriveKey KDF mode
     *          <ul>
     *              <li><b>context</b> {@link CryptoOperationData} Context of the key derivation</li>
     *              <li><b>label</b> {@link CryptoOperationData} Label that identifies the purpose for the derived keying material</li>
     *          </ul>
     *      </li>
     *      <li>DeriveBits/DeriveKey PBKDF2 mode
     *          <ul>
     *              <li><b>salt</b> {@link CryptoOperationData} Random salt as input for HMAC algorithm</li>
     *              <li><b>iterations</b> Iteration count. GOST recomended value 1000 (default) or 2000</li>
     *              <li><b>diversifier</b> Deversifier, ID=1 - key material for performing encryption or decryption, ID=3 - integrity key for MACing</li>
     *          </ul>
     *      </li>
     *      <li>DeriveBits/DeriveKey PFXKDF mode
     *          <ul>
     *              <li><b>salt</b> {@link CryptoOperationData} Random salt as input for HMAC algorithm</li>
     *              <li><b>iterations</b> Iteration count. GOST recomended value 1000 (default) or 2000</li>
     *              <li><b>diversifier</b> Deversifier, ID=1 - key material for performing encryption or decryption, 
     *              ID=2 - IV (Initial Value) for encryption or decryption, ID=3 - integrity key for MACing</li>
     *          </ul>
     *      </li>
     *      <li>DeriveBits/DeriveKey CPKDF mode
     *          <ul>
     *              <li><b>salt</b> {@link CryptoOperationData} Random salt as input for HMAC algorithm</li>
     *              <li><b>iterations</b> Iteration count. GOST recomended value 1000 (default) or 2000</li>
     *          </ul>
     *      </li>
     *  </ul>
     * 
     * @class GostDigest
     * @param {AlgorithmIdentifier} algorithm WebCryptoAPI algorithm identifier
     */
    function GostDigest(algorithm)
    {

        algorithm = algorithm || {};

        this.name = (algorithm.name || 'GOST R 34.10') + '-' + ((algorithm.version || 2012) % 100) +
                ((algorithm.version || 2012) > 1 ? '-' + (algorithm.length || 256) : '') +
                (((algorithm.mode || 'HASH') !== 'HASH') ? '-' + algorithm.mode : '') +
                (algorithm.procreator ? '/' + algorithm.procreator : '') +
                (typeof algorithm.sBox === 'string' ? '/' + algorithm.sBox : '');

        // Algorithm procreator
        this.procreator = algorithm.procreator;

        // Bit length
        this.bitLength = algorithm.length || 256;

        switch (algorithm.version || 2012) {
            case 1: // SHA-1
                this.digest = digestSHA1;
                this.bitLength = 160;
                break;
            case 1994:
                this.digest = digest94;
                // Define chiper algorithm
                this.sBox = (algorithm.sBox || (algorithm.procreator === 'SC' ? 'D-SC' : 'D-A')).toUpperCase();

                if (!GostCipher)
                    throw new NotSupportedError('Object GostCipher not found');

                this.cipher = new GostCipher({
                    name: 'GOST 28147',
                    block: 'ECB',
                    sBox: this.sBox,
                    procreator: this.procreator
                });

                break;
            case 2012:
                this.digest = digest2012;
                break;
            default:
                throw new NotSupportedError('Algorithm version ' + algorithm.version + ' not supported');
        }

        // Key size
        this.keySize = algorithm.keySize || (algorithm.version <= 2 ? this.bitLength / 8 : 32);

        switch (algorithm.mode || 'HASH') {
            case 'HASH':
                break;
            case 'HMAC':
                this.sign = signHMAC;
                this.verify = verifyHMAC;
                this.generateKey = generateKey;
                break;
            case 'KDF':
                this.deriveKey = deriveKey;
                this.deriveBits = deriveBitsKDF;
                this.label = algorithm.label;
                this.context = algorithm.context;
                break;
            case 'PBKDF2':
                this.deriveKey = deriveKey;
                this.deriveBits = deriveBitsPBKDF2;
                this.generateKey = generateKey;
                this.salt = algorithm.salt;
                this.iterations = algorithm.iterations || 2000;
                this.diversifier = algorithm.diversifier || 1;
                break;
            case 'PFXKDF':
                this.deriveKey = deriveKey;
                this.deriveBits = deriveBitsPFXKDF;
                this.generateKey = generateKey;
                this.salt = algorithm.salt;
                this.iterations = algorithm.iterations || 2000;
                this.diversifier = algorithm.diversifier || 1;
                break;
            case 'CPKDF':
                this.deriveKey = deriveKey;
                this.deriveBits = deriveBitsCP;
                this.generateKey = generateKey;
                this.salt = algorithm.salt;
                this.iterations = algorithm.iterations || 2000;
                break;
            default:
                throw new NotSupportedError('Algorithm mode ' + algorithm.mode + ' not supported');
        }
    }

module.exports = GostDigest;


/***/ }),

/***/ "./node_modules/node-gost-crypto/lib/gostEngine.js":
/*!*********************************************************!*\
  !*** ./node_modules/node-gost-crypto/lib/gostEngine.js ***!
  \*********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

/**
 * @file GOST 34.10-2012 signature function with 1024/512 bits digest
 * @version 1.76
 * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *    
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

//const GostRandom = require('./gostRandom');
const GostCipher = __webpack_require__(/*! ./gostCipher */ "./node_modules/node-gost-crypto/lib/gostCipher.js");
const GostDigest = __webpack_require__(/*! ./gostDigest */ "./node_modules/node-gost-crypto/lib/gostDigest.js");
const GostSign = __webpack_require__(/*! ./gostSign */ "./node_modules/node-gost-crypto/lib/gostSign.js");

    /*
     * Engine definition base on normalized algorithm identifier
     * 
     */

    var root = __webpack_require__.g;

    // Define engine
    function defineEngine(method, algorithm) {
        if (!algorithm)
            throw new (root.SyntaxError || Error)('Algorithm not defined');

        if (!algorithm.name)
            throw new (root.SyntaxError || Error)('Algorithm name not defined');

        var name = algorithm.name, mode = algorithm.mode;
        if ((name === 'GOST 28147' || name === 'GOST R 34.12' || name === 'RC2') && (method === 'generateKey' ||
                (mode === 'MAC' && (method === 'sign' || method === 'verify')) ||
                ((mode === 'KW' || mode === 'MASK') && (method === 'wrapKey' || method === 'unwrapKey')) ||
                ((!mode || mode === 'ES') && (method === 'encrypt' || method === 'decrypt')))) {
            return 'GostCipher';

        } else if ((name === 'GOST R 34.11' || name === 'SHA') && (method === 'digest' ||
                (mode === 'HMAC' && (method === 'sign' || method === 'verify' || method === 'generateKey')) ||
                ((mode === 'KDF' || mode === 'PBKDF2' || mode === 'PFXKDF' || mode === 'CPKDF') &&
                        (method === 'deriveKey' || method === 'deriveBits' || method === 'generateKey')))) {
            return 'GostDigest';

        } else if (name === 'GOST R 34.10' && (method === 'generateKey' ||
                ((!mode || mode === 'SIGN') && (method === 'sign' || method === 'verify')) ||
                (mode === 'MASK' && (method === 'wrapKey' || method === 'unwrapKey')) ||
                (mode === 'DH' && (method === 'deriveKey' || method === 'deriveBits')))) {
            return 'GostSign';
        } else
            throw new (root.NotSupportedError || Error)('Algorithm ' + name + '-' + mode + ' is not valid for ' + method);
    }

    /**
     * Object implements dedicated Web Workers and provide a simple way to create 
     * and run GOST cryptographic algorithms in background thread. 
     * 
     * Object provide interface to GOST low-level cryptogric classes:
     *  <ul>
     *      <li>GostCipher - implementation of GOST 28147, GOST R 34.12, GOST R 34.13 Encryption algorithms. Reference {@link http://tools.ietf.org/html/rfc5830}</li>
     *      <li>GostDigest - implementation of GOST R 34.11 Hash Function algorithms. References {@link http://tools.ietf.org/html/rfc5831} and {@link http://tools.ietf.org/html/rfc6986}</li>
     *      <li>GostSign - implementation of GOST R 34.10 Digital Signature algorithms. References {@link http://tools.ietf.org/html/rfc5832} and {@link http://tools.ietf.org/html/rfc7091}</li>
     *  </ul>
     * @namespace gostEngine
     */
    var gostEngine = {
        /**
         * gostEngine.execute(algorithm, method, args) Entry point to execution 
         * all low-level GOST cryptographic methods
         * 
         *  <ul>
         *      <li>Determine the appropriate engine for a given execution method</li>
         *      <li>Create cipher object for determineted engine</li>
         *      <li>Execute method of cipher with given args</li>
         *  </ul>
         * 
         * @memberOf gostEngine
         * @param {AlgorithmIndentifier} algorithm Algorithm identifier
         * @param {string} method Crypto method for execution
         * @param {Array} args Method arguments (keys, data, additional parameters)
         * @returns {(CryptoOperationData|Key|KeyPair|boolean)} Result of method execution
         */
        execute: function (algorithm, method, args)
        {
            // Define engine for GOST algorithms
            var engine = defineEngine(method, algorithm);
            // Create cipher 
            var cipher = this['get' + engine](algorithm);
            // Execute method
            return cipher[method].apply(cipher, args);
        },
        /**
         * gostEngine.getGostCipher(algorithm) returns GOST 28147 / GOST R 34.12 cipher instance<br><br>
         * 
         * GOST 28147-89 / GOST R 34.12-15 Encryption Algorithm<br><br> 
         * When keys and initialization vectors are converted to/from byte arrays, 
         * little-endian byte order is assumed.<br><br>
         * 
         * Normalized algorithm identifier common parameters:
         * 
         *  <ul>
         *      <li><b>name</b> Algorithm name 'GOST 28147' or 'GOST R 34.12'</li>
         *      <li><b>version</b> Algorithm version, number
         *          <ul>
         *              <li><b>1989</b> Current version of standard</li>
         *              <li><b>2015</b> New draft version of standard</li>
         *          </ul>
         *      </li>
         *      <li><b>length</b> Block length
         *          <ul>
         *              <li><b>64</b> 64 bits length (default)</li>
         *              <li><b>128</b> 128 bits length (only for version 2015)</li>
         *          </ul>
         *      </li>
         *      <li><b>mode</b> Algorithm mode, string
         *          <ul>
         *              <li><b>ES</b> Encryption mode (default)</li>
         *              <li><b>MAC</b> "imitovstavka" (MAC) mode</li>
         *              <li><b>KW</b> Key wrapping mode</li>
         *              <li><b>MASK</b> Key mask mode</li>
         *          </ul>
         *      </li>
         *      <li><b>sBox</b> Paramset sBox for GOST 28147-89, string. Used only if version = 1989</li>
         *  </ul>
         *  
         * Supported algorithms, modes and parameters:
         * 
         *  <ul>
         *      <li>Encript/Decrypt mode (ES)
         *          <ul>
         *              <li><b>block</b> Block mode, string. Default ECB</li>
         *              <li><b>keyMeshing</b> Key meshing mode, string. Default NO</li>
         *              <li><b>padding</b> Padding mode, string. Default NO for CFB and CTR modes, or ZERO for others</li>
         *              <li><b>iv</b> {@link CryptoOperationData} Initial vector with length of block. Default - zero block</li>
         *          </ul>
         *      </li>
         *      <li>Sign/Verify mode (MAC)
         *          <ul>
         *              <li><b>macLength</b> Length of mac in bits (default - 32 bits)</li>
         *              <li><b>iv</b> {@link CryptoOperationData} Initial vector with length of block. Default - zero block</li>
         *          </ul>
         *      </li>
         *      <li>Wrap/Unwrap key mode (KW)
         *          <ul>
         *              <li><b>keyWrapping</b> Mode of keywrapping, string. Default NO - standard GOST key wrapping</li>
         *              <li><b>ukm</b> {@link CryptoOperationData} User key material. Default - random generated value</li>
         *          </ul>
         *      </li>
         *      <li>Wrap/Unwrap key mode (MASK)</li>
         *  </ul>
         *      
         * Supported paramters values:
         *      
         *  <ul>
         *      <li>Block modes (parameter 'block')
         *          <ul>
         *              <li><b>ECB</b> "prostaya zamena" (ECB) mode (default)</li>
         *              <li><b>CFB</b> "gammirovanie s obratnoj svyaziyu" (64-bit CFB) mode</li>
         *              <li><b>CTR</b> "gammirovanie" (counter) mode</li>
         *              <li><b>CBC</b> Cipher-Block-Chaining (CBC) mode</li>
         *          </ul>
         *      </li>
         *      <li>Key meshing modes (parameter 'keyMeshing')
         *          <ul>
         *              <li><b>NO</b> No key wrapping (default)</li>
         *              <li><b>CP</b> CryptoPor Key key meshing</li>
         *          </ul>
         *      </li>
         *      <li>Padding modes (parameter 'padding')
         *          <ul>
         *              <li><b>NO</b> No padding only for CFB and CTR modes</li>
         *              <li><b>PKCS5</b> PKCS#5 padding mode</li>
         *              <li><b>ZERO</b> Zero bits padding mode</li>
         *              <li><b>RANDOM</b> Random bits padding mode</li>
         *          </ul>
         *      </li>
         *      <li>Wrapping key modes (parameter 'keyWrapping')
         *          <ul>
         *              <li><b>NO</b> Ref. rfc4357 6.1 GOST 28147-89 Key wrapping</li>
         *              <li><b>CP</b> CryptoPro Key wrapping mode</li>
         *              <li><b>SC</b> SignalCom Key wrapping mode</li>
         *          </ul>
         *      </li>
         *  </ul>
         * 
         * @memberOf gostEngine
         * @param {AlgorithmIndentifier} algorithm Algorithm identifier
         * @returns {GostCipher} Instance of GostCipher
         */
        getGostCipher: function (algorithm)
        {
            return new GostCipher(algorithm);
        },
        /**
         * gostEngine.getGostDigest(algorithm) returns GOST R 34.11 cipher instance<br><br>
         * 
         * Normalized algorithm identifier common parameters:
         * 
         *  <ul>
         *      <li><b>name</b> Algorithm name 'GOST R 34.11'</li>
         *      <li><b>version</b> Algorithm version
         *          <ul>
         *              <li><b>1994</b> old-style 256 bits digest based on GOST 28147-89</li>
         *              <li><b>2012</b> 256 ro 512 bits digest algorithm "Streebog" GOST R 34.11-2012 (default)</li>
         *          </ul>
         *      </li>
         *      <li><b>length</b> Digest length
         *          <ul>
         *              <li><b>256</b> 256 bits digest</li>
         *              <li><b>512</b> 512 bits digest, valid only for algorithm "Streebog"</li>
         *          </ul>
         *      </li>
         *      <li><b>mode</b> Algorithm mode
         *          <ul>
         *              <li><b>HASH</b> simple digest mode (default)</li>
         *              <li><b>HMAC</b> HMAC algorithm based on GOST R 34.11</li>
         *              <li><b>KDF</b> Derive bits for KEK deversification</li>
         *              <li><b>PBKDF2</b> Password based key dirivation algorithms PBKDF2 (based on HMAC)</li>
         *              <li><b>PFXKDF</b> PFX key dirivation algorithms PFXKDF</li>
         *              <li><b>CPKDF</b> CryptoPro Password based key dirivation algorithms</li>
         *          </ul>
         *      </li>
         *      <li><b>sBox</b> Paramset sBox for GOST 28147-89. Used only if version = 1994</li>
         *  </ul>
         * 
         * Supported algorithms, modes and parameters:
         * 
         *  <ul>
         *      <li>Digest HASH mode (default)</li>
         *      <li>Sign/Verify HMAC modes parameters depends on version and length
         *          <ul>
         *              <li><b>version: 1994</b> HMAC parameters (B = 32, L = 32)</li>
         *              <li><b>version: 2012, length: 256</b> HMAC parameters (B = 64, L = 32)</li>
         *              <li><b>version: 2012, length: 512</b> HMAC parameters  (B = 64, L = 64)</li>
         *          </ul>
         *      </li>
         *      <li>DeriveBits/DeriveKey KDF mode
         *          <ul>
         *              <li><b>context</b> {@link CryptoOperationData} Context of the key derivation</li>
         *              <li><b>label</b> {@link CryptoOperationData} Label that identifies the purpose for the derived keying material</li>
         *          </ul>
         *      </li>
         *      <li>DeriveBits/DeriveKey PBKDF2 mode
         *          <ul>
         *              <li><b>salt</b> {@link CryptoOperationData} Random salt as input for HMAC algorithm</li>
         *              <li><b>iterations</b> Iteration count. GOST recomended value 1000 (default) or 2000</li>
         *          </ul>
         *      </li>
         *      <li>DeriveBits/DeriveKey PFXKDF mode
         *          <ul>
         *              <li><b>salt</b> {@link CryptoOperationData} Random salt as input for HMAC algorithm</li>
         *              <li><b>iterations</b> Iteration count. GOST recomended value 1000 (default) or 2000</li>
         *              <li><b>diversifier</b> Deversifier, ID=1 - key material for performing encryption or decryption, 
         *              ID=2 - IV (Initial Value) for encryption or decryption, ID=3 - integrity key for MACing</li>
         *          </ul>
         *      </li>
         *      <li>DeriveBits/DeriveKey CPKDF mode
         *          <ul>
         *              <li><b>salt</b> {@link CryptoOperationData} Random salt as input for HMAC algorithm</li>
         *              <li><b>iterations</b> Iteration count. GOST recomended value 1000 (default) or 2000</li>
         *          </ul>
         *      </li>
         *  </ul>
         * 
         * @memberOf gostEngine
         * @param {AlgorithmIndentifier} algorithm Algorithm identifier
         * @returns {GostDigest} Instance of GostDigest
         */
        getGostDigest: function (algorithm)
        {
            return new GostDigest(algorithm);
        },
        /**
         * gostEngine.getGostSign(algorithm) returns GOST R 34.10 cipher instance<br><br>
         * 
         * Normalized algorithm identifier common parameters:
         * 
         *  <ul>
         *      <li><b>name</b> Algorithm name 'GOST R 34.10'</li>
         *      <li><b>version</b> Algorithm version
         *          <ul>
         *              <li><b>1994</b> - Old-style GOST R 34.10-94 ExpMod algorithm with GOST R 34.11-94 hash</li>
         *              <li><b>2001</b> - GOST R 34.10-2001 Eliptic curve algorithm with old GOST R 34.11-94 hash</li>
         *              <li><b>2012</b> - GOST R 34.10-2012 Eliptic curve algorithm with GOST R 34.11-12 hash, default mode</li>
         *          </ul>
         *      </li>
         *      <li><b>length</b> Length of hash and signature. Key length == hash length for EC algorithms and 2 * hash length for ExpMod algorithm
         *          <ul>
         *              <li><b>GOST R 34.10-256</b> - 256 bits digest, default mode</li>
         *              <li><b>GOST R 34.10-512</b> - 512 bits digest only for GOST R 34.11-2012 hash</li>
         *          </ul>
         *      </li>
         *      <li><b>mode</b> Algorithm mode
         *          <ul>
         *              <li><b>SIGN</b> Digital signature mode (default)</li>
         *              <li><b>DH</b> Diffie-Hellman key generation and key agreement mode</li>
         *              <li><b>MASK</b> Key mask mode</li>
         *          </ul>
         *      </li>
         *      <li><b>sBox</b> Paramset sBox for GOST 34.11-94. Used only if version = 1994 or 2001</li>
         *  </ul>
         *  
         * Supported algorithms, modes and parameters:
         * 
         *  <ul>
         *      <li>Sign/Verify mode (SIGN)</li>
         *      <li>Wrap/Unwrap mode (MASK)</li>
         *      <li>DeriveKey/DeriveBits mode (DH)
         *          <ul>
         *              <li>{@link CryptoOperationData} <b>ukm</b> User key material. Default - random generated value</li>
         *              <li>{@link CryptoOperationData} <b>public</b> The peer's EC public key data</li>
         *          </ul>
         *      </li>
         *      <li>GenerateKey mode (SIGN and DH and MASK) version = 1994
         *          <ul>
         *              <li><b>namedParam</b> Paramset for key generation algorithm. If specified no additianal parameters required</li>
         *          </ul>
         *          Additional parameters, if namedParam not specified
         *          <ul>
         *              <li><b>modulusLength</b> Bit length of p (512 or 1024 bits). Default = 1024</li>
         *              <li><b>p</b> {@link CryptoOperationData} Modulus, prime number, 2^(t-1)<p<2^t</li>
         *              <li><b>q</b> {@link CryptoOperationData} Order of cyclic group, prime number, 2^254<q<2^256, q is a factor of p-1</li>
         *              <li><b>a</b> {@link CryptoOperationData} Generator, integer, 1<a<p-1, at that aq (mod p) = 1</li>
         *          </ul>
         *      </li>
         *      <li>GenerateKey mode (SIGN and DH and MASK) version = 2001 or 2012
         *          <ul>
         *              <li><b>namedCurve</b> Paramset for key generation algorithm. If specified no additianal parameters required</li>
         *          </ul>
         *          Additional EC parameters, if namedCurve not specified
         *          <ul>
         *              <li><b>p</b> {@link CryptoOperationData} Prime number - elliptic curve modulus</li>
         *              <li><b>a</b> {@link CryptoOperationData} Coefficients a of the elliptic curve E</li>
         *              <li><b>b</b> {@link CryptoOperationData} Coefficients b of the elliptic curve E</li>
         *              <li><b>q</b> {@link CryptoOperationData} Prime number - order of cyclic group</li>
         *              <li><b>x</b> {@link CryptoOperationData} Base point p x-coordinate</li>
         *              <li><b>y</b> {@link CryptoOperationData} Base point p y-coordinate</li>
         *          </ul>
         *      </li>
         *  </ul>
         *  
         * @memberOf gostEngine
         * @param {AlgorithmIndentifier} algorithm Algorithm identifier
         * @returns {GostSign} Instance of GostSign
         */
        getGostSign: function (algorithm)
        {
            return new GostSign(algorithm);
        }
    };

module.exports = gostEngine;


/***/ }),

/***/ "./node_modules/node-gost-crypto/lib/gostKeys.js":
/*!*******************************************************!*\
  !*** ./node_modules/node-gost-crypto/lib/gostKeys.js ***!
  \*******************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

/** 
 * @file Key and Certificate Store methods
 * @version 1.76
 * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *    
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

const gostCrypto = __webpack_require__(/*! ./gostCrypto */ "./node_modules/node-gost-crypto/lib/gostCrypto.js");
// const GostASN1 = require('./gostASN1');
// const GostCert = require('./gostCert');
// const GostCMS = require('./gostCMS');

    /*
     * Common tools and methods
     */

    var root = __webpack_require__.g;
    var Promise = root.Promise;
    var Object = root.Object;
    var CryptoOperationData = root.ArrayBuffer;
    var Date = root.Date;

    var subtle = gostCrypto.subtle;
    var asn1 = gostCrypto.asn1;
    var coding = gostCrypto.coding;
    var providers = gostCrypto.security.providers;
    var cert = gostCrypto.cert;
    var cms = gostCrypto.cms;

    // Expand javascript object
    function expand() {
        var r = {};
        for (var i = 0, n = arguments.length; i < n; i++) {
            var item = arguments[i];
            if (typeof item === 'object')
                for (var name in item)
                    if (item.hasOwnProperty(name))
                        r[name] = item[name];
        }
        return r;
    }

    function defineProperty(object, name, descriptor, enumerable) {
        if (typeof descriptor !== 'object')
            descriptor = {value: descriptor};
        if (enumerable !== undefined)
            descriptor.enumerable = enumerable;
        Object.defineProperty(object, name, descriptor);
    }

    function defineProperties(object, properties, enumerable) {
        for (var name in properties)
            defineProperty(object, name, properties[name], enumerable);
    }

    // Extend javascript class
    function extend(Super, Class, propertiesObject, propertiesClass) {
        // If constructor not defined
        if (typeof Class !== 'function') {
            propertiesClass = propertiesObject;
            propertiesObject = Class;
            Class = function () {
                Super.apply(this, arguments);
            };
        }
        // Create prototype properties
        Class.prototype = Object.create(Super.prototype, {
            constructor: {
                value: Class
            },
            superclass: {
                value: Super.prototype
            }
        });
        if (propertiesObject)
            defineProperties(Class.prototype, propertiesObject, true);
        // Inherites super class properties
        if (Super !== Object)
            for (var name in Super)
                Class[name] = Super[name];
        Class.super = Super;
        if (propertiesClass)
            defineProperties(Class, propertiesClass, true);
        return Class;
    }

    // Get random values
    function getSeed(length) {
        var seed = new Uint8Array(length);
        gostCrypto.getRandomValues(seed);
        return seed.buffer;
    }

    // Self resolver
    function call(callback) {
        try {
            callback();
        } catch (e) {
        }
    }


    // Get buffer
    function buffer(d) {
        if (d instanceof CryptoOperationData)
            return d;
        else if (d && d.buffer && d.buffer instanceof CryptoOperationData)
            return d.byteOffset === 0 && d.byteLength === d.buffer.byteLength ?
                    d.buffer : new Uint8Array(new Uint8Array(d, d.byteOffset, d.byteLength)).buffer;
        else
            throw new DataError('CryptoOperationData required');
    }
    // Today date + n days with time
    function now(n) {
        var date = new Date();
        if (n)
            date.setDate(date.getDate() + n);
        return date;
    }

    // Today date + n days
    function today(n) {
        var date = now(n);
        date.setHours(0, 0, 0, 0);
        return date;
    }

    // Check the buffers to equal
    function equalBuffers(r1, r2) {
        var s1 = new Uint8Array(r1),
                s2 = new Uint8Array(r2);
        if (s1.length !== s2.length)
            return false;
        for (var i = 0, n = s1.length; i < n; i++)
            if (s1[i] !== s2[i])
                return false;
        return true;
    }

    // Generate new alias
    function generateUUID() {
        var r = new Uint8Array(getSeed(16)), s = '';
        for (var i = 0; i < 16; i++)
            s += ('00' + r[i].toString(16)).slice(-2);
        return s.substr(0, 8) + '-' + s.substr(8, 4) + '-4' + s.substr(13, 3) +
                '-9' + s.substr(17, 3) + '-' + s.substr(20, 12);
    }

    // Return get32 from buffer
    function get32(buffer, offset) {
        var r = new Uint8Array(buffer, offset, 4);
        return (r[3] << 24) | (r[2] << 16) | (r[1] << 8) | r[0];
    }

    function set32(buffer, offset, int) {
        var r = new Uint8Array(buffer, offset, 4);
        r[3] = int >>> 24;
        r[2] = int >>> 16 & 0xff;
        r[1] = int >>> 8 & 0xff;
        r[0] = int & 0xff;
        return r;
    }

    // Salt size
    function saltSize(algorithm) {
        switch (algorithm.id) {
            case 'pbeWithSHAAnd40BitRC2-CBC':
            case 'pbeWithSHAAnd128BitRC2-CBC':
                return 8;
            case 'pbeUnknownGost':
                return 16;
            case 'sha1':
                return 20;
            default:
                return 32;
        }
    }

    // Password to bytes
    function passwordData(derivation, password) {
        if (!password)
            return new CryptoOperationData(0);
        if (derivation.name.indexOf('CPKDF') >= 0) {
            // CryptoPro store password
            var r = [];
            for (var i = 0; i < password.length; i++) {
                var c = password.charCodeAt(i);
                r.push(c & 0xff);
                r.push(c >>> 8 & 0xff);
                r.push(0);
                r.push(0);
            }
            return new Uint8Array(r).buffer;
        } else if (derivation.name.indexOf('PFXKDF') >= 0)
            // PKCS#12 unicode password
            return coding.Chars.decode(password + '\0', 'unicode');
        else
            // PKCS#5 password mode
            return coding.Chars.decode(password, 'utf8');
    }



    /**
     * Key and Certificate Store methods
     * 
     * @class GostKeys
     */
    function GostKeys() {
    }

    /**
     * Key templates
     * <ul>
     *      <li>providerName - provider name for key encryption, default 'CP-01'</li>
     *      <li>days - validity of the key in days, default 7305</li>
     * </ul>
     * 
     * @memberOf GostKeys
     * @instance
     */
    var options = {
        providerName: 'CP-01',
        days: 7305
    };

    GostKeys.prototype.options = options;

    /**
     * A class for private keys in PKCS #8 format
     * 
     * @class GostKeys.PKCS8
     * @extends GostASN1.PrivateKeyInfo
     * @param {(FormatedData|GostASN1.PrivateKeyInfo)} keyInfo
     */
    function PKCS8(keyInfo) {
        asn1.PrivateKeyInfo.call(this, keyInfo);
    }

    extend(asn1.PrivateKeyInfo, PKCS8, {
        /**
         * Get the private key
         * 
         * @memberOf GostKeys.PKCS8
         * @instance
         * @returns {Promise} Promise to return the {@link Key}
         */
        getPrivateKey: function ()
        {
            var keyUsages = (this.privateKeyAlgorithm.id === 'rsaEncryption') ? ['sign'] :
                    ['sign', 'deriveKey', 'deriveBits'];
            return subtle.importKey('pkcs8', this.encode(), this.privateKeyAlgorithm, 'true', keyUsages);
        },
        /**
         * Set the private key
         * 
         * @memberOf GostKeys.PKCS8
         * @instance
         * @param {Key} privateKey The Private Key
         * @returns {Promise} Promise to return the self object after set the key
         */
        setPrivateKey: function (privateKey)
        {
            var self = __webpack_require__.g;
            return subtle.exportKey('pkcs8', privateKey).then(function (keyInfo) {
                asn1.PrivateKeyInfo.call(self, keyInfo);
                return self;
            });
        },
        /**
         * Generate private key and return certification request
         * 
         * @memberOf GostKeys.PKCS8
         * @instance
         * @param {(FormatedData|GostASN1.CertificationRequest)} req The request templates
         * @param {(AlgorithmIdentifier|string)} keyAlgorithm The name of provider or algorithm identifier
         * @returns {Promise} Promise to return the {@link GostCert.Request} after key generation
         */
        generate: function (req, keyAlgorithm)
        {
            var self = __webpack_require__.g;
            return new Promise(call).then(function () {
                if (!(req instanceof cert.Request))
                    req = new cert.Request(req);
                // Generate request
                return req.generate(keyAlgorithm);
            }).then(function (key) {
                asn1.PrivateKeyInfo.call(self, key);
                ;
                return req;
            });
        }
    });

    /**
     * A class for private keys in PKCS #8 format
     * 
     * @memberOf GostKeys
     * @type GostKeys.PKCS8
     */
    GostKeys.prototype.PKCS8 = PKCS8;

    /**
     * A class for PKCS #5 and PKCS #12 password-encrypted private keys in PKCS #8 format
     * 
     * @class GostKeys.PKCS8Encrypted
     * @extends GostASN1.EncryptedPrivateKeyInfo
     * @param {(FormatedData|GostASN1.EncryptedPrivateKeyInfo)} encryptedKey
     */
    function PKCS8Encrypted(encryptedKey) {
        asn1.EncryptedPrivateKeyInfo.call(this, encryptedKey);
    }

    extend(asn1.EncryptedPrivateKeyInfo, PKCS8Encrypted, {
        /**
         * Get the private key info
         * 
         * @memberOf GostKeys.PKCS8Encrypted
         * @instance
         * @param {(Key|CryptoOperationData|string)} keyPassword The secret key or password for decryption 
         * @returns {Promise} Promise to return decrypted {@link GostKeys.PKCS8}
         */
        getKey: function (keyPassword)
        {
            var self = this, engine;
            return new Promise(call).then(function () {
                engine = new cms.EncryptedDataContentInfo({
                    contentType: 'encryptedData',
                    version: 0,
                    encryptedContentInfo: {
                        contentType: 'data',
                        contentEncryptionAlgorithm: self.encryptionAlgorithm,
                        encryptedContent: self.encryptedData
                    }
                });
                return engine.getEnclosed(keyPassword);
            }).then(function (contentInfo) {
                // Create key object
                return PKCS8.decode(contentInfo.content);
            });
        },
        /**
         * Get the private key
         * 
         * @memberOf GostKeys.PKCS8Encrypted
         * @instance
         * @param {(Key|CryptoOperationData|string)} keyPassword The secret key or password for decryption 
         * @returns {Promise} Promise to return decrypted {@link Key}
         */
        getPrivateKey: function (keyPassword)
        {
            return this.getKey(keyPassword).then(function (keyInfo) {
                return keyInfo.getPrivateKey();
            });
        },
        /**
         * Sets and encrypt the private key info
         * 
         * @memberOf GostKeys.PKCS8Encrypted
         * @instance
         * @param {(FormatedData|GostKeys.PKCS8)} keyInfo The private key info 
         * @param {(Key|CryptoOperationData|string)} keyPassword The secret key or password for encryption
         * @param {(AlgorithmIdentifier|string)} encryptionAlgorithm The encryption algorithm or provider name
         * @returns {Promise} Promise to return self object after set key 
         */
        setKey: function (keyInfo, keyPassword, encryptionAlgorithm)
        {
            var self = this, engine;
            return new Promise(call).then(function () {
                keyInfo = new PKCS8(keyInfo);
                engine = new cms.EncryptedDataContentInfo();
                return engine.encloseContent(keyInfo.encode(), keyPassword, encryptionAlgorithm || options.providerName);
            }).then(function () {
                self.encryptionAlgorithm = engine.encryptedContentInfo.contentEncryptionAlgorithm;
                self.encryptedData = engine.encryptedContentInfo.encryptedContent;
                return self;
            });
        },
        /**
         * Set the private key
         * 
         * @memberOf GostKeys.PKCS8Encrypted
         * @instance
         * @param {Key} privateKey The private key
         * @param {(Key|CryptoOperationData|string)} keyPassword The secret key or password for decryption 
         * @param {(AlgorithmIdentifier|string)} encryptionAlgorithm The encryption algorithm or provider name
         * @returns {Promise} Promise to return self object after set key 
         */
        setPrivateKey: function (privateKey, keyPassword, encryptionAlgorithm)
        {
            var self = __webpack_require__.g;
            return new PKCS8().setPrivateKey(privateKey).then(function (keyInfo) {
                return self.setKey(keyInfo, keyPassword, encryptionAlgorithm);
            });
        },
        /**
         * Generate private key and return certification request
         * 
         * @memberOf GostKeys.PKCS8Encrypted
         * @instance
         * @param {(FormatedData|GostASN1.CertificationRequest)} req The request templates
         * @param {(Key|CryptoOperationData|string)} keyPassword The secret key or password for decryption 
         * @param {(AlgorithmIdentifier|string)} keyAlgorithm The name of provider or algorithm
         * @param {(AlgorithmIdentifier|string)} encryptionAlgorithm The encryption algorithm or provider name
         * @returns {Promise} Promise to return {@link GostCert.Request}
         */
        generate: function (req, keyPassword, keyAlgorithm, encryptionAlgorithm)
        {
            var self = __webpack_require__.g;
            return new Promise(call).then(function () {
                if (!(req instanceof cert.Request))
                    req = new cert.Request(req);
                // Generate request
                return req.generate(keyAlgorithm);
            }).then(function (key) {
                return self.setKey(key, keyPassword, encryptionAlgorithm);
            }).then(function () {
                return req;
            });
        }
    });

    /**
     * A class for PKCS #5 and PKCS #12 password-encrypted private keys in PKCS #8 format
     * 
     * @memberOf GostKeys
     * @type GostKeys.PKCS8Encrypted
     */
    GostKeys.prototype.PKCS8Encrypted = PKCS8Encrypted;

    /**
     * A class for password-encrypted private keys in SignalCom container<br><br>
     * 
     * The container file list:
     * <ul>
     *      <li>mk.db3 - master key data</li>
     *      <li>masks.db3 - encrypted or decrypted masks</li>
     *      <li>kek.opq - wrapped key encryption key</li>
     *      <li>rand.opq - wrapped random data</li>
     * </ul>
     * 
     * @class GostKeys.SignalComKeyContainer
     * @param {SignalComKeyContainer} container 
     */
    function SignalComKeyContainer(container)
    {
        if (container) {
            var self = __webpack_require__.g;
            ['mk.db3', 'masks.db3', 'kek.opq', 'rand.opq'].forEach(function (name) {
                self[name] = container[name];
            });
        }
    }

    extend(Object, SignalComKeyContainer, {
        /**
         * Get password-based encryption key
         * 
         * @memberOf GostKeys.SignalComKeyContainer
         * @instance
         * @param {string} keyPassword 
         * @returns {Promise} Promise to return {@link Key}
         */
        getEncryptionKey: function (keyPassword)
        {
            var self = this, wrapping = providers['SC-01'].wrapping,
                    encryption = providers['SC-01'].encryption,
                    derivation = providers['SC-01'].derivation,
                    masks = self['masks.db3'], mk = self['mk.db3'], kek = self['kek.opq'];
            // Decrypt key
            return new Promise(call).then(function () {
                if ((!masks || !mk || !kek))
                    throw new Error('Not enougth key container files');
                // Check for encrypted key
                if (masks.byteLength > 32) {
                    if (keyPassword) {
                        // Extract password based encryption mask
                        return subtle.importKey('raw', coding.Chars.decode(keyPassword, 'utf8'),
                                derivation, false, ['deriveKey', 'deriveBits']).then(function (integrityKey) {
                            return subtle.deriveKey(expand(derivation,
                                    {salt: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0])}),
                                    integrityKey, encryption, false, ['decrypt']);
                        }).then(function (encryptionKey) {
                            var encrypted = new cms.EncryptedDataContentInfo(masks);
                            return encrypted.getEnclosed(encryptionKey);
                        }).then(function (digested) {
                            return digested.verify();
                        }).then(function (data) {
                            return data.content;
                        });
                    } else
                        throw new Error('Key password is required');
                } else if (keyPassword)
                    throw new Error('Key password is not required');
                return masks;
            }).then(function (decrypedMasks) {
                // Combine masks
                masks = decrypedMasks;
                var mkm = new Uint8Array(mk.byteLength + masks.byteLength);
                mkm.set(new Uint8Array(mk), 0);
                mkm.set(new Uint8Array(masks), mk.byteLength);
                // Import master key
                return subtle.importKey('raw', mkm.buffer, wrapping, false, ['unwrapKey']);
            }).then(function (unwrappingKey) {
                // Unwrap kek
                return subtle.unwrapKey('raw', kek, unwrappingKey, wrapping, encryption,
                        false, ['wrapKey', 'unwrapKey']);
            });
        },
        /**
         * Generate encryption key and container files
         * 
         * @memberOf GostKeys.SignalComKeyContainer
         * @instance
         * @param {string} keyPassword
         * @returns {Promise} Promise to return {@link Key}
         */
        generateContainer: function (keyPassword)
        {
            var self = this, wrapping = providers['SC-01'].wrapping,
                    encryption = providers['SC-01'].encryption,
                    derivation = providers['SC-01'].derivation,
                    digest = providers['SC-01'].digest,
                    encryptionKey, wrappingKey;
            return new Promise(call).then(function () {
                // Generate wrapping key
                return subtle.generateKey(wrapping, true, ['wrapKey']);
            }).then(function (key) {
                wrappingKey = key;
                // Split masks
                var len = wrappingKey.buffer.byteLength;
                self['mk.db3'] = new Uint8Array(new Uint8Array(wrappingKey.buffer, 0, len - 32)).buffer;
                var masks = new Uint8Array(new Uint8Array(wrappingKey.buffer, len - 32, 32)).buffer;
                if (keyPassword) {
                    // Encrypt masks
                    var encrypted = new cms.EncryptedDataContentInfo(),
                            digested = new cms.DigestedDataContentInfo();
                    // Digest data
                    return digested.encloseContent(masks, digest).then(function () {
                        digested = {// Double wrapping - SignalCom mistake
                            contentType: 'digestedData',
                            content: digested.encode()
                        };
                        return subtle.importKey('raw', coding.Chars.decode(keyPassword, 'utf8'),
                                derivation, false, ['deriveKey', 'deriveBits']);
                    }).then(function (integrityKey) {
                        return subtle.deriveKey(expand(derivation,
                                {salt: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0])}),
                                integrityKey, encryption, false, ['encrypt']);
                    }).then(function (encryptionKey) {
                        // Encrypt data with password
                        return encrypted.encloseContent(digested, encryptionKey, encryption);
                    }).then(function () {
                        return encrypted.encode();
                    });
                }
                return masks;
            }).then(function (masks) {
                self['masks.db3'] = masks;
                // Generate encryption key
                return subtle.generateKey(encryption, false, ['wrapKey', 'unwrapKey']);
            }).then(function (key) {
                encryptionKey = key;
                // Wrap encryption key
                return subtle.wrapKey('raw', key, wrappingKey, wrapping);
            }).then(function (data) {
                self['kek.opq'] = data;
                // Generate random seed
                return subtle.generateKey(encryption, false, ['wrapKey', 'unwrapKey']);
            }).then(function (key) {
                // Wrap random seed
                return subtle.wrapKey('raw', key, wrappingKey, wrapping);
            }).then(function (data) {
                self['rand.opq'] = data;
                return encryptionKey;
            });
        }
    });

    /**
     * A class for password-encrypted private keys in SignalCom container
     * 
     * @memberOf GostKeys
     * @type GostKeys.SignalComKeyContainer
     */
    GostKeys.prototype.SignalComKeyContainer = SignalComKeyContainer;

    /**
     * A class for password-encrypted SignalCom private keys
     * 
     * @class GostKeys.SignalComPrivateKeyInfo
     * @extends GostASN1.GostWrappedPrivateKey
     * @extends GostKeys.SignalComKeyContainer
     * @param {GostASN1.PrivateKeyInfo} keyInfo 
     * @param {GostKeys.SignalComKeyContainer} container 
     */
    function SignalComPrivateKeyInfo(keyInfo, container)
    {
        asn1.GostWrappedPrivateKey.call(this, keyInfo);
        SignalComKeyContainer.call(this, container);
    }

    extend(asn1.GostWrappedPrivateKey, SignalComPrivateKeyInfo, {
        /**
         * Get the private key info
         * 
         * @memberOf GostKeys.SignalComPrivateKeyInfo
         * @param {string} keyPassword The password for decryption 
         * @returns {Promise} Promise to return {@link GostKeys.PKCS8}
         */
        getKey: function (keyPassword)
        {
            return this.getPrivateKey(keyPassword).then(function (privateKey) {
                return new PKCS8().setPrivateKey(privateKey);
            });
        },
        /**
         * Get the private key
         * 
         * @memberOf GostKeys.SignalComPrivateKeyInfo
         * @instance
         * @param {string} keyPassword The password for decryption 
         * @returns {Promise} Promise to return the {@link Key}
         */
        getPrivateKey: function (keyPassword)
        {
            var self = this, wrapping = providers['SC-01'].wrapping,
                    publicKeyData;
            // Decrypt key
            return new Promise(call).then(function () {
                // Get password key
                return self.getEncryptionKey(keyPassword, true);
            }).then(function (encryptionKey) {
                // Unwrap private key
                return subtle.unwrapKey('raw', self.privateKeyWrapped, encryptionKey, wrapping,
                        self.privateKeyAlgorithm, true, ['sign', 'deriveKey', 'deriveBits']);
            }).then(function (privateKey) {
                publicKeyData = self.attributes && self.attributes['id-sc-gostR3410-2001-publicKey'];
                // Generate key pair
                if (publicKeyData)
                    return subtle.generateKey(expand(privateKey.algorithm, {ukm: privateKey.buffer}),
                            privateKey.extractable, privateKey.usages);
                else
                    return {privateKey: privateKey};
            }).then(function (keyPair) {
                // Compare public key
                if (publicKeyData && !equalBuffers(keyPair.publicKey.buffer, publicKeyData))
                    throw new Error('Check public key failed');
                return keyPair.privateKey;
            });
        },
        /**
         * Sets and encrypt the private key info
         * 
         * @memberOf GostKeys.SignalComPrivateKeyInfo
         * @instance
         * @param {(FormatedData|GostKeys.PKCS8)} keyInfo The private key info 
         * @param {string} keyPassword The password for encryption
         * @returns {Promise} Promise to return self object after set the key
         */
        setKey: function (keyInfo, keyPassword)
        {
            var self = __webpack_require__.g;
            return new PKCS8(keyInfo).getPrivateKey().then(function (privateKey) {
                return self.setPrivateKey(privateKey, keyPassword);
            });
        },
        /**
         * Set the private key
         * 
         * @memberOf GostKeys.SignalComPrivateKeyInfo
         * @instance
         * @param {Key} privateKey The private key
         * @param {string} keyPassword The secret key encryption 
         * @returns {Promise} Promise to return self object after set the key
         */
        setPrivateKey: function (privateKey, keyPassword)
        {
            var self = this, wrapping = providers['SC-01'].wrapping, wrappedData;
            return new Promise(call).then(function () {
                // Get or generate encryption key
                return self.getEncryptionKey(keyPassword)['catch'](function () {
                    return self.generateContainer(keyPassword);
                });
            }).then(function (encryptionKey) {
                // Encrypt key buffer
                return subtle.wrapKey('raw', privateKey, encryptionKey, wrapping);
            }).then(function (data) {
                wrappedData = data;
                // Generate public key
                return subtle.generateKey(expand(privateKey.algorithm,
                        {ukm: privateKey.buffer}), true, ['sign', 'verify']);
            }).then(function (keyPair) {
                self.object = {
                    version: 0,
                    privateKeyAlgorithm: privateKey.algorithm,
                    privateKeyWrapped: wrappedData,
                    attributes: {
                        'id-sc-gostR3410-2001-publicKey': keyPair.publicKey.buffer
                    }
                };
                return self;
            });
        },
        /**
         * Change key password
         * 
         * @memberOf GostKeys.SignalComPrivateKeyInfo
         * @instance
         * @param {string} oldKeyPassword Old key password
         * @param {string} newKeyPassword New key password
         * @returns {Promise} Promise to return self object after change password
         */
        changePassword: function (oldKeyPassword, newKeyPassword)
        {
            var self = __webpack_require__.g;
            return self.getPrivateKey(oldKeyPassword).then(function (privateKey) {
                return self.setPrivateKey(privateKey, newKeyPassword);
            });
        },
        /**
         * Generate private key, certificate and return certification request
         * 
         * @memberOf GostKeys.SignalComPrivateKeyInfo
         * @instance
         * @param {(FormatedData|GostASN1.CertificationRequest)} req The request templates
         * @param {(Key|CryptoOperationData|string)} keyPassword The secret key or password for decryption 
         * @param {(AlgorithmIdentifier|string)} keyAlgorithm The name of provider or algorithm
         * @returns {Promise} Promise to return {@link GostCert.Request}
         */
        generate: function (req, keyPassword, keyAlgorithm)
        {
            var self = this, keyInfo;
            return new Promise(call).then(function () {
                if (!(req instanceof cert.Request))
                    req = new cert.Request(req);
                // Generate request
                return req.generate(keyAlgorithm);
            }).then(function (key) {
                keyInfo = key;
                return self.setKey(keyInfo, keyPassword);
            }).then(function () {
                return req;
            });
        }
    });
    defineProperties(SignalComPrivateKeyInfo.prototype, SignalComKeyContainer.prototype);

    /**
     * A class for password-encrypted SignalCom private keys
     * 
     * @memberOf GostKeys
     * @type GostKeys.SignalComPrivateKeyInfo
     */
    GostKeys.prototype.SignalComPrivateKeyInfo = SignalComPrivateKeyInfo;

    /**
     * A class for password-encrypted private keys in CryptoPro container
     * 
     * The container file list:
     * <ul>
     *      <li>header - container header @link GostASN1.GostKeyContainer</li>
     *      <li>name - container name @link GostASN1.GostKeyContainerName</li>
     *      <li>primary - private keys data @link GostASN1.GostPrivateKeys</li>
     *      <li>masks - private key masks @link GostASN1.GostPrivateMasks</li>
     *      <li>primary2 - reserve of private keys data @link GostASN1.GostPrivateKeys</li>
     *      <li>masks2 - reserve of private key masks @link GostASN1.GostPrivateMasks</li>
     * </ul>
     * 
     * @class GostKeys.CryptoProKeyContainer
     * @param {Object} container 
     */
    function CryptoProKeyContainer(container)
    {
        if (container) {
            this.header = asn1.GostKeyContainer.decode(container.header);
            this.name = asn1.GostKeyContainerName.decode(container.name);
            this.primary = asn1.GostPrivateKeys.decode(container.primary);
            this.masks = asn1.GostPrivateMasks.decode(container.masks);
            if (container.primary2 && container.masks2) {
                this.primary2 = asn1.GostPrivateKeys.decode(container.primary2);
                this.masks2 = asn1.GostPrivateMasks.decode(container.masks2);
            }
        }
    }

    extend(Object, CryptoProKeyContainer, (function () {


        // True if 512 bit
        function isKeySize512(algorithm) {
            return algorithm.name.indexOf('-512') >= 0 || algorithm.length === 512;
        }

        // Test version 2012
        function isVersion2012(algorithm) {
            return !((algorithm.name.indexOf('-94') >= 0 || algorithm.name.indexOf('-2001') >= 0 ||
                    algorithm.version === 1994 || algorithm.version === 2001));
        }

        // Derive password key
        function derivePasswordKey(algorithm, password, salt) {
            var hash = isVersion2012(algorithm) ? 'GOST R 34.11-256' : 'GOST R 34.11-94/' + (algorithm.sBox || 'D-A'),
                    derivation = {name: 'CPKDF', hash: hash, salt: salt, iterations: password ? 2000 : 2};

            // Import password
            return subtle.importKey('raw', passwordData(derivation, password),
                    derivation, false, ['deriveKey', 'deriveBits']).then(function (baseKey) {

                // Derive key
                return subtle.deriveKey(derivation, baseKey, 'GOST 28147',
                        false, ['sign', 'verify', 'encrypt', 'decrypt']);
            });
        }

        // Compute password MAC 
        function computePasswordMAC(algorithm, password, salt) {
            var mac = expand({name: 'GOST 28147-MAC'}, algorithm.encParams);

            // Derive password
            return derivePasswordKey(algorithm, password, salt).then(function (macKey) {

                // Mac for 16 zero bytes
                return subtle.sign(mac, macKey,
                        new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
            });
        }

        //        var lastBuffer;
        // Compute container MAC
        function computeContainerMAC(algorithm, content) {
            var mac = expand({name: 'GOST 28147-MAC'}, algorithm.encParams),
                    keyData = new Uint8Array([// 32 zero bytes
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
            return subtle.importKey('raw', keyData, mac, false, ['sign']).then(function (macKey) {
                //                var buffer = new Uint8Array(content.encode());
                //                console.log(coding.Hex.encode(buffer));
                //                if (lastBuffer && lastBuffer.length === buffer.length) {
                //                    for (var i = 0; i < buffer.length; i++)
                //                        if (lastBuffer[i] !== buffer[i])
                //                            console.log('diff at ' + i);
                //                } else
                //                    console.log('diff length');
                //                lastBuffer = buffer;
                // Mac for content
                return subtle.sign(mac, macKey, content.encode());
            });
        }

        // Compute mask MAC
        function computeMaskMAC(algorithm, mask, status) {
            // Import mask as key for MAC
            var mac = expand({name: 'GOST 28147-MAC'}, algorithm.encParams),
                    keyData = mask.byteLength === 64 ?
                    new Uint8Array(new Uint8Array(mask, 32, 32)).buffer : mask;
            return subtle.importKey('raw', keyData, mac, false, ['sign']).then(function (macKey) {

                // Verify MAC for maskStatus
                return subtle.sign(mac, macKey, status);
            });
        }

        // Generate mask
        function generateMasks(algorithm) {
            var wrapAlgorithm = expand(algorithm, {mode: 'MASK'}),
                    mask, status = getSeed(12);
            wrapAlgorithm.name = wrapAlgorithm.name.replace('-DH', '');
            return subtle.generateKey(wrapAlgorithm, true, ['wrapKey', 'unwrapKey']).then(function (key) {
                return subtle.exportKey('raw', key);
            }).then(function (data) {
                mask = data;
                return computeMaskMAC(algorithm, mask, status);
            }).then(function (hmac) {
                return new asn1.GostPrivateMasks({
                    mask: mask,
                    randomStatus: status,
                    hmacRandom: hmac
                });
            });
        }

        // Compute FP
        function computeFP(privateKey) {
            // Generate key pair with predefined ukm for check public key
            return subtle.generateKey(expand(privateKey.algorithm, {ukm: privateKey.buffer}), true, ['sign', 'verify']).then(function (keyPair) {
                return new Uint8Array(new Uint8Array(keyPair.publicKey.buffer, 0, 8)).buffer;
            });
        }

        // Unwrap private key
        function unwrapKey(algorithm, encryptionKey, key, mask, fp) {
            var encryption = {name: 'GOST 28147-ECB', sBox: algorithm.encParams && algorithm.encParams.sBox},
            unwrapAlgorithm = expand(algorithm, {mode: 'MASK'}), privateKey;
            unwrapAlgorithm.name = unwrapAlgorithm.name.replace('-DH', '');
            var wrappedKey;

            // Encrypt ukm data for private key
            return subtle.decrypt(encryption, encryptionKey, key).then(function (data) {
                wrappedKey = data;
                // Import mask key
                return subtle.importKey('raw', mask, unwrapAlgorithm, 'false', ['sign', 'unwrapKey']);
            }).then(function (unwrappingKey) {

                // Unwrap private key
                return subtle.unwrapKey('raw', wrappedKey, unwrappingKey,
                        unwrapAlgorithm, algorithm, 'true', ['sign']);
            }).then(function (key) {
                privateKey = key;
                return computeFP(privateKey);
            }).then(function (computedFP) {
                // Check public key buffer
                if (!equalBuffers(computedFP, fp))
                    throw new Error('Incorrect fp');

                return privateKey;
            });

        }

        // Wrap private key
        function wrapKey(algorithm, encryptionKey, privateKey, mask) {
            var encryption = {name: 'GOST 28147-ECB', sBox: algorithm.encParams && algorithm.encParams.sBox},
            wrapAlgorithm = expand(algorithm, {mode: 'MASK'});
            wrapAlgorithm.name = wrapAlgorithm.name.replace('-DH', '');

            // Import mask key
            return subtle.importKey('raw', mask, wrapAlgorithm, false,
                    ['sign', 'wrapKey']).then(function (wrappingKey) {
                // Wrap private key
                return subtle.wrapKey('raw', privateKey, wrappingKey, wrapAlgorithm);
            }).then(function (wrappedKey) {
                // Encrypt key
                return subtle.encrypt(encryption, encryptionKey, wrappedKey);
            });
        }

        // Decrypt private key
        function decryptKey(content, primary, masks, keyPassword, secondary) {
            var algorithm = content.primaryPrivateKeyParameters.privateKeyAlgorithm;
            return new Promise(call).then(function () {
                // Check format
                if (primary.hmacKey)
                    throw new Error('Old key format');

                if (masks.randomStatus.byteLength < 12)
                    throw new Error("Invalid random status length");

                // Import mask as key for MAC
                return computeMaskMAC(algorithm, masks.mask, masks.randomStatus);
            }).then(function (hmac) {
                if (!equalBuffers(hmac, masks.hmacRandom))
                    throw new Error("Imita for mask is invalid");

                // Derive key
                return derivePasswordKey(algorithm, keyPassword, new Uint8Array(masks.randomStatus, 0, 12));
            }).then(function (encryptionKey) {
                // Unwrap keys
                return secondary && primary.secondaryKey ?
                        unwrapKey(content.secondaryPrivateKeyParameters.privateKeyAlgorithm,
                                encryptionKey, primary.secondaryKey, masks.mask, content.secondaryFP) :
                        unwrapKey(algorithm, encryptionKey, primary.primaryKey, masks.mask, content.primaryFP);
            });
        }

        // Encrypt private key
        function encryptKey(algorithm, primary, masks, keyPassword, secondary, privateKey) {
            // Derive key
            return derivePasswordKey(algorithm, keyPassword, new Uint8Array(masks.randomStatus, 0, 12)).then(function (encryptionKey) {
                // Wrap keys
                return wrapKey(algorithm, encryptionKey, privateKey, masks.mask);
            }).then(function (encryptedKey) {
                if (!primary)
                    primary = new asn1.GostPrivateKeys();
                if (secondary) {
                    primary.secondaryKey = encryptedKey;
                } else {
                    primary.primaryKey = encryptedKey;
                }
                return primary;
            });
        }



        return {
            /**
             * Get the private key info
             * 
             * @memberOf GostKeys.CryptoProKeyContainer
             * @instance
             * @param {string} keyPassword The password for decryption 
             * @param {boolean} secondary True if required secondary key
             * @returns {Promise} Promise to return {@link GostKeys.PKCS8}
             */
            getKey: function (keyPassword, secondary)
            {
                return this.getPrivateKey(keyPassword, secondary).then(function (privateKey) {
                    return new PKCS8().setPrivateKey(privateKey);
                });
            },
            /**
             * Get the private key
             * 
             * @memberOf GostKeys.CryptoProKeyContainer
             * @instance
             * @param {string} keyPassword Rhe password for decryption 
             * @param {boolean} secondary True if required secondary key
             * @returns {Promise} Promise to return the {@link Key}
             */
            getPrivateKey: function (keyPassword, secondary)
            {
                var self = this, content = self.header.keyContainerContent;
                // Decrypt key
                return decryptKey(content, self.primary, self.masks, keyPassword, secondary)['catch'](function (e) {
                    if (self.primary2 && self.masks2)
                        return decryptKey(content, self.primary2, self.masks2, keyPassword, secondary);
                    else
                        throw e;
                });
            },
            /**
             * Get the certificate from the key container
             * 
             * @memberOf GostKeys.CryptoProKeyContainer
             * @instance
             * @param {boolean} secondary True for set secondary certificate
             * @returns {Promise} Promise to return {@link GostCert.X509}
             */
            getCertificate: function (secondary)
            {
                var self = this, content = self.header.keyContainerContent;
                return new Promise(call).then(function () {
                    if (secondary)
                        return new cert.X509(content.secondaryCertificate);
                    else
                        return new cert.X509(content.primaryCertificate);
                });
            },
            /**
             * Get the container name
             * 
             * @memberOf GostKeys.CryptoProKeyContainer
             * @instance
             * @returns {string} Container name
             */
            getContainerName: function ()
            {
                return this.name.containerName;
            },
            /**
             * Sets and encrypt the private key info
             * 
             * @memberOf GostKeys.CryptoProKeyContainer
             * @instance
             * @param {(FormatedData|GostKeys.PKCS8)} keyInfo The private key info 
             * @param {string} keyPassword The assword for encryption
             * @param {boolean} secondary True for set secondary key
             * @param {number} days Validity days. Default 7305 days (20 years)
             * @returns {Promise} Promise to return self object after set key
             */
            setKey: function (keyInfo, keyPassword, secondary, days)
            {
                var self = __webpack_require__.g;
                return new PKCS8(keyInfo).getPrivateKey().then(function (privateKey) {
                    return self.setPrivateKey(privateKey, keyPassword, secondary, days);
                });
            },
            /**
             * Set the private key
             * 
             * @memberOf GostKeys.CryptoProKeyContainer
             * @instance
             * @param {Key} privateKey The private key
             * @param {string} keyPassword The secret key encryption 
             * @param {boolean} secondary True for set secondary key
             * @param {number} days Validity days. Default 7305 days (20 years)
             * @returns {Promise} Promise to return self object after set key
             */
            setPrivateKey: function (privateKey, keyPassword, secondary, days)
            {
                var self = this, content, algorithm;
                return new Promise(call).then(function () {
                    self.header = self.header || new asn1.GostKeyContainer({
                        keyContainerContent: {
                            containerAlgoritmIdentifier: {
                                algorithm: 'id-CryptoPro-GostPrivateKeys-V2-Full'
                            },
                            attributes: ['kccaReservePrimary', 'kccaPrimaryKeyAbsent'],
                            extensions: {
                                keyValidity: {
                                    notAfter: now(days || options.days)
                                }
                            }
                        }
                    });
                    content = self.header.keyContainerContent;
                    // Set private key                    
                    var keyParameters = secondary ? content.secondaryPrivateKeyParameters :
                            content.primaryPrivateKeyParameters;
                    if (!keyParameters) {
                        algorithm = expand(privateKey.algorithm, {
                            sBox: "D-A",
                            encParams: {
                                block: "CFB",
                                sBox: "E-A",
                                keyMeshing: "CP"
                            }
                        });
                        keyParameters = {
                            attributes: ["pkaExportable", "pkaExchange", "pkaDhAllowed"],
                            privateKeyAlgorithm: algorithm
                        };
                        if (secondary) {
                            if (!content.primaryPrivateKeyParameters)
                                throw new Error('Primary key must be defined first');
                            content.secondaryPrivateKeyParameters = keyParameters;
                        } else {
                            content.primaryPrivateKeyParameters = keyParameters;
                            var absent = content.attributes.indexOf('kccaPrimaryKeyAbsent');
                            if (absent >= 0)
                                content.attributes.splice(absent, 1);
                        }
                    } else
                        algorithm = keyParameters.privateKeyAlgorithm;
                    // Generate masks
                    var promises = [];
                    [0, 1].forEach(function (i) {
                        var name = 'masks' + (i > 0 ? '2' : '');
                        if (!self[name])
                            promises.push(generateMasks(algorithm).then(function (masks) {
                                self[name] = masks;
                            }));
                    });
                    return Promise.all(promises);
                }).then(function () {
                    // Encrypt key
                    var promises = [];
                    [0, 1].forEach(function (i) {
                        var name = 'primary' + (i > 0 ? '2' : ''),
                                maskname = 'masks' + (i > 0 ? '2' : '');
                        promises.push(encryptKey(algorithm, self[name], self[maskname], keyPassword, secondary, privateKey).then(function (primary) {
                            self[name] = primary;
                        }));
                    });
                    return Promise.all(promises);
                }).then(function () {
                    // Compute FP for a private key
                    return computeFP(privateKey).then(function (FP) {
                        if (secondary)
                            content.secondaryFP = FP;
                        else
                            content.primaryFP = FP;
                    });
                }).then(function () {
                    // Compute password MAC
                    var softPassword = content.attributes.indexOf('kccaSoftPassword');
                    if (keyPassword) {
                        if (softPassword < 0)
                            content.attributes.push('kccaSoftPassword');
                        return computePasswordMAC(algorithm, keyPassword, content.primaryFP);
                    } else {
                        if (softPassword >= 0)
                            content.attributes.splice(softPassword, 1);
                    }
                }).then(function (hmac) {
                    if (hmac)
                        content.hmacPassword = hmac;
                    // Calculate container MAC
                    return computeContainerMAC(algorithm, content);
                }).then(function (hmac) {
                    self.header.hmacKeyContainerContent = hmac;
                    return self;
                });
            },
            /**
             * Set the certificate to the key container
             * 
             * @memberOf GostKeys.CryptoProKeyContainer
             * @instance
             * @param {(FormatedData|GostCert.X509)} certificate The certificate
             * @param {boolean} secondary True for set secondary certificate
             * @param {number} days Validity days. Default 7305 days (20 years)
             * @returns {Promise} Promise to return self object after set certificate
             */
            setCertificate: function (certificate, secondary, days)
            {
                var self = this, content, algorithm;
                return new Promise(call).then(function () {
                    self.header = self.header || new asn1.GostKeyContainer({
                        keyContainerContent: {
                            containerAlgoritmIdentifier: {
                                algorithm: 'id-CryptoPro-GostPrivateKeys-V2-Full'
                            },
                            attributes: ['kccaReservePrimary', 'kccaPrimaryKeyAbsent'],
                            extensions: {
                                keyValidity: {
                                    notAfter: now(days || options.days)
                                }
                            }
                        }
                    });
                    content = self.header.keyContainerContent;
                    certificate = new cert.X509(certificate);
                    algorithm = (content.primaryPrivateKeyParameters &&
                            content.primaryPrivateKeyParameters.privateKeyAlgorithm) ||
                            expand(certificate.subjectPublicKeyInfo.algorithm, {
                                sBox: "D-A",
                                encParams: {
                                    block: "CFB",
                                    sBox: "E-A",
                                    keyMeshing: "CP"
                                }
                            });
                    return certificate.getPublicKey();
                }).then(function (publicKey) {
                    if (secondary) {
                        if (content.secondaryFP && !equalBuffers(content.secondaryFP,
                                new Uint8Array(publicKey.buffer, 0, content.secondaryFP.byteLength)))
                            throw new Error('The public key of the certificate does not match the private key');
                        content.secondaryCertificate = certificate;
                    } else {
                        if (content.primaryFP && !equalBuffers(content.primaryFP,
                                new Uint8Array(publicKey.buffer, 0, content.primaryFP.byteLength)))
                            throw new Error('The public key of the certificate does not match the private key');
                        content.primaryCertificate = certificate;
                    }
                    // Calculate container MAC
                    return computeContainerMAC(algorithm, content);
                }).then(function (hmac) {
                    self.header.hmacKeyContainerContent = hmac;
                    return self;
                });
            },
            /**
             * Set the container name
             * 
             * @memberOf GostKeys.CryptoProKeyContainer
             * @instance
             * @param {string} name Container name
             */
            setContainerName: function (name)
            {
                this.name = new asn1.GostKeyContainerName({containerName: name});
            },
            /**
             * Verify key container with password
             * 
             * @memberOf GostKeys.CryptoProKeyContainer
             * @instance
             * @param {string} keyPassword the secret key or password for decryption 
             * @returns {Promise} Promise to return self object after verify
             */
            verify: function (keyPassword)
            {
                var self = this, content, algorithm;
                return new Promise(call).then(function () {
                    content = self.header.keyContainerContent;
                    algorithm = content.primaryPrivateKeyParameters.privateKeyAlgorithm;
                    // Verify container MAC
                    return computeContainerMAC(algorithm, content);
                }).then(function (hmac) {
                    if (!equalBuffers(hmac, self.header.hmacKeyContainerContent))
                        throw new Error("Container is not valid.");
                    // Verify key password MAC
                    var needPassword = content.attributes.indexOf('kccaSoftPassword') >= 0;
                    if (!keyPassword && needPassword)
                        throw new Error("Password is required");
                    if (keyPassword && !needPassword)
                        throw new Error("Password is not reqiured.");
                    if (keyPassword)
                        // Derive password
                        return computePasswordMAC(algorithm, keyPassword, content.primaryFP).then(function (hmac) {
                            if (!equalBuffers(hmac, content.hmacPassword))
                                throw new Error("Password is not valid.");
                            return self;
                        });
                    return self;
                });
            },
            /**
             * Change key password
             * 
             * @memberOf GostKeys.CryptoProKeyContainer
             * @instance
             * @param {string} oldKeyPassword Old key password
             * @param {string} newKeyPassword New key password
             * @returns {Promise} Promise to return self object after change password
             */
            changePassword: function (oldKeyPassword, newKeyPassword)
            {
                var self = this, content;
                return new Promise(call).then(function () {
                    content = self.header.keyContainerContent;
                    if (!content.primaryPrivateKeyParameters)
                        throw new Error('Private key not yet defined');
                    return self.getPrivateKey(oldKeyPassword).then(function (privateKey) {
                        return self.setPrivateKey(privateKey, newKeyPassword);
                    });
                }).then(function () {
                    if (content.secondaryPrivateKeyParameters)
                        return self.getPrivateKey(oldKeyPassword, true).then(function (privateKey) {
                            return self.setPrivateKey(privateKey, newKeyPassword, true);
                        });
                    return self;
                });
            },
            /**
             * Generate private key, certificate and return certification request
             * 
             * @memberOf GostKeys.CryptoProKeyContainer
             * @instance
             * @param {(FormatedData|GostASN1.CertificationRequest)} req The request templates
             * @param {(Key|CryptoOperationData|string)} keyPassword The secret key or password for decryption 
             * @param {(AlgorithmIdentifier|string)} keyAlgorithm The name of provider or algorithm
             * @returns {Promise} Promise to return {@link GostCert.Request}
             */
            generate: function (req, keyPassword, keyAlgorithm)
            {
                var self = this, certificate, keyInfo;
                return new Promise(call).then(function () {
                    if (!(req instanceof cert.Request))
                        req = new cert.Request(req);
                    // Generate request
                    return req.generate(keyAlgorithm);
                }).then(function (key) {
                    keyInfo = key;
                    return self.setKey(keyInfo, keyPassword);
                }).then(function () {
                    // Create the new certificate
                    certificate = new cert.X509(req);
                    return certificate.sign(keyInfo);
                }).then(function () {
                    return self.setCertificate(certificate);
                }).then(function () {
                    return req;
                });
            },
            /**
             * Encode key container
             * 
             * @memberOf GostKeys.CryptoProKeyContainer
             * @instance
             * @param {string} format Encode format 'DER', 'CER', 'PEM'
             * @returns {Object} container Object contains encoded files
             */
            encode: function (format)
            {
                return {
                    header: this.header.encode(format),
                    name: this.name.encode(format),
                    masks: this.masks.encode(format),
                    primary: this.primary.encode(format),
                    masks2: this.masks2.encode(format),
                    primary2: this.primary2.encode(format)
                };
            }
        };
    })());

    /**
     * A class for password-encrypted private keys in CryptoPro container
     * 
     * @memberOf GostKeys
     * @type GostKeys.SignalComPrivateKeyInfo
     */
    GostKeys.prototype.CryptoProKeyContainer = CryptoProKeyContainer;

    /**
     * A class for password-encrypted private keys in ViPNet container entry
     * 
     * @class GostKeys.ViPNetContainerEntry
     * @extends GostASN1.ViPNetInfo
     * @param {(FormatedData|GostKeys.ViPNetContainerEntry)} entry 
     */
    function ViPNetContainerEntry(entry)
    {
        asn1.ViPNetInfo.call(this, entry || {
            version: 3,
            keyInfo: {
                keyClass: 1,
                keyType: 43556,
                flags: 1
            },
            defenceKeyInfo: {
                keyClass: 1024,
                keyType: 24622,
                keyUID: getSeed(32),
                flags: -2147483648
            }
        });
    }

    extend(asn1.ViPNetInfo, ViPNetContainerEntry, (function () {

        function getKeyPassword(keyPassword)
        {
            if (keyPassword === undefined)
                keyPassword = '';
            // Generate key data
            var passwordData = coding.Chars.decode(keyPassword, 'win1251'), keyData;
            return subtle.digest('GOST R 34.11-94', passwordData).then(function (data) {
                keyData = data;
                // Generate mask data
                var secodeData = new Uint8Array(passwordData.byteLength + keyData.byteLength);
                secodeData.set(new Uint8Array(passwordData), 0);
                secodeData.set(new Uint8Array(keyData), passwordData.byteLength);
                return subtle.digest('GOST R 34.11-94', secodeData);
            }).then(function (data) {
                // Remove mask
                return subtle.importKey('raw', data, 'GOST 28147', false, ['unwrapKey']);
            }).then(function (unwrappingKey) {
                // Unwrap secret key
                return subtle.unwrapKey('raw', keyData, unwrappingKey,
                        'GOST 28147-MASK/VN', 'GOST 28147-89',
                        'false', ['encrypt', 'decrypt', 'sign', 'verify']);
            });
        }

        return {
            /**
             * Get the private key
             * 
             * @memberOf GostKeys.ViPNetContainerEntry
             * @instance
             * @param {string} keyPassword The password of secrect key for decryption 
             * @returns {Promise} Promise to return the {@link Key}
             */
            getPrivateKey: function (keyPassword)
            {
                var self = this, keyPart, encryptedKey;
                // Decrypt key
                return new Promise(call).then(function () {
                    return !keyPassword || typeof keyPassword === 'string' ?
                            getKeyPassword(keyPassword) : keyPassword;
                }).then(function (key) {
                    keyPassword = key;
                    // Verify password    
                    keyPart = self.keyPart;
                    encryptedKey = new Uint8Array(keyPart, 0, keyPart.byteLength - 4 - 8);
                    var macKey = new Uint8Array(keyPart, encryptedKey.byteLength, 4),
                            encodedKeyInfo = self.keyInfo.encode(),
                            data = new Uint8Array(encryptedKey.byteLength + encodedKeyInfo.byteLength);
                    data.set(new Uint8Array(encryptedKey), 0);
                    data.set(new Uint8Array(encodedKeyInfo), encryptedKey.byteLength);
                    return subtle.verify({name: 'GOST 28147-89-MAC'}, keyPassword, macKey, data);
                }).then(function (result) {
                    if (!result)
                        throw new Error('Invalid key password');
                    var iv = new Uint8Array(keyPart, keyPart.byteLength - 8, 8);
                    // Decrypt key data
                    return subtle.decrypt({name: 'GOST 28147-89-CFB', iv: iv}, keyPassword, encryptedKey);
                }).then(function (keyData) {
                    var l2 = keyData.byteLength / 2;
                    if (self.keyInfo.keyClass & 0x3 === 0) {
                        // Secret key. Remove mask and import
                        return subtle.importKey('raw', new Int32Array(keyData, l2, l2), 'GOST 28147', false,
                                ['unwrapKey']).then(function (unwrappingKey) {
                            // Unwrap secret key
                            return subtle.unwrapKey('raw', new Int32Array(keyData, 0, l2), unwrappingKey,
                                    'GOST 28147-MASK/VN', 'GOST 28147-89',
                                    'false', ['encrypt', 'decrypt', 'sign', 'verify']);
                        });
                    } else {
                        // Private key
                        var algorithm = self.keyInfo.algorithm ||
                                (self.certificate && self.certificate.subjectPublicKeyInfo.algorithm);
                        if (!algorithm)
                            throw new Error('Algorithm is not specified');
                        var unwrapAlgorithm = expand(algorithm, {mode: 'MASK', procreator: 'VN'});
                        unwrapAlgorithm.name = unwrapAlgorithm.name.replace('-DH', '');
                        var wrapped = new Uint8Array(keyData, 0, l2),
                                mask = new Uint8Array(keyData, l2, l2);
                        // Import mask key
                        return subtle.importKey('raw', mask, unwrapAlgorithm, 'false', ['sign', 'unwrapKey']).then(function (unwrappingKey) {
                            // Unwrap private key
                            return subtle.unwrapKey('raw', wrapped, unwrappingKey, unwrapAlgorithm, algorithm, 'true', ['sign', 'deriveBits', 'deriveKey']);
                        }).then(function (privateKey) {
                            // Generate key pair
                            if (self.publicKey)
                                return subtle.generateKey(expand(privateKey.algorithm, {ukm: privateKey.buffer}),
                                        privateKey.extractable, privateKey.usages);
                            else
                                return {privateKey: privateKey};
                        }).then(function (keyPair) {
                            // Compare public key
                            if (self.publicKey && !equalBuffers(keyPair.publicKey.buffer, self.publicKey))
                                throw new Error('Check public key failed');
                            return keyPair.privateKey;
                        });
                    }
                });
            },
            /**
             * Set the private key
             * 
             * @memberOf GostKeys.ViPNetContainerEntry
             * @instance
             * @param {Key} privateKey The private key
             * @param {string} keyPassword The secret key encryption 
             * @param {number} days Validity days. Default 7305 days (20 years)
             * @returns {Promise} Promise to return the self object after set the key
             */
            setPrivateKey: function (privateKey, keyPassword, days)
            {
                var self = this, wrapAlgorithm, wrappingKey, keyData, keyPart;
                // Decrypt key
                return new Promise(call).then(function () {
                    return !keyPassword || typeof keyPassword === 'string' ?
                            getKeyPassword(keyPassword) : keyPassword;
                }).then(function (key) {
                    keyPassword = key;
                    var algorithm = privateKey.algorithm;
                    self.keyInfo.algorithm = algorithm;
                    self.keyInfo.serialNumber = getSeed(16);
                    self.keyInfo.keyUID = getSeed(8);
                    self.keyInfo.validity = {
                        notBefore: today(),
                        notAfter: today(days || options.days)
                    };
                    if (privateKey.type === 'private') {
                        // Generate mask
                        wrapAlgorithm = expand(algorithm, {mode: 'MASK', procreator: 'VN'});
                        wrapAlgorithm.name = wrapAlgorithm.name.replace('-DH', '');
                        self.keyInfo.keyClass = 1;
                        self.keyInfo.keyType = 43556;
                        // Generate public key
                        return subtle.generateKey(expand(algorithm, {ukm: privateKey.buffer}), true,
                                ['sign', 'verify']).then(function (keyPair) {
                            self.publicKey = keyPair.publicKey.buffer;
                            // Check certificate
                            if (self.certificate) {
                                var spki = self.certificate.subjectPublicKeyInfo;
                                return subtle.importKey('spki', spki.encode(), spki.algorithm, true, ['verify']);
                            }
                        }).then(function (publicKey) {
                            if (publicKey && !equalBuffers(publicKey.buffer, self.publicKey))
                                delete self.certificate; // Remove not valid certificate
                        });
                    } else if (privateKey.type === 'secret') {
                        wrapAlgorithm = 'GOST 28147/MASK/VN';
                        delete self.certificate;
                        delete self.publicKey;
                        self.keyInfo.keyClass = 64;
                        self.keyInfo.keyType = 24622;
                    } else
                        throw new Error('Invalid key type');
                }).then(function () {
                    // Generate mask
                    return subtle.generateKey(wrapAlgorithm, true, ['wrapKey', 'unwrapKey']);
                }).then(function (key) {
                    wrappingKey = key;
                    // Wrap private key with mask
                    return subtle.wrapKey('raw', privateKey, wrappingKey, wrapAlgorithm);
                }).then(function (data) {
                    keyData = new Uint8Array(data.byteLength * 2);
                    keyData.set(new Uint8Array(data));
                    return subtle.exportKey('raw', wrappingKey);
                }).then(function (data) {
                    keyData.set(new Uint8Array(data), data.byteLength);
                    keyPart = new Uint8Array(keyData.byteLength + 12);
                    // Encrypt key
                    var encyption = {name: 'GOST 28147-CFB', iv: getSeed(8)};
                    keyPart.set(new Uint8Array(encyption.iv), keyPart.byteLength - 8);
                    return subtle.encrypt(encyption, keyPassword, keyData);
                }).then(function (encryptedKey) {
                    keyPart.set(new Uint8Array(encryptedKey));
                    // Calculate MAC
                    var encodedKeyInfo = self.keyInfo.encode(),
                            data = new Uint8Array(encryptedKey.byteLength + encodedKeyInfo.byteLength);
                    data.set(new Uint8Array(encryptedKey), 0);
                    data.set(new Uint8Array(encodedKeyInfo), encryptedKey.byteLength);
                    return subtle.sign({name: 'GOST 28147-89-MAC'}, keyPassword, data);
                }).then(function (macKey) {
                    keyPart.set(new Uint8Array(macKey), keyPart.byteLength - 12);
                    self.keyPart = keyPart.buffer;
                    return self;
                });
            },
            /**
             * Encode container entry
             * 
             * @memberOf GostKeys.ViPNetContainerEntry
             * @instance
             * @param {string} format The encoded data format
             * @returns {CryptoOperationData}
             */
            encode: function (format)
            {
                var header = asn1.ViPNetInfo.method('encode').call(this),
                        result = new Uint8Array(8 + header.byteLength + this.keyPart.byteLength);
                set32(result.buffer, 0, 4 + header.byteLength + this.keyPart.byteLength);
                result.set(new Uint8Array(header), 4);
                set32(result.buffer, 4 + header.byteLength, this.keyPart.byteLength);
                result.set(new Uint8Array(this.keyPart), 8 + header.byteLength);
                if (format === 'PEM')
                    return coding.Base64.encode(result.buffer);
                return result.buffer;
            }
        };
    })(), {
        /**
         * Decode container entry
         * 
         * @memberOf GostKeys.ViPNetContainerEntry
         * @param {FormatedData} entry
         * @returns {GostKeys.ViPNetContainer}
         */
        decode: function (entry)
        {
            if (typeof entry === 'string')
                entry = coding.Base64.decode(entry);
            entry = buffer(entry);
            // Entry size 
            var entrySize = get32(entry, 0);
            if (entry.byteLength !== entrySize + 4)
                throw new Error('Invalid container entry size');
            // Decode header info
            var source = coding.BER.decode(new Uint8Array(entry, 4, entrySize));
            var result = asn1.ViPNetInfo.decode.call(this, source);
            // Decode key info
            var headerSize = source.header.byteLength + source.content.byteLength,
                    keyPartSize = get32(entry, 4 + headerSize);
            if (entry.byteLength !== headerSize + keyPartSize + 8)
                throw new Error('Invalid container key part size');
            result.keyPart = new Uint8Array(new Uint8Array(entry, headerSize + 8, keyPartSize)).buffer;
            // Key Info buffer - can be used in case error of format encoding
            // var keyInfoSource = source.object[1];
            // result.encodedKeyInfo = new Uint8Array(new Uint8Array(keyInfoSource.header.buffer, 
            //    keyInfoSource.header.byteOffset, keyInfoSource.header.byteLength + keyInfoSource.content.byteLength)).buffer;
            return result;
        }
    });

    /**
     * A class for password-encrypted private keys in CryptoPro container
     * 
     * @memberOf GostKeys
     * @type GostKeys.SignalComPrivateKeyInfo
     */
    GostKeys.prototype.ViPNetContainerEntry = ViPNetContainerEntry;

    /**
     * A class for password-encrypted private keys in ViPNet container
     * 
     * @class GostKeys.ViPNetContainer
     * @param {(FormatedData|GostKeys.ViPNetContainer)} container 
     */
    function ViPNetContainer(container)
    {
        if (container && (container instanceof CryptoOperationData ||
                container.buffer instanceof CryptoOperationData ||
                typeof container === 'string'))
            this.decode(container);
        else {
            container = container || {};
            this.fileType = container.fileType || 'ITCS';
            this.fileVersion = container.fileVersion || 0x10;
            if (container.applicationHeader)
                this.applicationHeader = container.applicationHeader;
            this.entries = container.entries || [];
        }
    }


    extend(Object, ViPNetContainer, {
        /**
         * Get the certificate from the container
         * 
         * @memberOf GostKeys.ViPNetContainer
         * @instance
         * @param {number} index Index of the entriy. Default 0
         * @returns {Promise} Promise to return {@link GostCert.X509} 
         */
        getCertificate: function (index)
        {
            var self = __webpack_require__.g;
            return new Promise(call).then(function () {
                var entry = self.entries[index || 0];
                if (!entry)
                    throw new Error('Entry not defined');
                if (entry.certificate)
                    return new cert.X509(entry.certificate);
            });
        },
        /**
         * Get the private key info
         * 
         * @memberOf GostKeys.ViPNetContainer
         * @instance
         * @param {string} keyPassword The password for decryption 
         * @param {number} index Index of the entriy. Default 0
         * @returns {Promise} Promise to return {@link GostKeys.PKCS8}
         */
        getKey: function (keyPassword, index)
        {
            return this.getPrivateKey(keyPassword, index).then(function (privateKey) {
                return new PKCS8().setPrivateKey(privateKey);
            });
        },
        /**
         * Get the private key
         * 
         * @memberOf GostKeys.ViPNetContainer
         * @instance
         * @param {string} keyPassword The password of secrect key for decryption 
         * @param {number} index Index of the entriy. Default 0
         * @returns {Promise} Promise to return the {@link Key}
         */
        getPrivateKey: function (keyPassword, index)
        {
            var self = __webpack_require__.g;
            return new Promise(call).then(function () {
                var entry = self.entries[index || 0];
                if (!entry)
                    throw new Error('Entry not defined');
                return entry.getPrivateKey(keyPassword);
            });
        },
        /**
         * Set the certificate to the container
         * 
         * @memberOf GostKeys.ViPNetContainer
         * @instance
         * @param {(FormatedData|GostCert.X509)} certificate The certificate
         * @param {number} index Index of the entriy. Default 0
         * @returns {Promise} Promise to return self object after set certificate
         */
        setCertificate: function (certificate, index)
        {
            var self = this, entry, certificate;
            return new Promise(call).then(function () {
                entry = self.entries[index || 0] ||
                        (self.entries[index || 0] = new ViPNetContainerEntry());
                certificate = new cert.X509(certificate);
                if (entry.publicKey)
                    return certificate.getPublicKey();
            }).then(function (publicKey) {
                if (publicKey && !equalBuffers(entry.publicKey, publicKey.buffer))
                    throw new Error('Invalid certificate for private key');
                entry.certificate = certificate;
                return self;
            });
        },
        /**
         * Set the key to the container
         * 
         * @memberOf GostKeys.ViPNetContainer
         * @instance
         * @param {(FormatedData|GostKeys.PKCS8)} keyInfo The key
         * @param {string} keyPassword The password for decryption 
         * @param {number} index Index of the entriy. Default 0
         * @param {number} days Validity days. Default 7305 days (20 years)
         * @returns {Promise} Promise to return self object after set the key
         */
        setKey: function (keyInfo, keyPassword, index, days)
        {
            var self = __webpack_require__.g;
            return new PKCS8(keyInfo).getPrivateKey().then(function (privateKey) {
                return self.setPrivateKey(privateKey, keyPassword, index, days);
            });
        },
        /**
         * Set the private key
         * 
         * @memberOf GostKeys.ViPNetContainerEntry
         * @instance
         * @param {Key} privateKey The private key
         * @param {string} keyPassword The secret key encryption 
         * @param {number} index Index of the entriy. Default 0
         * @param {number} days Validity days. Default 7305 days (20 years)
         * @returns {Promise} Promise to return the self object after set the key
         */
        setPrivateKey: function (privateKey, keyPassword, index, days)
        {
            var self = __webpack_require__.g;
            return new Promise(call).then(function () {
                var entry = self.entries[index || 0] ||
                        (self.entries[index || 0] = new ViPNetContainerEntry());
                return entry.setPrivateKey(privateKey, keyPassword, days);
            }).then(function () {
                return self;
            });
        },
        /**
         * Change key password
         * 
         * @memberOf GostKeys.ViPNetContainerEntry
         * @instance
         * @param {string} oldKeyPassword Old key password
         * @param {string} newKeyPassword New key password
         * @returns {Promise} Promise to return self object after change password
         */
        changePassword: function (oldKeyPassword, newKeyPassword)
        {
            var self = __webpack_require__.g;
            return new Promise(call).then(function () {
                return self.getPrivateKey(oldKeyPassword).then(function (privateKey) {
                    return self.setPrivateKey(privateKey, newKeyPassword);
                });
            });
        },
        /**
         * Generate private key, certificate and return certification request
         * 
         * @memberOf GostKeys.ViPNetContainerEntry
         * @instance
         * @param {(FormatedData|GostASN1.CertificationRequest)} req The request templates
         * @param {(Key|CryptoOperationData|string)} keyPassword The secret key or password for decryption 
         * @param {(AlgorithmIdentifier|string)} keyAlgorithm The name of provider or algorithm
         * @returns {Promise} Promise to return {@link GostCert.Request}
         */
        generate: function (req, keyPassword, keyAlgorithm)
        {
            var self = this, certificate, keyInfo;
            return new Promise(call).then(function () {
                if (!(req instanceof cert.Request))
                    req = new cert.Request(req);
                // Generate request
                return req.generate(keyAlgorithm);
            }).then(function (key) {
                keyInfo = key;
                return self.setKey(keyInfo, keyPassword);
            }).then(function () {
                // Create the new certificate
                certificate = new cert.X509(req);
                return certificate.sign(keyInfo);
            }).then(function () {
                return self.setCertificate(certificate);
            }).then(function () {
                return req;
            });
        },
        /**
         * Encode objet to container
         * 
         * @memberOf GostKeys.ViPNetContainer
         * @instance
         * @param {string} format The encoded data format
         * @returns {CryptoOperationData}
         */
        encode: function (format)
        {
            // Encode entries
            var entries = [], entriesSize = 0;
            this.entries.forEach(function (entry) {
                var encoded = entry.encode();
                entriesSize += encoded.byteLength;
                entries.push(encoded);
            });
            var headerSize = this.applicationHeader ? this.applicationHeader.byteLength : 0,
                    result = new Uint8Array(12 + headerSize + entriesSize);
            result.set(new Uint8Array(coding.Chars.decode(this.fileType, 'ascii')));
            set32(result.buffer, 4, this.fileVersion);
            set32(result.buffer, 8, headerSize);
            if (headerSize > 0)
                result.set(new Uint8Array(this.applicationHeader), 12);
            var offset = 12 + headerSize;
            entries.forEach(function (entry) {
                result.set(new Uint8Array(entry), offset);
                offset += entry.byteLength;
            });
            if (format === 'PEM')
                return coding.Base64.encode(result.buffer);
            return result.buffer;
        },
        /**
         * Decode container to the object
         * 
         * @memberOf GostKeys.ViPNetContainer
         * @instance
         * @param {FormatedData} container
         * @returns {GostKeys.ViPNetContainer}
         */
        decode: function (container)
        {
            container = this.constructor.decode(container);
            this.fileType = container.fileType;
            this.fileVersion = container.fileVersion;
            if (container.applicationHeader)
                this.applicationHeader = container.applicationHeader;
            this.entries = container.entries;
        }
    }, {
        /**
         * Encode object
         * 
         * @memberOf GostKeys.ViPNetContainer
         * @instance
         * @param {GostKeys.ViPNetContainer} object
         * @param {string} format The encoded data format
         * @returns {CryptoOperationData}
         */
        encode: function (object, format)
        {
            return new this(object).encode(format);
        },
        /**
         * Decode container
         * 
         * @memberOf GostKeys.ViPNetContainer
         * @instance
         * @param {FormatedData} container
         * @returns {GostKeys.ViPNetContainer}
         */
        decode: function (container)
        {
            if (typeof container === 'string')
                container = coding.Base64.decode(container);
            container = buffer(container);
            // File type
            var fileType = coding.Chars.encode(new Uint8Array(container, 0, 4), 'ascii');
            if (fileType !== 'ITCS' && fileType !== 'PKEY' && fileType !== '_CCK' && fileType !== '_LCK')
                throw new Error('Unsupported ViPNet container type');
            // File version
            var fileVersion = get32(container, 4),
                    i = fileVersion >>> 16, j = fileVersion & 0xffff;
            if ((i !== 0 && i !== 1) || j > 0xff)
                throw new Error('Unsupported ViPNet container version');
            // File header
            var headerSize = get32(container, 8), applicationHeader;
            if (headerSize > 0)
                applicationHeader = buffer(new Uint8Array(container, 12, headerSize));
            // Read entries
            var offset = 12 + headerSize, entries = [];
            while (offset < container.byteLength) {
                // Entry size
                var entrySize = get32(container, offset);
                // Decode entry
                entries.push(ViPNetContainerEntry.decode(
                        new Uint8Array(container, offset, entrySize + 4)));
                offset = offset + entrySize + 4;
            }
            return new ViPNetContainer({
                fileType: fileType,
                fileVersion: fileVersion,
                applicationHeader: applicationHeader,
                entries: entries
            });
        }
    });

    /**
     * A class for password-encrypted private keys in CryptoPro container
     * 
     * @memberOf GostKeys
     * @type GostKeys.SignalComPrivateKeyInfo
     */
    GostKeys.prototype.ViPNetContainer = ViPNetContainer;

    /**
     * An implementation of PKCS #12 password encryption/integrity modes. Both input and output are implemented.<br><br>
     * 
     * A PFX object may contain multiple authenticated safes (represented as GostASN1.SafeContents objects). 
     * Each authenticated safe may have its own encryption method, and contains a number of bags 
     * (represented as instances of GostASN1.SafeBag). <br>
     * Note: the methods and constructors that input a PFX object do not automatically check the validity of the MAC. 
     * You need to explicitly call verify() to make this check.
     * 
     * @class GostKeys.PKCS12
     * @extends GostASN1.PFX
     * @param {(FormatedData|GostASN1.PFX)} store
     */
    function PKCS12(store)
    {
        asn1.PFX.call(this, store || {
            version: 3,
            authSafe: {
                contentType: 'data'
            }
        });
    }

    extend(asn1.PFX, PKCS12, (function () {


        function calcHMAC(derivation, password, content) {
            var hmac = {name: 'HMAC', hash: derivation.hash};
            // Import password for key generation 
            return subtle.importKey('raw', passwordData(derivation, password),
                    derivation, false, ['deriveKey']).then(function (passwordKey) {
                // Generate key from password. 
                return subtle.deriveKey(derivation, passwordKey, hmac, false, ['sign']);
            }).then(function (integrityKey) {
                // Sign MAC 
                return subtle.sign(hmac, integrityKey, content);
            });
        }

        function verifyHMAC(derivation, password, digest, content) {
            return calcHMAC(derivation, password, content).then(function (test) {
                if (!equalBuffers(digest, test))
                    throw new Error('Invalid password, MAC is not verified');
            });
        }

        return {
            /**
             * Sign the enclosed content with given digest algorithm
             * 
             * @memberOf GostKeys.PKCS12
             * @instance
             * @param {string} password The password 
             * @param {(AlgorithmIdentifier|string)} digestAlgorithm Digest algorithm or provider name
             * @returns {Promise} Promise to return self object after enclose content
             */
            sign: function (password, digestAlgorithm)
            {
                var self = __webpack_require__.g;
                return new Promise(call).then(function () {
                    // Calculate mac for password integrity
                    if (password) {
                        // Define digeset algorithm
                        var hash, derivation, digestProvider;
                        if (digestAlgorithm)
                            digestProvider = providers[digestAlgorithm];
                        else
                            digestAlgorithm = providers[options.providerName].digest;
                        if (digestProvider) {
                            hash = digestProvider.digest;
                            derivation = digestProvider.derivation;
                        } else {
                            hash = digestAlgorithm;
                            derivation = {name: 'PFXKDF', hash: hash, iterations: 2000};
                        }
                        // Add salt
                        derivation = expand(derivation, {salt: getSeed(saltSize(hash)), diversifier: 3});
                        // Sign HMAC
                        var content = self.authSafe.content;
                        return calcHMAC(derivation, password, content).then(function (digest) {
                            self.macData = {
                                mac: {
                                    digestAlgorithm: hash,
                                    digest: digest
                                },
                                macSalt: derivation.salt,
                                iterations: derivation.iterations
                            };
                            return self;
                        });
                    } else
                        return self;
                });
            },
            /**
             * Verifies the MAC.
             * 
             * @memberOf GostKeys.PKCS12
             * @instance
             * @param password The password for mac verification
             * @returns {Promise} Promise to return self object after verification
             */
            verify: function (password)
            {
                var self = this, authSafe = self.authSafe, derivation;
                return new Promise(call).then(function () {
                    // Indirectly verification
                    if (authSafe.contentType === 'data') {
                        // Check MAC 
                        if (self.macData) {
                            if (!password)
                                throw new Error('Password must be defined for the MAC verification');
                            derivation = {
                                name: 'PFXKDF',
                                hash: self.macData.mac.digestAlgorithm,
                                salt: self.macData.macSalt,
                                iterations: self.macData.iterations,
                                diversifier: 3
                            };
                            var content = self.authSafe.content, digest = self.macData.mac.digest;
                            // Verify HMAC with PFXKDF (PKCS#12)
                            return verifyHMAC(derivation, password, digest, content)['catch'](function () {
                                // Verify HMAC with PBKDF2 (TC 26, PKCS#5)
                                derivation.name = 'PBKDF2';
                                return verifyHMAC(derivation, password, digest, content);
                            });
                        } // No check with MAC
                    } else
                        throw new Error('Unsupported format');
                }).then(function () {
                    return self;
                });
            }
        };
    })());

    /**
     * An implementation of PKCS #12 password encryption/integrity modes. 
     * 
     * @memberOf GostKeys
     * @type GostKeys.PKCS12
     */
    GostKeys.prototype.PKCS12 = PKCS12;

    /**
     * This type of entry holds a cryptographic PrivateKey, which is optionally stored 
     * in a protected format to prevent unauthorized access. It is also accompanied by 
     * a certificate chain for the corresponding public key.
     * 
     * @class GostKeys.KeyEntry
     * @property {(GostKeys.PKCS8|GostKeys.PKCS8Encrypted)} key The Private Key
     * @property {GostCert.X509[]} certs The X.509 Certificates chain
     * @property {GostCert.CRL[]} crls The X.509 CRLs for certificate chain
     */

    /**
     * This class represents a storage facility for cryptographic keys and certificates.
     * 
     * @class GostKeys.KeyStore
     * @param {Object} entries Object contains aliased {@link KeyEntry} objects
     */
    function KeyStore(entries)
    {
        this.entries = {};
        if (entries)
            for (var name in entries)
                this.setEntry(name, entries[name]);
    }

    extend(Object, KeyStore, {
        /**
         * Lists all the alias names of this keystore.
         * 
         * @memberOf GostKeys.KeyStore
         * @instance
         * @returns {string[]}
         */
        aliases: function ()
        {
            var result = [];
            for (var name in this.entries)
                result.push(name);
            return result;
        },
        /**
         * Checks if the given alias exists in this keystore.
         * 
         * @memberOf GostKeys.KeyStore
         * @instance
         * @param {string} alias The alias name
         * @returns {boolean} True if the alias exists, false otherwise
         */
        containsAlias: function (alias)
        {
            return !!this.entries[alias];
        },
        /**
         * Deletes the entry identified by the given alias from this keystore.
         * 
         * @memberOf GostKeys.KeyStore
         * @instance
         * @param {string} alias The alias name 
         */
        deleteEntry: function (alias)
        {
            delete this.entries[alias];
        },
        /**
         * Saves a keystore Entry under the specified alias.
         * 
         * @memberOf GostKeys.KeyStore
         * @instance
         * @param {string} alias The alias name 
         * @param {GostKeys.KeyEntry} entry The entry
         */
        setEntry: function (alias, entry)
        {
            var r = {};
            // Keys
            if (entry.key) {
                try {
                    r.key = new PKCS8(entry.key, true); // Private key
                } catch (e) {
                    try {
                        r.key = new PKCS8Encrypted(entry.key, true); // Encrypted private key
                    } catch (e1) {
                        if (entry.key instanceof CryptoOperationData)
                            r.key = entry.key; // Secret key
                        else
                            throw new Error('Unknown Key format');
                    }
                }
            }
            // Certs
            if (entry.certs) {
                var certs = entry.certs instanceof Array ? entry.certs : [entry.certs];
                for (var i = 0; i < certs.length; i++) {
                    try {
                        certs[i] = new cert.X509(certs[i]);
                    } catch (e) {
                    }
                }
                r.certs = certs;
            }
            // CRLs
            if (entry.crls) {
                var crls = entry.crls instanceof Array ? entry.crls : [entry.crls];
                for (var i = 0; i < crls.length; i++) {
                    try {
                        crls[i] = new cert.CRL(crls[i]);
                    } catch (e) {
                    }
                }
                r.crls = crls;
            }
            this.entries[alias] = r;
        },
        /**
         * Gets a keystore Entry for the specified alias 
         * 
         * @memberOf GostKeys.KeyStore
         * @instance
         * @param {string} alias The alias name 
         * @returns {GostKeys.KeyEntry} The entry
         */
        getEntry: function (alias)
        {
            return this.entries[alias];
        },
        /**
         * Loads this KeyStore from the given input stream.<br><br>
         * A password may be given to unlock the keystore (e.g. the keystore resides on a hardware token device), 
         * or to check the integrity of the keystore data. If a password is not given for integrity checking, 
         * then integrity checking is not performed.
         * 
         * @memberOf GostKeys.KeyStore
         * @instance
         * @param {(FormatedData|GostKeys.PKSC12)} store The input stream from which the keystore is loaded
         * @param {string} password The password used to check the integrity of the keystore, the password used to unlock the keystore
         * @returns {Promise} Promise to return self object after store loaded
         */
        load: function (store, password)
        {
            var self = __webpack_require__.g;
            return new Promise(call).then(function () {
                // Verify store file
                store = new PKCS12(store);
                return store.verify(password);
            }).then(function () {
                if (store.authSafe.contentType !== 'data')
                    throw new Error('Unsupported PFX format');
                var authSafe = asn1.AuthenticatedSafe.decode(store.authSafe.content).object,
                        promises = [];
                // Decrypt encrypted content
                authSafe.forEach(function (info) {
                    if (info.contentType === 'data')
                        promises.push(new cms.DataContentInfo(info));
                    else if (info.contentType === 'encryptedData')
                        promises.push(new cms.EncryptedDataContentInfo(info).getEnclosed(password));
                    else
                        throw new Error('Unsupported PFX format');
                });
                return Promise.all(promises);
            }).then(function (contents) {
                // Read bags
                var entries = {};
                contents.forEach(function (info) {
                    var bags = asn1.SafeContents.decode(info.content).object;
                    bags.forEach(function (bag) {
                        var keyId = coding.Hex.encode((bag.bagAttributes && bag.bagAttributes.localKeyId)
                                || getSeed(4), true), entry = entries[keyId] || (entries[keyId] = {});
                        switch (bag.bagId) {
                            case 'keyBag':
                                entry.key = new PKCS8(bag.bagValue);
                                break;
                            case 'pkcs8ShroudedKeyBag':
                                entry.key = new PKCS8Encrypted(bag.bagValue);
                                break;
                            case 'secretBag':
                                if (bag.bagValue.secretTypeId === 'secret')
                                    entry.key = bag.bagValue.secretValue;
                                break;
                            case 'certBag':
                                var certs = entry.certs || (entry.certs = []);
                                if (bag.bagValue.certId === 'x509Certificate')
                                    certs.push(new cert.X509(bag.bagValue.certValue));
                                break;
                            case 'crlBag':
                                var crls = entry.crls || (entry.crls = []);
                                if (bag.bagValue.crlId === 'x509CRL')
                                    crls.push(new cert.CRL(bag.bagValue.crlValue));
                                break;
                        }
                        if (bag.bagAttributes && bag.bagAttributes.friendlyName)
                            entry.friendlyName = bag.bagAttributes.friendlyName;
                    });
                });
                // Decrypt keys
                var promises = [];
                for (var name in entries)
                    promises.push((function (entry) {
                        // Try to decrypt private key
                        if (entry.key instanceof PKCS8Encrypted)
                            return entry.key.getKey(password).then(function (key) {
                                // Return entry with decrypted key
                                entry.key = key;
                                return entry;
                            })['catch'](function () {
                                // Return entry with encrypted key
                                return entry;
                            });
                        else
                            return entry;
                    })(entries[name]));
                return Promise.all(promises);
            }).then(function (entries) {
                // Set alias names
                entries.forEach(function (entry) {
                    var friendlyName = entry.friendlyName;
                    if (friendlyName) {
                        delete entry.friendlyName;
                        self.entries[friendlyName] = entry;
                    } else
                        self.entries[generateUUID()] = entry;
                });
                return self;
            });
        },
        /**
         * Stores this keystore to the given output stream, and protects its integrity with the given password.
         * 
         * @memberOf GostKeys.KeyStore
         * @instance
         * @param {string} password The password to generate the keystore integrity check
         * @param {string} digestAlgortihm The digest algorithm or provider name for integrity check
         * @param {string} encryptionAlgortihm The encryption algorithm or provider name for encrypt certificates
         * @returns {Promise} Promise to return {@link GostKeyst.PKCS12} 
         */
        store: function (password, digestAlgortihm, encryptionAlgortihm)
        {
            var self = this, keys = [], contents = [], authSafe = [];
            return new Promise(call).then(function () {
                // Define encryption algorithm
                if (encryptionAlgortihm)
                    encryptionAlgortihm = providers[encryptionAlgortihm] ?
                            providers[encryptionAlgortihm].pbes : encryptionAlgortihm;
                else if (digestAlgortihm)
                    encryptionAlgortihm = providers[digestAlgortihm] ?
                            providers[digestAlgortihm].pbes : providers[options.providerName].pbes;
                else
                    encryptionAlgortihm = providers[options.providerName].pbes;
                // Prepare keys and certs
                var index = 1;
                for (var name in self.entries) {
                    var keyId = new Uint32Array([index]), entry = self.entries[name];
                    if (entry.key) {
                        (function (key, attributes) {
                            if (key instanceof CryptoOperationData)
                                contents.push({
                                    bagId: 'secretBag',
                                    bagValue: {
                                        secretTypeId: 'secret',
                                        secretValue: key,
                                        bagAttributes: attributes
                                    }
                                });
                            else if (key instanceof PKCS8) {
                                if (encryptionAlgortihm && password)
                                    keys.push(new PKCS8Encrypted().setKey(key, password, encryptionAlgortihm).then(function (encryptedKey) {
                                        return {
                                            bagId: 'pkcs8ShroudedKeyBag',
                                            bagValue: encryptedKey,
                                            bagAttributes: attributes
                                        };
                                    }));
                                else
                                    keys.push({
                                        bagId: 'keyBag',
                                        bagValue: key,
                                        bagAttributes: attributes
                                    });
                            } else if (key instanceof PKCS8Encrypted)
                                keys.push({
                                    bagId: 'pkcs8ShroudedKeyBag',
                                    bagValue: key,
                                    bagAttributes: attributes
                                });
                        })(entry.key, {
                            localKeyId: keyId,
                            friendlyName: name
                        });
                    }
                    if (entry.certs) {
                        entry.certs.forEach(function (certificate) {
                            var attributes = {localKeyId: keyId};
                            if (certificate instanceof cert.X509)
                                contents.push({
                                    bagId: 'certBag',
                                    bagValue: {
                                        certId: 'x509Certificate',
                                        certValue: certificate
                                    },
                                    bagAttributes: attributes
                                });
                        });
                    }
                    if (entry.crls) {
                        entry.crls.forEach(function (crl) {
                            var attributes = {localKeyId: keyId};
                            if (crl instanceof cert.CRL)
                                contents.push({
                                    bagId: 'crlBag',
                                    bagValue: {
                                        crlId: 'x509CRL',
                                        crlValue: crl
                                    },
                                    bagAttributes: attributes
                                });
                        });
                    }
                }
                // Encrypt keys
                if (keys.length > 0)
                    return Promise.all(keys);
            }).then(function (bags) {
                if (bags) {
                    var keyContents = asn1.SafeContents.encode(bags);
                    authSafe.push(new cms.DataContentInfo({
                        contentType: 'data',
                        content: keyContents
                    }));
                }

                // Encrypt certificates and crls
                if (contents.length > 0) {
                    contents = asn1.SafeContents.encode(contents);
                    if (encryptionAlgortihm && password)
                        return new cms.EncryptedDataContentInfo().encloseContent(
                                contents, password, encryptionAlgortihm);
                    else
                        return new cms.DataContentInfo().encloseContent(contents);
                }
            }).then(function (contents) {
                authSafe.push(contents);
                // Set enclosed data
                authSafe = new asn1.AuthenticatedSafe(authSafe);
                var store = new PKCS12();
                store.authSafe = {
                    contentType: 'data',
                    content: authSafe.encode()
                };
                // Return new PKCS12 with enclosed authenificated content
                return store.sign(password, digestAlgortihm);
            });
        }
    });

    /**
     * This class represents a storage facility for cryptographic keys and certificates.
     * 
     * @memberOf GostKeys
     * @type GostKeys.KeyStore
     */
    GostKeys.prototype.KeyStore = KeyStore;

    /**
     * Implements the Key and Certificate Store methods
     * 
     * @memberOf gostCrypto
     * @type GostKeys
     */
    gostCrypto.keys = new GostKeys();

module.exports = GostKeys;


/***/ }),

/***/ "./node_modules/node-gost-crypto/lib/gostRandom.js":
/*!*********************************************************!*\
  !*** ./node_modules/node-gost-crypto/lib/gostRandom.js ***!
  \*********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

/** 
 * @file Implementation Web Crypto random generatore for GOST algorithms
 * @version 1.76
 * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *    
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

    /**
     * The gostCrypto provide general purpose cryptographic functionality for
     * GOST standards including a cryptographically strong pseudo-random number 
     * generator seeded with truly random values.
     * 
     * @Class GostRandom
     * 
     */

    var root = __webpack_require__.g;
    var rootCrypto = root.crypto || root.msCrypto;

    var TypeMismatchError = root.TypeMismatchError || Error;
    var QuotaExceededError = root.QuotaExceededError || Error;

    // Initialize mouse and time counters for random generator    
    var randomRing = {
        seed: new Uint8Array(1024),
        getIndex: 0,
        setIndex: 0,
        set: function (x) {
            if (this.setIndex >= 1024)
                this.setIndex = 0;
            this.seed[this.setIndex++] = x;
        },
        get: function () {
            if (this.getIndex >= 1024)
                this.getIndex = 0;
            return this.seed[this.getIndex++];
        }
    };

    function GostRandom() {
    }

    /**
     * The getRandomValues method generates cryptographically random values. <br><br>
     * 
     * Random generator based on JavaScript Web Crypto random genereator 
     * (if it is possible) or  Math.random mixed with time and parameters of 
     * mouse and keyboard events
     * 
     * @memberOf GostRandom
     * @param {(ArrayBuffer|ArrayBufferView)} array Destination buffer for random data
     */
    GostRandom.prototype.getRandomValues = function (array)
    {

        if (!array.byteLength)
            throw new TypeMismatchError('Array is not of an integer type (Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, or Uint32Array)');

        if (array.byteLength > 65536)
            throw new QuotaExceededError('Byte length of array can\'t be greate then 65536');

        var u8 = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
        if (rootCrypto && rootCrypto.getRandomValues) {
            // Native window cryptographic interface
            rootCrypto.getRandomValues(u8);
        } else {
            // Standard Javascript method
            for (var i = 0, n = u8.length; i < n; i++)
                u8[i] = Math.floor(256 * Math.random()) & 255;
        }

        // Mix bio randomizator
        for (var i = 0, n = u8.length; i < n; i++)
            u8[i] = u8[i] ^ randomRing.get();
        return array;
    };

module.exports = GostRandom;



/***/ }),

/***/ "./node_modules/node-gost-crypto/lib/gostSecurity.js":
/*!***********************************************************!*\
  !*** ./node_modules/node-gost-crypto/lib/gostSecurity.js ***!
  \***********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

/**
 * @file GOST and common ASN.1 Object and Algorithm Identifiers 
 * @version 1.76
 * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *    
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

const gostCrypto = __webpack_require__(/*! ./gostCrypto */ "./node_modules/node-gost-crypto/lib/gostCrypto.js");

    var root = __webpack_require__.g;

    // Expand javascript object
    function expand() {
        var r = {};
        for (var i = 0, n = arguments.length; i < n; i++) {
            var item = arguments[i];
            if (typeof item === 'object')
                for (var name in item)
                    r[name] = item[name];
        }
        return r;
    }


    /**
     * Freandly names for ASN.1 Object Identifiers
     * 
     * @field names
     * @memberOf GostSecurity
     */
    var names = {
        // CryptoPro algoritms
        '1.2.643.2.2': 'CryptoPro',
        '1.2.643.2.2.3': 'id-GostR3411-94-with-GostR3410-2001',
        '1.2.643.2.2.4': 'id-GostR3411-94-with-GostR3410-94',
        '1.2.643.2.2.9': 'id-GostR3411-94',
        '1.2.643.2.2.10': 'id-HMACGostR3411-94',
        '1.2.643.2.2.13.0': 'id-Gost28147-89-None-KeyWrap',
        '1.2.643.2.2.13.1': 'id-Gost28147-89-CryptoPro-KeyWrap',
        '1.2.643.2.2.14.0': 'id-Gost28147-89-None-KeyMeshing',
        '1.2.643.2.2.14.1': 'id-Gost28147-89-CryptoPro-KeyMeshing',
        '1.2.643.2.2.19': 'id-GostR3410-2001',
        '1.2.643.2.2.20': 'id-GostR3410-94',
        '1.2.643.2.2.20.1': 'id-GostR3410-94-a',
        '1.2.643.2.2.20.2': 'id-GostR3410-94-aBis',
        '1.2.643.2.2.20.3': 'id-GostR3410-94-b',
        '1.2.643.2.2.20.4': 'id-GostR3410-94-bBis',
        '1.2.643.2.2.21': 'id-Gost28147-89',
        '1.2.643.2.2.22': 'id-Gost28147-89-MAC',
        '1.2.643.2.2.30.0': 'id-GostR3411-94-TestParamSet',
        '1.2.643.2.2.30.1': 'id-GostR3411-94-CryptoProParamSet',
        '1.2.643.2.2.30.2': 'id-GostR3411-94-CryptoPro-B-ParamSet',
        '1.2.643.2.2.30.3': 'id-GostR3411-94-CryptoPro-C-ParamSet',
        '1.2.643.2.2.30.4': 'id-GostR3411-94-CryptoPro-D-ParamSet',
        '1.2.643.2.2.31.0': 'id-Gost28147-89-TestParamSet',
        '1.2.643.2.2.31.1': 'id-Gost28147-89-CryptoPro-A-ParamSet',
        '1.2.643.2.2.31.2': 'id-Gost28147-89-CryptoPro-B-ParamSet',
        '1.2.643.2.2.31.3': 'id-Gost28147-89-CryptoPro-C-ParamSet',
        '1.2.643.2.2.31.4': 'id-Gost28147-89-CryptoPro-D-ParamSet',
        '1.2.643.2.2.31.5': 'id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet',
        '1.2.643.2.2.31.6': 'id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet',
        '1.2.643.2.2.31.7': 'id-Gost28147-89-CryptoPro-RIC-1-ParamSet ',
        '1.2.643.2.2.31.12': 'id-Gost28147-89-CryptoPro-tc26-1',
        '1.2.643.2.2.31.13': 'id-Gost28147-89-CryptoPro-tc26-2',
        '1.2.643.2.2.31.14': 'id-Gost28147-89-CryptoPro-tc26-3',
        '1.2.643.2.2.31.15': 'id-Gost28147-89-CryptoPro-tc26-4',
        '1.2.643.2.2.31.16': 'id-Gost28147-89-CryptoPro-tc26-5',
        '1.2.643.2.2.31.17': 'id-Gost28147-89-CryptoPro-tc26-6',
        '1.2.643.2.2.32.0': 'id-GostR3410-94-TestParamSet',
        '1.2.643.2.2.32.2': 'id-GostR3410-94-CryptoPro-A-ParamSet',
        '1.2.643.2.2.32.3': 'id-GostR3410-94-CryptoPro-B-ParamSet',
        '1.2.643.2.2.32.4': 'id-GostR3410-94-CryptoPro-C-ParamSet',
        '1.2.643.2.2.32.5': 'id-GostR3410-94-CryptoPro-D-ParamSet',
        '1.2.643.2.2.33.1': 'id-GostR3410-94-CryptoPro-XchA-ParamSet',
        '1.2.643.2.2.33.2': 'id-GostR3410-94-CryptoPro-XchB-ParamSet',
        '1.2.643.2.2.33.3': 'id-GostR3410-94-CryptoPro-XchC-ParamSet',
        // Certificate center attributes
        '1.2.643.2.2.34.2': 'temporaryAccessToRC',
        '1.2.643.2.2.34.3': 'internetContentSignature',
        '1.2.643.2.2.34.4': 'adminRC',
        '1.2.643.2.2.34.5': 'operatorRC',
        '1.2.643.2.2.34.6': 'userRC',
        '1.2.643.2.2.34.7': 'clientRC',
        '1.2.643.2.2.34.8': 'serverRC',
        '1.2.643.2.2.34.9': 'sysAdminRC',
        '1.2.643.2.2.34.10': 'arcAdminRC',
        '1.2.643.2.2.34.11': 'authorityPersonRC',
        '1.2.643.2.2.34.12': 'clientCC',
        '1.2.643.2.2.34.13': 'sysAdminCC',
        '1.2.643.2.2.34.14': 'arcAdminCC',
        '1.2.643.2.2.34.15': 'accessIPSecCA',
        '1.2.643.2.2.34.16': 'auditAdminHSM',
        '1.2.643.2.2.34.21': 'adminHSM',
        '1.2.643.2.2.34.22': 'serverAdminHSH',
        '1.2.643.2.2.34.24': 'winlogonCA',
        '1.2.643.2.2.34.25': 'timestampServiceUser',
        '1.2.643.2.2.34.26': 'statusServiceUser',
        '1.2.643.2.2.34.27': 'arcAdminHSM',
        '1.2.643.2.2.34.28': 'auditorHSM',
        // CryptoPro algoritms
        '1.2.643.2.2.35.0': 'id-GostR3410-2001-CryptoPro-TestParamSet',
        '1.2.643.2.2.35.1': 'id-GostR3410-2001-CryptoPro-A-ParamSet',
        '1.2.643.2.2.35.2': 'id-GostR3410-2001-CryptoPro-B-ParamSet',
        '1.2.643.2.2.35.3': 'id-GostR3410-2001-CryptoPro-C-ParamSet',
        '1.2.643.2.2.36.0': 'id-GostR3410-2001-CryptoPro-XchA-ParamSet',
        '1.2.643.2.2.36.1': 'id-GostR3410-2001-CryptoPro-XchB-ParamSet',
        "1.2.643.2.2.37.1": 'id-CryptoPro-GostPrivateKeys-V1',
        "1.2.643.2.2.37.2": 'id-CryptoPro-GostPrivateKeys-V2',
        "1.2.643.2.2.37.2.1": 'id-CryptoPro-GostPrivateKeys-V2-Full',
        "1.2.643.2.2.37.2.2": 'id-CryptoPro-GostPrivateKeys-V2-PartOf',
        '1.2.643.2.2.37.3.1': 'intermediateCertificates',
        '1.2.643.2.2.37.3.2': 'trustedCertificatesSignature',
        '1.2.643.2.2.37.3.3': 'trustedCertificatesExchange',
        '1.2.643.2.2.37.3.10': 'keyValidity',
        '1.2.643.2.2.38.1': 'personalBaseProlicy',
        '1.2.643.2.2.38.2': 'networkBasePolicy',
        '1.2.643.2.2.47.1': 'id-CryptoPro-ocsp-treats-exp-key-or-exp-cert-rev',
        '1.2.643.2.2.47.2': 'id-CryptoPro-ocsp-crl-locator',
        '1.2.643.2.2.47.3': 'id-CryptoPro-ocsp-instant-revocation-indicator',
        '1.2.643.2.2.47.4': 'id-CryptoPro-ocsp-revocation-announcement-reference',
        '1.2.643.2.2.47.5': 'id-CryptoPro-ocsp-historical-request',
        '1.2.643.2.2.49.2': 'limitedLicense',
        '1.2.643.2.2.96': 'id-GostR3410-2001-CryptoPro-ESDH',
        '1.2.643.2.2.97': 'id-GostR3410-94-CryptoPro-ESDH',
        '1.2.643.2.2.98': 'id-GostR3410-2001DH',
        '1.2.643.2.2.99': 'id-GostR3410-94DH',
        // signature attributes
        '1.2.643.2.45.1.1.1': 'signatureComment',
        '1.2.643.2.45.1.1.2': 'resourceName',
        '1.2.643.2.45.1.1.3': 'signatureUsage',
        // params
        '1.2.643.3.131.1.1': 'INN',
        '1.2.643.3.141.1.1': 'RNS FSS',
        '1.2.643.3.141.1.2': 'KP FSS',
        // tc26
        '1.2.643.7.1': 'tc26',
        '1.2.643.7.1.1.1.1': 'id-tc26-gost3410-12-256',
        '1.2.643.7.1.1.1.2': 'id-tc26-gost3410-12-512',
        '1.2.643.7.1.1.2.1': 'id-tc26-gost3411-94',
        '1.2.643.7.1.1.2.2': 'id-tc26-gost3411-12-256',
        '1.2.643.7.1.1.2.3': 'id-tc26-gost3411-12-512',
        '1.2.643.7.1.1.3.1': 'id-tc26-signwithdigest-gost3410-12-94',
        '1.2.643.7.1.1.3.2': 'id-tc26-signwithdigest-gost3410-12-256',
        '1.2.643.7.1.1.3.3': 'id-tc26-signwithdigest-gost3410-12-512',
        '1.2.643.7.1.1.4.1': 'id-tc26-hmac-gost-3411-12-256',
        '1.2.643.7.1.1.4.2': 'id-tc26-hmac-gost-3411-12-512',
        '1.2.643.7.1.1.6.1': 'id-tc26-agreement-gost-3410-12-256',
        '1.2.643.7.1.1.6.2': 'id-tc26-agreement-gost-3410-12-512',
        '1.2.643.7.1.2.1.1.0': 'id-tc26-gost-3410-12-256-paramSetTest',
        '1.2.643.7.1.2.1.1.1': 'id-tc26-gost-3410-12-256-paramSetA',
        '1.2.643.7.1.2.1.1.2': 'id-tc26-gost-3410-12-256-paramSetB',
        '1.2.643.7.1.2.1.2.0': 'id-tc26-gost-3410-12-512-paramSetTest',
        '1.2.643.7.1.2.1.2.1': 'id-tc26-gost-3410-12-512-paramSetA',
        '1.2.643.7.1.2.1.2.2': 'id-tc26-gost-3410-12-512-paramSetB',
        '1.2.643.7.1.2.1.2.3': 'id-tc26-gost-3410-12-512-paramSetC',
        '1.2.643.7.1.2.1.2.4': 'id-tc26-gost-3410-12-512-paramSetD',
        '1.2.643.7.1.2.5.1.1': 'id-tc26-gost-28147-param-Z',
        // GOST Parameters
        '1.2.643.100.1': 'OGRN',
        '1.2.643.100.2.1': 'SMEV-person',
        '1.2.643.100.2.2': 'SMEV-government',
        '1.2.643.100.3': 'SNILS',
        '1.2.643.100.4': 'KPP',
        '1.2.643.100.5': 'OGRNIP',
        '1.2.643.100.6': 'internal-government',
        '1.2.643.100.111': 'subjectSignTool',
        '1.2.643.100.112': 'issuerSignTool',
        '1.2.643.100.113.1': 'signToolClassKC1',
        '1.2.643.100.113.2': 'signToolClassKC2',
        '1.2.643.100.113.3': 'signToolClassKC3',
        '1.2.643.100.113.4': 'signToolClassKB1',
        '1.2.643.100.113.5': 'signToolClassKB2',
        '1.2.643.100.113.6': 'signToolClassKA1',
        '1.2.643.100.114.1': 'issuerToolClassKC1',
        '1.2.643.100.114.2': 'issuerToolClassKC2',
        '1.2.643.100.114.3': 'issuerToolClassKC3',
        '1.2.643.100.114.4': 'issuerToolClassKB2',
        '1.2.643.100.114.5': 'issuerToolClassKB1',
        '1.2.643.100.114.6': 'issuerToolClassKA1',
        // Common algorithms
        '1.2.840.10040.4': 'x9cm',
        '1.2.840.10040.4.1': 'dsa',
        '1.2.840.10040.4.3': 'dsa-with-SHA1',
        '1.2.840.10045': 'ansi-x962',
        '1.2.840.10045.1': 'id-fieldType',
        '1.2.840.10045.1.1': 'id-prime-Field',
        '1.2.840.10045.1.2': 'id-characteristic-two-field',
        '1.2.840.10045.2.1': 'ecPublicKey',
        '1.2.840.10045.3.0': 'characteristicTwo',
        '1.2.840.10045.3.1.1': 'secp192r1',
        '1.2.840.10045.3.1.2': 'prime192v2',
        '1.2.840.10045.3.1.3': 'prime192v3',
        '1.2.840.10045.3.1.4': 'prime239v1',
        '1.2.840.10045.3.1.5': 'prime239v2',
        '1.2.840.10045.3.1.6': 'prime239v3',
        '1.2.840.10045.3.1.7': 'secp256r1',
        '1.2.840.10045.4': 'ecdsa',
        '1.2.840.10045.4.1': 'ecdsa-with-SHA1',
        '1.2.840.10045.4.2': 'ecdsa-with-Recommended',
        '1.2.840.10045.4.4': 'ecdsa-with-SHA2',
        '1.2.840.10045.4.4.1': 'ecdsa-with-SHA224',
        '1.2.840.10045.4.4.2': 'ecdsa-with-SHA256',
        '1.2.840.10045.4.4.3': 'ecdsa-with-SHA384',
        '1.2.840.10045.4.4.4': 'ecdsa-with-SHA512',
        '1.2.840.113533.7.66.13': 'PasswordBasedMac',
        '1.3.6.1.4.1.22554.1.1.2.1.2': 'pbeWithSHAAndAES128-CBC',
        '1.3.6.1.4.1.22554.1.1.2.1.22': 'pbeWithSHAAndAES192-CBC',
        '1.3.6.1.4.1.22554.1.1.2.1.42': 'pbeWithSHAAndAES256-CBC',
        '1.3.6.1.4.1.22554.1.2.1.2.1.2': 'pbeWithSHA256AndAES128-CBC',
        '1.3.6.1.4.1.22554.1.2.1.2.1.22': 'pbeWithSHA256AndAES192-CBC',
        '1.3.6.1.4.1.22554.1.2.1.2.1.42': 'pbeWithSHA256AndAES256-CBC',
        //  Diffie-Hellman Key Exchange Keys
        '1.2.840.113549': 'rsa',
        '1.2.840.113549.1.1.1': 'rsaEncryption',
        '1.2.840.113549.1.1.2': 'md2withRSAEncryption',
        '1.2.840.113549.1.1.3': 'md4withRSAEncryption',
        '1.2.840.113549.1.1.4': 'md5withRSAEncryption',
        '1.2.840.113549.1.1.5': 'sha1withRSAEncryption',
        '1.2.840.113549.1.1.7': 'rsaes-oaep',
        '1.2.840.113549.1.1.8': 'mgf1',
        '1.2.840.113549.1.1.9': 'pSpecified',
        '1.2.840.113549.1.1.10': 'rsassa-pss',
        '1.2.840.113549.1.1.11': 'sha256withRSAEncryption',
        '1.2.840.113549.1.1.12': 'sha384withRSAEncryption',
        '1.2.840.113549.1.1.13': 'sha512withRSAEncryption',
        '1.2.840.113549.1.2.7': 'hmacWithSHA1',
        '1.2.840.113549.1.2.8': 'hmacWithSHA224',
        '1.2.840.113549.1.2.9': 'hmacWithSHA256',
        '1.2.840.113549.1.2.10': 'hmacWithSHA384',
        '1.2.840.113549.1.2.11': 'hmacWithSHA512',
        '1.2.840.113549.1.3.1': 'dhKeyAgreement',
        // pkcs#7 content types
        '1.2.840.113549.1.5.12': 'PBKDF2',
        '1.2.840.113549.1.5.13': 'PBES2',
        '1.2.840.113549.1.5.14': 'PBMAC1',
        '1.2.840.113549.1.7.1': 'data',
        '1.2.840.113549.1.7.2': 'signedData',
        '1.2.840.113549.1.7.3': 'envelopedData',
        '1.2.840.113549.1.7.4': 'signedAndEnvelopedData',
        '1.2.840.113549.1.7.5': 'digestedData',
        '1.2.840.113549.1.7.6': 'encryptedData',
        '1.2.840.113549.1.9.1': 'emailAddress',
        '1.2.840.113549.1.9.2': 'unstructuredName',
        '1.2.840.113549.1.9.3': 'contentType',
        '1.2.840.113549.1.9.4': 'messageDigest',
        '1.2.840.113549.1.9.5': 'signingTime',
        '1.2.840.113549.1.9.6': 'countersignature',
        '1.2.840.113549.1.9.7': 'challengePassword',
        '1.2.840.113549.1.9.8': 'unstructuredAddress',
        '1.2.840.113549.1.9.9': 'extendedCertificateAttributes',
        '1.2.840.113549.1.9.10': 'issuerAndSerialNumber',
        '1.2.840.113549.1.9.11': 'passwordCheck',
        '1.2.840.113549.1.9.12': 'publicKey',
        '1.2.840.113549.1.9.13': 'signingDescription',
        '1.2.840.113549.1.9.14': 'extensionRequest',
        '1.2.840.113549.1.9.15': 'sMimeCapabilities',
        '1.2.840.113549.1.9.16': 'sMimeObjectIdentifierRegistry',
        '1.2.840.113549.1.9.16.1.2': 'authData',
        '1.2.840.113549.1.9.16.1.4 ': 'timestampToken',
        '1.2.840.113549.1.9.16.1.17 ': 'firmwareLoadReceipt',
        '1.2.840.113549.1.9.16.1.21': 'encKeyWithID',
        '1.2.840.113549.1.9.16.1.23': 'authEnvelopedData',
        '1.2.840.113549.1.9.16.2': 'sMimeAttributes',
        '1.2.840.113549.1.9.16.2.1': 'receiptRequest',
        '1.2.840.113549.1.9.16.2.12': 'signingCertificate',
        '1.2.840.113549.1.9.16.2.14': 'timeStampToken',
        '1.2.840.113549.1.9.16.2.2': 'securityLabel',
        '1.2.840.113549.1.9.16.2.3': 'mlExpansionHistory',
        '1.2.840.113549.1.9.16.2.34': 'unsignedData',
        '1.2.840.113549.1.9.16.2.47': 'signingCertificateV2',
        '1.2.840.113549.1.9.16.3.5': 'ESDH',
        // pkcs#9 oids
        '1.2.840.113549.1.9.20': 'friendlyName',
        '1.2.840.113549.1.9.21': 'localKeyId',
        '1.2.840.113549.1.9.22': 'certTypes',
        '1.2.840.113549.1.9.22.1': 'x509Certificate',
        '1.2.840.113549.1.9.22.2': 'sdsiCertificate',
        '1.2.840.113549.1.9.23': 'crlTypes',
        '1.2.840.113549.1.9.23.1': 'x509CRL',
        '1.2.840.113549.1.9.24': 'secretTypes',
        '1.2.840.113549.1.9.24.1': 'secret',
        '1.2.840.113549.1.9.25.1': 'pkcs15Token',
        '1.2.840.113549.1.9.25.2': 'encryptedPrivateKeyInfo',
        '1.2.840.113549.1.9.25.3': 'randomNonce',
        '1.2.840.113549.1.9.25.4': 'sequenceNumber',
        '1.2.840.113549.1.9.25.5': 'pkcs7PDU',
        '1.2.840.113549.1.9.26.1': 'pkcs9String',
        '1.2.840.113549.1.9.26.2': 'signingTimeString',
        '1.2.840.113549.1.9.27.1': 'caseIgnoreMatch',
        '1.2.840.113549.1.9.27.2': 'signingTimeMatch',
        // password-based-encryption for pkcs#12
        '1.2.840.113549.1.12.0.1': 'pkcs-12',
        '1.2.840.113549.1.12.1': 'pbe',
        '1.2.840.113549.1.12.1.1': 'pbeWithSHAAnd128BitRC4',
        '1.2.840.113549.1.12.1.2': 'pbeWithSHAAnd40BitRC4',
        '1.2.840.113549.1.12.1.3': 'pbeWithSHAAnd3-KeyTripleDES-CBC',
        '1.2.840.113549.1.12.1.4': 'pbeWithSHAAnd2-KeyTripleDES-CBC',
        '1.2.840.113549.1.12.1.5': 'pbeWithSHAAnd128BitRC2-CBC',
        '1.2.840.113549.1.12.1.6': 'pbeWithSHAAnd40BitRC2-CBC',
        '1.2.840.113549.1.12.1.80': 'pbeUnknownGost',
        '1.2.840.113549.1.12.2.1': 'pkcs8-key-shrouding',
        '1.2.840.113549.1.12.3.1': 'keyBagId',
        '1.2.840.113549.1.12.3.2': 'certAndCRLBagId',
        '1.2.840.113549.1.12.3.3': 'secretBagId',
        '1.2.840.113549.1.12.3.4': 'safeContentsId',
        '1.2.840.113549.1.12.3.5': 'pkcs-8ShroudedKeyBagId',
        '1.2.840.113549.1.12.4.1': 'x509CertCRLBagId',
        '1.2.840.113549.1.12.4.2': 'pkcs-12-SDSICertBag',
        // pkcs#12 safe bags
        '1.2.840.113549.1.12.10.1.1': 'keyBag',
        '1.2.840.113549.1.12.10.1.2': 'pkcs8ShroudedKeyBag',
        '1.2.840.113549.1.12.10.1.3': 'certBag',
        '1.2.840.113549.1.12.10.1.4': 'crlBag',
        '1.2.840.113549.1.12.10.1.5': 'secretBag',
        '1.2.840.113549.1.12.10.1.6': 'safeContentsBag',
        // hash algorithm
        '1.2.840.113549.2.5': 'md-5',
        // symmetric key algorithm oids
        '1.2.840.113549.3.7': 'des-EDE3-CBC',
        // additional algorithms
        '1.3.132.0.34': 'secp384r1',
        '1.3.132.0.35': 'secp521r1',
        '1.3.132.112': 'ecDH',
        '1.3.14.3.2.26': 'sha1',
        '1.3.6.1.4.1.311.2.1.14': 'msCertExtensions',
        '1.3.6.1.4.1.311.17.1': 'keyProviderNameAttr',
        '1.3.6.1.4.1.311.17.2': 'localMachineKeyset',
        '1.3.6.1.4.1.311.17.3.20': 'certKeyIdentifierPropId',
        // SignalCom algorithms
        '1.3.6.1.4.1.5849': 'SignalCom',
        '1.3.6.1.4.1.5849.1.1.1': 'id-sc-gost28147-ecb',
        '1.3.6.1.4.1.5849.1.1.2': 'id-sc-gost28147-gamma',
        '1.3.6.1.4.1.5849.1.1.3': 'id-sc-gost28147-gfb',
        '1.3.6.1.4.1.5849.1.1.4': 'id-sc-gost28147-mac',
        '1.3.6.1.4.1.5849.1.1.5': 'id-sc-gostR3410-94',
        '1.3.6.1.4.1.5849.1.1.6.1.1.1': 'id-sc-gostR3410-94-default',
        '1.3.6.1.4.1.5849.1.1.6.1.1.2': 'id-sc-gostR3410-94-test',
        '1.3.6.1.4.1.5849.1.2.1': 'id-sc-gostR3411-94',
        '1.3.6.1.4.1.5849.1.3.1': 'id-sc-gostR3411-94-with-gostR3410-94',
        '1.3.6.1.4.1.5849.1.3.2': 'id-sc-gostR3411-94-with-gostR3410-2001',
        '1.3.6.1.4.1.5849.1.4.1': 'id-sc-cmsGostWrap',
        '1.3.6.1.4.1.5849.1.4.2': 'id-sc-cmsGost28147Wrap',
        '1.3.6.1.4.1.5849.1.5.1': 'id-sc-pbeWithGost3411AndGost28147',
        '1.3.6.1.4.1.5849.1.5.2': 'id-sc-pbeWithGost3411AndGost28147CFB',
        '1.3.6.1.4.1.5849.1.6.2': 'id-sc-gostR3410-2001',
        '1.3.6.1.4.1.5849.1.7.2': 'id-sc-hmacWithGostR3411',
        '1.3.6.1.4.1.5849.1.8.1': 'id-sc-r3410-ESDH-r3411kdf',
        '1.3.6.1.4.1.5849.1.8.3': 'id-sc-ecdh-singlePass-cofactor-r3411kdf',
        '1.3.6.1.4.1.5849.2.2.1': 'id-sc-gostR3410-2001-publicKey',
        // additinal data
        '1.3.6.1.5.5.7.0.12': 'attribute-cert',
        '1.3.6.1.5.5.7.1.1': 'authorityInfoAccess',
        '1.3.6.1.5.5.7.1.4': 'auditIdentity',
        '1.3.6.1.5.5.7.1.6': 'aaControls',
        '1.3.6.1.5.5.7.1.10': 'ac-proxying',
        '1.3.6.1.5.5.7.1.11': 'subjectInfoAccess',
        '1.3.6.1.5.5.7.3.1': 'serverAuth',
        '1.3.6.1.5.5.7.3.2': 'clientAuth',
        '1.3.6.1.5.5.7.3.3': 'codeSigning',
        '1.3.6.1.5.5.7.3.4': 'emailProtection',
        '1.3.6.1.5.5.7.3.5': 'ipsecEndSystem',
        '1.3.6.1.5.5.7.3.6': 'ipsecTunnel',
        '1.3.6.1.5.5.7.3.7': 'ipsecUser',
        '1.3.6.1.5.5.7.3.8': 'timeStamping',
        '1.3.6.1.5.5.7.3.9': 'OCSPSigning',
        '1.3.6.1.5.5.7.5.1': 'regCtrl',
        '1.3.6.1.5.5.7.5.1.1': 'regToken',
        '1.3.6.1.5.5.7.5.1.2': 'authenticator',
        '1.3.6.1.5.5.7.5.1.3': 'pkiPublicationInfo',
        '1.3.6.1.5.5.7.5.1.4': 'pkiArchiveOptions',
        '1.3.6.1.5.5.7.5.1.5': 'oldCertID',
        '1.3.6.1.5.5.7.5.1.6': 'protocolEncrKey',
        '1.3.6.1.5.5.7.5.2': 'regInfoAttr',
        '1.3.6.1.5.5.7.5.2.1': 'UTF8Pairs',
        '1.3.6.1.5.5.7.5.2.2': 'certReq',
        '1.3.6.1.5.5.7.6.2': 'noSignature',
        '1.3.6.1.5.5.7.7.1': 'statusInfo',
        '1.3.6.1.5.5.7.7.2': 'identification',
        '1.3.6.1.5.5.7.7.3': 'identityProof',
        '1.3.6.1.5.5.7.7.4': 'dataReturn',
        '1.3.6.1.5.5.7.7.5': 'transactionId',
        '1.3.6.1.5.5.7.7.6': 'senderNonce',
        '1.3.6.1.5.5.7.7.7': 'recipientNonce',
        '1.3.6.1.5.5.7.7.8': 'addExtensions',
        '1.3.6.1.5.5.7.7.9': 'encryptedPOP',
        '1.3.6.1.5.5.7.7.10': 'decryptedPOP',
        '1.3.6.1.5.5.7.7.11': 'lraPOPWitness',
        '1.3.6.1.5.5.7.7.15': 'getCert',
        '1.3.6.1.5.5.7.7.16': 'getCRL',
        '1.3.6.1.5.5.7.7.17': 'revokeRequest',
        '1.3.6.1.5.5.7.7.18': 'regInfo',
        '1.3.6.1.5.5.7.7.19': 'responseInfo',
        '1.3.6.1.5.5.7.7.21': 'queryPending',
        '1.3.6.1.5.5.7.7.22': 'popLinkRandom',
        '1.3.6.1.5.5.7.7.23': 'popLinkWitness',
        '1.3.6.1.5.5.7.7.24': 'confirmCertAcceptance',
        '1.3.6.1.5.5.7.7.25': 'statusInfoV2',
        '1.3.6.1.5.5.7.7.26': 'trustedAnchors',
        '1.3.6.1.5.5.7.7.27': 'authPublish',
        '1.3.6.1.5.5.7.7.28': 'batchRequests',
        '1.3.6.1.5.5.7.7.29': 'batchResponses',
        '1.3.6.1.5.5.7.7.30': 'publishCert',
        '1.3.6.1.5.5.7.7.31': 'modCertTemplate',
        '1.3.6.1.5.5.7.7.32': 'controlProcessed',
        '1.3.6.1.5.5.7.7.33': 'popLinkWitnessV2',
        '1.3.6.1.5.5.7.7.34': 'identityProofV2',
        '1.3.6.1.5.5.7.9.1': 'dateOfBirth',
        '1.3.6.1.5.5.7.9.2': 'placeOfBirth',
        '1.3.6.1.5.5.7.9.3': 'gender',
        '1.3.6.1.5.5.7.9.4': 'countryOfCitizenship',
        '1.3.6.1.5.5.7.9.5': 'countryOfResidence',
        '1.3.6.1.5.5.7.10.1': 'authenticationInfo',
        '1.3.6.1.5.5.7.10.2': 'accessIdentity',
        '1.3.6.1.5.5.7.10.3': 'chargingIdentity',
        '1.3.6.1.5.5.7.10.4': 'group',
        '1.3.6.1.5.5.7.10.6': 'encAttrs',
        '1.3.6.1.5.5.7.12.2': 'PKIData',
        '1.3.6.1.5.5.7.12.3': 'PKIResponse',
        '1.3.6.1.5.5.7.48.1.1': 'ocsp-basic',
        '1.3.6.1.5.5.7.48.1.2': 'ocsp-nonce',
        '1.3.6.1.5.5.7.48.1.3': 'ocsp-crl',
        '1.3.6.1.5.5.7.48.1.4': 'ocsp-response',
        '1.3.6.1.5.5.7.48.1.5': 'ocsp-nocheck',
        '1.3.6.1.5.5.7.48.1.6': 'ocsp-archive-cutoff',
        '1.3.6.1.5.5.7.48.1.7': 'ocsp-service-locator',
        // Key packages
        '2.16.840.1.101.2.1.2.78.2': 'encryptedKeyPkg',
        '2.16.840.1.101.2.1.2.78.3': 'keyPackageReceipt',
        '2.16.840.1.101.2.1.2.78.5': 'aKeyPackage',
        '2.16.840.1.101.2.1.2.78.6': 'keyPackageError',
        // symmetric key algorithm oids
        '2.16.840.1.101.3.4': 'nistAlgorithms',
        '2.16.840.1.101.3.4.1': 'aes',
        '2.16.840.1.101.3.4.1.1': 'aes128-ECB',
        '2.16.840.1.101.3.4.1.2': 'aes128-CBC',
        '2.16.840.1.101.3.4.1.3': 'aes128-OFB',
        '2.16.840.1.101.3.4.1.4': 'aes128-CFB',
        '2.16.840.1.101.3.4.1.5': 'aes128-wrap',
        '2.16.840.1.101.3.4.1.6': 'aes128-GCM',
        '2.16.840.1.101.3.4.1.7': 'aes128-CCM',
        '2.16.840.1.101.3.4.1.8': 'aes128-wrap-pad',
        '2.16.840.1.101.3.4.1.21': 'aes192-ECB',
        '2.16.840.1.101.3.4.1.22': 'aes192-CBC',
        '2.16.840.1.101.3.4.1.23': 'aes192-OFB',
        '2.16.840.1.101.3.4.1.24': 'aes192-CFB',
        '2.16.840.1.101.3.4.1.25': 'aes192-wrap',
        '2.16.840.1.101.3.4.1.26': 'aes192-GCM',
        '2.16.840.1.101.3.4.1.27': 'aes192-CCM',
        '2.16.840.1.101.3.4.1.28': 'aes192-wrap-pad',
        '2.16.840.1.101.3.4.1.41': 'aes256-ECB',
        '2.16.840.1.101.3.4.1.42': 'aes256-CBC',
        '2.16.840.1.101.3.4.1.43': 'aes256-OFB',
        '2.16.840.1.101.3.4.1.44': 'aes256-CFB',
        '2.16.840.1.101.3.4.1.45': 'aes256-wrap',
        '2.16.840.1.101.3.4.1.46': 'aes256-GCM',
        '2.16.840.1.101.3.4.1.47': 'aes256-CCM',
        '2.16.840.1.101.3.4.1.48': 'aes256-wrap-pad',
        // hash algorihtms
        '2.16.840.1.101.3.4.2.1': 'sha256',
        '2.16.840.1.101.3.4.2.2': 'sha384',
        '2.16.840.1.101.3.4.2.3': 'sha512',
        // pkcs12
        '2.16.840.1.113730.3.1.216': 'userPKCS12',
        // certificate issuer/subject OIDsets
        '2.5.1.5.55': 'clearance',
        '2.5.4.0': 'objectClass',
        '2.5.4.1': 'aliasedEntryName',
        '2.5.4.2': 'knowldgeinformation',
        '2.5.4.3': 'commonName',
        '2.5.4.5': 'serialName',
        '2.5.4.6': 'countryName',
        '2.5.4.7': 'localityName',
        '2.5.4.8': 'stateOrProvinceName',
        '2.5.4.9': 'streetAddress',
        '2.5.4.10': 'organizationName',
        '2.5.4.11': 'organizationalUnitName',
        '2.5.4.12': 'title',
        '2.5.4.13': 'description',
        '2.5.4.14': 'searchGuide',
        '2.5.4.15': 'businessCategory',
        '2.5.4.16': 'postalAddress',
        '2.5.4.17': 'postalCode',
        '2.5.4.18': 'postOfficeBox',
        '2.5.4.19': 'physicalDeliveryOfficeName',
        '2.5.4.20': 'telephoneNumber',
        '2.5.4.21': 'telexNumber',
        '2.5.4.22': 'teletexTerminalIdentifier',
        '2.5.4.23': 'facsimileTelephoneNumber',
        '2.5.4.24': 'x121Address',
        '2.5.4.25': 'internationalISDNNumber',
        '2.5.4.26': 'registeredAddress',
        '2.5.4.27': 'destinationIndicator',
        '2.5.4.28': 'preferredDeliveryMethod',
        '2.5.4.29': 'presentationAddress',
        '2.5.4.30': 'supportedApplicationContext',
        '2.5.4.31': 'member',
        '2.5.4.32': 'owner',
        '2.5.4.33': 'roleOccupant',
        '2.5.4.34': 'seeAlso',
        '2.5.4.35': 'userPassword',
        '2.5.4.36': 'userCertificate',
        '2.5.4.37': 'cACertificate',
        '2.5.4.38': 'authorityRevocationList',
        '2.5.4.39': 'certificateRevocationList',
        '2.5.4.40': 'crossCertificatePair',
        '2.5.4.41': 'name',
        '2.5.4.42': 'givenName',
        '2.5.4.43': 'initials',
        '2.5.4.44': 'generationQualifier',
        '2.5.4.45': 'uniqueIdentifier',
        '2.5.4.46': 'dnQualifier',
        '2.5.4.47': 'enhancedSearchGuide',
        '2.5.4.48': 'protocolInformation',
        '2.5.4.49': 'distinguishedName',
        '2.5.4.50': 'uniqueMember',
        '2.5.4.51': 'houseIdentifier',
        '2.5.4.52': 'supportedAlgorithms',
        '2.5.4.53': 'deltaRevocationList',
        '2.5.4.58': 'attributeCertificate',
        '2.5.4.65': 'pseudonym',
        '2.5.4.72': 'role',
        // X.509 extension OIDsets
        '2.5.29.1': 'authorityKeyIdentifierX',
        '2.5.29.2': 'keyAttributesX',
        '2.5.29.3': 'certificatePoliciesX',
        '2.5.29.4': 'keyUsageRestriction',
        '2.5.29.5': 'policyMapping',
        '2.5.29.6': 'subtreesConstraint',
        '2.5.29.7': 'subjectAltNameX',
        '2.5.29.8': 'issuerAltNameX',
        '2.5.29.9': 'subjectDirectoryAttributes',
        '2.5.29.10': 'basicConstraintsX',
        '2.5.29.11': 'nameConstraintsX',
        '2.5.29.12': 'policyConstraintsX',
        '2.5.29.13': 'basicConstraintsY',
        '2.5.29.14': 'subjectKeyIdentifier',
        '2.5.29.15': 'keyUsage',
        '2.5.29.16': 'privateKeyUsagePeriod',
        '2.5.29.17': 'subjectAltName',
        '2.5.29.18': 'issuerAltName',
        '2.5.29.19': 'basicConstraints',
        '2.5.29.20': 'cRLNumber',
        '2.5.29.21': 'cRLReason',
        '2.5.29.22': 'expirationDate',
        '2.5.29.23': 'instructionCode',
        '2.5.29.24': 'invalidityDate',
        '2.5.29.25': 'cRLDistributionPointsX',
        '2.5.29.26': 'issuingDistributionPointX',
        '2.5.29.27': 'deltaCRLIndicator',
        '2.5.29.28': 'issuingDistributionPoint',
        '2.5.29.29': 'certificateIssuer',
        '2.5.29.30': 'nameConstraints',
        '2.5.29.31': 'cRLDistributionPoints',
        '2.5.29.32': 'certificatePolicies',
        '2.5.29.33': 'policyMappings',
        '2.5.29.34': 'policyConstraintsY',
        '2.5.29.35': 'authorityKeyIdentifier',
        '2.5.29.36': 'policyConstraints',
        '2.5.29.37': 'extKeyUsage',
        '2.5.29.46': 'freshestCRL',
        '2.5.29.54': 'inhibitAnyPolicy',
        '2.5.29.55': 'targetInformation',
        '2.5.29.56': 'noRevAvail'
    };

    /**
     * ASN.1 Object Identifiers for friandly names
     * Generated automaticly
     * @field identifiers
     * @memberOf GostSecurity
     */
    var identifiers = {};
    for (var id in names) 
        identifiers[names[id]] = id;
    


    /**
     * Algorithm identifiers {@link gostCrypto.AlgorithmIdentifier} for Object Identifiers
     * 
     * @field algorithms
     * @memberOf GostSecurity
     */
    var algorithms = {
        // CryptoPro algoritms
        'id-GostR3411-94-with-GostR3410-2001': 'GOST R 34.10-2001/GOST R 34.11-94',
        'id-GostR3411-94-with-GostR3410-94': 'GOST R 34.10-94/GOST R 34.11-94',
        'id-GostR3411-94': 'GOST R 34.11-94',
        'id-HMACGostR3411-94': {name: 'HMAC', hash: {name: 'GOST R 34.11-94'}},
        'id-Gost28147-89-None-KeyWrap': 'GOST 28147-89-KW',
        'id-Gost28147-89-CryptoPro-KeyWrap': 'GOST 28147-89-CPKW',
        'id-GostR3410-2001': 'GOST R 34.10-2001',
        'id-GostR3410-94': 'GOST R 34.10-94',
        'id-GostR3410-94-a': 'GOST R 34.10-94',
        'id-GostR3410-94-aBis': 'GOST R 34.10-94',
        'id-GostR3410-94-b': 'GOST R 34.10-94',
        'id-GostR3410-94-bBis': 'GOST R 34.10-94',
        'id-Gost28147-89': 'GOST 28147-89',
        'id-Gost28147-89-MAC': 'GOST 28147-89-MAC',
        'id-GostR3410-2001-CryptoPro-ESDH': 'GOST R 34.10-2001-DH/GOST R 34.11-94',
        'id-GostR3410-94-CryptoPro-ESDH': 'GOST R 34.10-94-DH/GOST R 34.11-94',
        'id-GostR3410-2001DH': 'GOST R 34.10-2001-DH',
        'id-GostR3410-94DH': 'GOST R 34.10-94-DH',
        // TK-26 attributes
        'id-tc26-gost3410-12-256': 'GOST R 34.10-256',
        'id-tc26-gost3410-12-512': 'GOST R 34.10-512',
        'id-tc26-gost3411-94': 'GOST R 34.11-94',
        'id-tc26-gost3411-12-256': 'GOST R 34.11-256',
        'id-tc26-gost3411-12-512': 'GOST R 34.11-512',
        'id-tc26-signwithdigest-gost3410-12-94': 'GOST R 34.10-256/GOST R 34.11-94',
        'id-tc26-signwithdigest-gost3410-12-256': 'GOST R 34.10-256/GOST R 34.11-256',
        'id-tc26-signwithdigest-gost3410-12-512': 'GOST R 34.10-512/GOST R 34.11-512',
        'id-tc26-hmac-gost-3411-12-256': {name: 'HMAC', hash: {name: 'GOST R 34.11-256'}},
        'id-tc26-hmac-gost-3411-12-512': {name: 'HMAC', hash: {name: 'GOST R 34.11-512'}},
        'id-tc26-agreement-gost-3410-12-256': 'GOST R 34.10-256-DH/GOST R 34.11-256',
        'id-tc26-agreement-gost-3410-12-512': 'GOST R 34.10-512-DH/GOST R 34.11-256',
        // SignalCom algorithms
        'id-sc-gost28147-ecb': 'GOST 28147-89-ECB/SC',
        'id-sc-gost28147-gamma': 'GOST 28147-89-CTR/SC',
        'id-sc-gost28147-gfb': 'GOST 28147-89-CFB/SC',
        'id-sc-gost28147-mac': 'GOST 28147-89-MAC/SC',
        'id-sc-gostR3410-94': 'GOST R 34.10-94/SC',
        'id-sc-gostR3410-94-default': 'GOST R 34.10-94/SC',
        'id-sc-gostR3410-94-test': 'GOST R 34.10-94/SC/S-TEST',
        'id-sc-gostR3411-94': 'GOST R 34.11-94/SC',
        'id-sc-gostR3411-94-with-gostR3410-94': 'GOST R 34.10-94/GOST R 34.11-94/SC',
        'id-sc-gostR3411-94-with-gostR3410-2001': 'GOST R 34.10-2001/GOST R 34.11-94/SC',
        'id-sc-cmsGostWrap': 'GOST 28147-89-SCKW/SC',
        'id-sc-cmsGost28147Wrap': 'GOST 28147-89-KW/SC',
        'id-sc-pbeWithGost3411AndGost28147': {derivation: {name: 'GOST R 34.11-94-PBKDF2/SC'}, encryption: {name: 'GOST 28147-ECB/SC'}},
        'id-sc-pbeWithGost3411AndGost28147CFB': {derivation: {name: 'GOST R 34.11-94-PBKDF2/SC'}, encryption: {name: 'GOST 28147-CFB/SC'}},
        'id-sc-gostR3410-2001': 'GOST R 34.10-2001/SC',
        'id-sc-hmacWithGostR3411': {name: 'HMAC', hash: {name: 'GOST R 34.11-94/SC'}},
        'id-sc-r3410-ESDH-r3411kdf': 'GOST R 34.10-2001-DH/GOST R 34.11-94/SC',
        // RSA algorithms
        noSignature: 'NONE',
        rsaEncryption: {name: 'RSASSA-PKCS1-v1_5', hash: {name: 'SHA-256'}},
        sha1withRSAEncryption: {name: 'RSASSA-PKCS1-v1_5', hash: {name: 'SHA-1'}},
        sha256withRSAEncryption: {name: 'RSASSA-PKCS1-v1_5', hash: {name: 'SHA-256'}},
        sha384withRSAEncryption: {name: 'RSASSA-PKCS1-v1_5', hash: {name: 'SHA-384'}},
        sha512withRSAEncryption: {name: 'RSASSA-PKCS1-v1_5', hash: {name: 'SHA-512'}},
        'rsaes-oaep': 'RSA-OAEP',
        'rsassa-pss': 'RSA-PSS',
        // ECDSA
        'ecdsa': 'ECDSA',
        'ecdsa-with-SHA1': {name: 'ECDSA', hash: {name: 'SHA-1'}},
        'ecdsa-with-SHA256': {name: 'ECDSA', hash: {name: 'SHA-256'}},
        'ecdsa-with-SHA384': {name: 'ECDSA', hash: {name: 'SHA-384'}},
        'ecdsa-with-SHA512': {name: 'ECDSA', hash: {name: 'SHA-512'}},
        // Legion of the Bouncy Castle pbe
        'pbeWithSHAAndAES128-CBC': {derivation: {name: 'PBKDF2', hash: {name: 'SHA-1'}}, encryption: {name: 'AES-CBC', length: 128}},
        'pbeWithSHAAndAES192-CBC': {derivation: {name: 'PBKDF2', hash: {name: 'SHA-1'}}, encryption: {name: 'AES-CBC', length: 192}},
        'pbeWithSHAAndAES256-CBC': {derivation: {name: 'PBKDF2', hash: {name: 'SHA-1'}}, encryption: {name: 'AES-CBC', length: 256}},
        'pbeWithSHA256AndAES128-CBC': {derivation: {name: 'PBKDF2', hash: {name: 'SHA-256'}}, encryption: {name: 'AES-CBC', length: 128}},
        'pbeWithSHA256AndAES192-CBC': {derivation: {name: 'PBKDF2', hash: {name: 'SHA-256'}}, encryption: {name: 'AES-CBC', length: 192}},
        'pbeWithSHA256AndAES256-CBC': {derivation: {name: 'PBKDF2', hash: {name: 'SHA-256'}}, encryption: {name: 'AES-CBC', length: 256}},
        // PKCS12 PBE
        'pbeWithSHAAnd3-KeyTripleDES-CBC': {derivation: {name: 'PFXKDF', iterations: 2000, hash: 'SHA-1'}, encryption: {name: '3DES', block: 'CBC'}},
        'pbeWithSHAAnd2-KeyTripleDES-CBC': {derivation: {name: 'PFXKDF', iterations: 2000, hash: 'SHA-1'}, encryption: {name: '2DES', block: 'CBC'}},
        'pbeWithSHAAnd128BitRC2-CBC': {derivation: {name: 'PFXKDF', iterations: 2000, hash: 'SHA-1'}, encryption: {name: 'RC2', block: 'CBC', length: 128}},
        'pbeWithSHAAnd40BitRC2-CBC': {derivation: {name: 'PFXKDF', iterations: 2000, hash: 'SHA-1'}, encryption: {name: 'RC2', block: 'CBC', length: 40}},
        'pbeUnknownGost': {derivation: {name: 'PFXKDF', iterations: 2000, hash: 'GOST R 34.11-94'}, encryption: {name: 'GOST 28147-89-CFB'}},
        //  Diffie-Hellman Key Exchange Keys
        ecDH: 'ECDH',
        dhKeyAgreement: 'DH',
        // symmetric key algorithm oids
        'aes128-CBC': {name: 'AES-CBC', length: 128},
        'aes128-CFB': {name: 'AES-CFB-8', length: 128},
        'aes128-GCM': {name: 'AES-GCM', length: 128},
        'aes128-wrap': {name: 'AES-KW', length: 128},
        'aes192-CBC': {name: 'AES-CBC', length: 192},
        'aes192-CFB': {name: 'AES-CFB-8', length: 192},
        'aes192-GCM': {name: 'AES-GCM', length: 192},
        'aes192-wrap': {name: 'AES-KW', length: 192},
        'aes256-CBC': {name: 'AES-CBC', length: 256},
        'aes256-CFB': {name: 'AES-CFB-8', length: 256},
        'aes256-GCM': {name: 'AES-GCM', length: 256},
        'aes256-wrap': {name: 'AES-KW', length: 256},
        // hash algorihtms
        sha1: 'SHA-1',
        sha256: 'SHA-256',
        sha384: 'SHA-384',
        sha512: 'SHA-512',
        // PBE
        PBKDF2: 'PBKDF2',
        PBES2: {derivation: {name: 'PBKDF2'}, encryption: {}},
        PBMAC1: {derivation: {name: 'PBKDF2'}, hmac: {}},
        // HMAC
        hmacWithSHA1: 'SHA-1-HMAC',
        hmacWithSHA256: {name: 'HMAC', hash: {name: 'SHA-256'}},
        hmacWithSHA384: {name: 'HMAC', hash: {name: 'SHA-384'}},
        hmacWithSHA512: {name: 'HMAC', hash: {name: 'SHA-512'}}
    };

    // Each algorithm must has id for convertions
    for (var id in algorithms) {
        var algorithm = algorithms[id];
        if (typeof algorithm === 'string') {
            algorithm = {name: algorithm};
        }
        algorithm.id = id;
        algorithms[id] = algorithm;
    }

    /**
     * Algorithm parameters
     * 
     * @field parameters
     * @memberOf GostSecurity
     */
    var parameters = {
        'id-GostR3410-94-TestParamSet': {namedParam: 'S-TEST'},
        'id-GostR3410-94-CryptoPro-A-ParamSet': {namedParam: 'S-A'},
        'id-GostR3410-94-CryptoPro-B-ParamSet': {namedParam: 'S-B'},
        'id-GostR3410-94-CryptoPro-C-ParamSet': {namedParam: 'S-C'},
        'id-GostR3410-94-CryptoPro-D-ParamSet': {namedParam: 'S-D'},
        'id-GostR3410-94-CryptoPro-XchA-ParamSet': {namedParam: 'X-A'},
        'id-GostR3410-94-CryptoPro-XchB-ParamSet': {namedParam: 'X-B'},
        'id-GostR3410-94-CryptoPro-XchC-ParamSet': {namedParam: 'X-C'},
        // CryptoPro named curves
        'id-GostR3410-2001-CryptoPro-TestParamSet': {namedCurve: 'S-256-TEST'},
        'id-GostR3410-2001-CryptoPro-A-ParamSet': {namedCurve: 'S-256-A'},
        'id-GostR3410-2001-CryptoPro-B-ParamSet': {namedCurve: 'S-256-B'},
        'id-GostR3410-2001-CryptoPro-C-ParamSet': {namedCurve: 'S-256-C'},
        'id-GostR3410-2001-CryptoPro-XchA-ParamSet': {namedCurve: 'X-256-A'},
        'id-GostR3410-2001-CryptoPro-XchB-ParamSet': {namedCurve: 'X-256-B'},
        // TC-26 named curves
        'id-tc26-gost-3410-12-256-paramSetTest': {namedCurve: 'T-256-TEST'},
        'id-tc26-gost-3410-12-256-paramSetA': {namedCurve: 'T-256-A'},
        'id-tc26-gost-3410-12-256-paramSetB': {namedCurve: 'T-256-B'},
        'id-tc26-gost-3410-12-512-paramSetTest': {namedCurve: 'T-512-TEST'},
        'id-tc26-gost-3410-12-512-paramSetA': {namedCurve: 'T-512-A'},
        'id-tc26-gost-3410-12-512-paramSetB': {namedCurve: 'T-512-B'},
        'id-tc26-gost-3410-12-512-paramSetC': {namedCurve: 'T-512-C'},
        'id-tc26-gost-3410-12-512-paramSetD': {namedCurve: 'T-512-D'},
        // Curve attributes additional algorithms
        secp256r1: {namedCurve: 'P-256'},
        secp384r: {namedCurve: 'P-384'},
        secp521r: {namedCurve: 'P-521'},
        // CryptoPro encryption parameters
        'id-GostR3411-94-TestParamSet': {sBox: 'D-TEST'},
        'id-GostR3411-94-CryptoProParamSet': {sBox: 'D-A'},
        'id-GostR3411-94-CryptoPro-A-ParamSet': {sBox: 'D-B'},
        'id-GostR3411-94-CryptoPro-B-ParamSet': {sBox: 'D-C'},
        'id-GostR3411-94-CryptoPro-C-ParamSet': {sBox: 'D-D'},
        'id-Gost28147-89-TestParamSet': {block: 'CTR', sBox: 'E-TEST'},
        'id-Gost28147-89-CryptoPro-A-ParamSet': {block: 'CFB', sBox: 'E-A', keyMeshing: 'CP'},
        'id-Gost28147-89-CryptoPro-B-ParamSet': {block: 'CFB', sBox: 'E-B', keyMeshing: 'CP'},
        'id-Gost28147-89-CryptoPro-C-ParamSet': {block: 'CFB', sBox: 'E-C', keyMeshing: 'CP'},
        'id-Gost28147-89-CryptoPro-D-ParamSet': {block: 'CFB', sBox: 'E-D', keyMeshing: 'CP'},
        'id-Gost28147-89-None-KeyMeshing': {keyMeshing: 'NO'},
        'id-Gost28147-89-CryptoPro-KeyMeshing': {keyMeshing: 'CP'},
        // TC-26 encryption parameters
        'id-tc26-gost-28147-param-Z': {block: 'CFB', sBox: 'E-Z'}
    };

    /**
     * Named attributes for Algorithm identifiers {@link AlgorithmIdentifier}<br><br> 
     * 
     * Recognized attributes:
     *  <ul>
     *      <li>sBox - Paramsets for GOST 28147. Supported values:
     *          <ul>
     *              <li>D-TEST - id-GostR3411-94-TestParamSet</li>
     *              <li>D-A - id-GostR3411-94-CryptoProParamSet</li>
     *              <li>D-B - id-GostR3411-94-CryptoPro-A-ParamSet</li>
     *              <li>D-C - id-GostR3411-94-CryptoPro-B-ParamSet</li>
     *              <li>D-D - id-GostR3411-94-CryptoPro-C-ParamSet</li>
     *              <li>E-TEST - id-Gost28147-89-TestParamSet</li>
     *              <li>E-A - id-Gost28147-89-CryptoPro-A-ParamSet</li>
     *              <li>E-B - id-Gost28147-89-CryptoPro-B-ParamSet</li>
     *              <li>E-C - id-Gost28147-89-CryptoPro-C-ParamSet</li>
     *              <li>E-D - id-Gost28147-89-CryptoPro-D-ParamSet</li>
     *              <li>E-Z - id-tc26-gost-28147-param-Z</li>
     *              <li>D-256 - id-tc26-gost3411-12-256</li>
     *              <li>D-512 - id-tc26-gost3411-12-512</li>
     *          </ul>
     *      </li>
     *      <li>namedParam - Paramset for GOST R 34.10-94
     *          <ul>
     *              <li>S-TEST - id-GostR3410-94-TestParamSet</li>
     *              <li>S-A - id-GostR3410-94-CryptoPro-A-ParamSet</li>
     *              <li>S-B - id-GostR3410-94-CryptoPro-B-ParamSet</li>
     *              <li>S-C - id-GostR3410-94-CryptoPro-C-ParamSet</li>
     *              <li>S-D - id-GostR3410-94-CryptoPro-D-ParamSet</li>
     *              <li>X-A - id-GostR3410-94-CryptoPro-XchA-ParamSet</li>
     *              <li>X-B - id-GostR3410-94-CryptoPro-XchB-ParamSet</li>
     *              <li>X-C - id-GostR3410-94-CryptoPro-XchC-ParamSet</li>
     *          </ul>
     *      </li>
     *      <li>namedCurve - Paramset for GOST R 34.10-01 and GOST R 34.10-12
     *          <ul>
     *              <li>S-256-TEST - id-GostR3410-2001-CryptoPro-TestParamSet</li>
     *              <li>S-256-A - id-GostR3410-2001-CryptoPro-A-ParamSet</li>
     *              <li>S-256-B - id-GostR3410-2001-CryptoPro-B-ParamSet</li>
     *              <li>S-256-C - id-GostR3410-2001-CryptoPro-C-ParamSet</li>
     *              <li>X-256-A - id-GostR3410-2001-CryptoPro-XchA-ParamSet</li>
     *              <li>X-256-B - id-GostR3410-2001-CryptoPro-XchB-ParamSet</li>
     *              <li>P-256 - secp256r1</li>
     *              <li>T-256-TEST - id-tc26-gost-3410-12-256-paramSetTest</li>
     *              <li>T-256-A - id-tc26-gost-3410-12-256-paramSetA</li>
     *              <li>T-256-B - id-tc26-gost-3410-12-256-paramSetB</li>
     *              <li>T-512-TEST - id-tc26-gost-3410-12-512-paramSetTest</li>
     *              <li>T-512-A - id-tc26-gost-3410-12-512-paramSetA</li>
     *              <li>T-512-B - id-tc26-gost-3410-12-512-paramSetB</li>
     *          </ul>
     *      </li>
     *  </ul>
     * @field attributes
     * @memberOf GostSecurity
     */
    var attributes = {
        sBox: {
            'D-TEST': 'id-GostR3411-94-TestParamSet',
            'D-A': 'id-GostR3411-94-CryptoProParamSet',
            'D-B': 'id-GostR3411-94-CryptoPro-A-ParamSet',
            'D-C': 'id-GostR3411-94-CryptoPro-B-ParamSet',
            'D-D': 'id-GostR3411-94-CryptoPro-C-ParamSet',
            'E-TEST': 'id-Gost28147-89-TestParamSet',
            'E-A': 'id-Gost28147-89-CryptoPro-A-ParamSet',
            'E-B': 'id-Gost28147-89-CryptoPro-B-ParamSet',
            'E-C': 'id-Gost28147-89-CryptoPro-C-ParamSet',
            'E-D': 'id-Gost28147-89-CryptoPro-D-ParamSet',
            'E-Z': 'id-tc26-gost-28147-param-Z',
            'D-256': 'id-tc26-gost3411-12-256',
            'D-512': 'id-tc26-gost3411-12-512'
        },
        namedParam: {
            'S-TEST': 'id-GostR3410-94-TestParamSet',
            'S-A': 'id-GostR3410-94-CryptoPro-A-ParamSet',
            'S-B': 'id-GostR3410-94-CryptoPro-B-ParamSet',
            'S-C': 'id-GostR3410-94-CryptoPro-C-ParamSet',
            'S-D': 'id-GostR3410-94-CryptoPro-D-ParamSet',
            'X-A': 'id-GostR3410-94-CryptoPro-XchA-ParamSet',
            'X-B': 'id-GostR3410-94-CryptoPro-XchB-ParamSet',
            'X-C': 'id-GostR3410-94-CryptoPro-XchC-ParamSet'
        },
        namedCurve: {
            'S-256-TEST': 'id-GostR3410-2001-CryptoPro-TestParamSet',
            'S-256-A': 'id-GostR3410-2001-CryptoPro-A-ParamSet',
            'S-256-B': 'id-GostR3410-2001-CryptoPro-B-ParamSet',
            'S-256-C': 'id-GostR3410-2001-CryptoPro-C-ParamSet',
            'X-256-A': 'id-GostR3410-2001-CryptoPro-XchA-ParamSet',
            'X-256-B': 'id-GostR3410-2001-CryptoPro-XchB-ParamSet',
            'P-256': 'secp256r1',
            'T-256-TEST': 'id-tc26-gost-3410-12-256-paramSetTest',
            'T-256-A': 'id-tc26-gost-3410-12-256-paramSetA',
            'T-256-B': 'id-tc26-gost-3410-12-256-paramSetB',
            'T-512-TEST': 'id-tc26-gost-3410-12-512-paramSetTest',
            'T-512-A': 'id-tc26-gost-3410-12-512-paramSetA',
            'T-512-B': 'id-tc26-gost-3410-12-512-paramSetB'
        }
    };

    /**
     * Set of algorithms for different providers<br><br>
     * Supported providers:
     *  <ul>
     *      <li><b>CP-94</b> - CryptoPro GOST R 34.10-94 algorithm set</li>
     *      <li><b>CP-01</b> - CryptoPro GOST R 34.10-2001 algorithm set</li>
     *      <li><b>TC-256</b> - Technical Commitee GOST R 34.10-256 algorithm set</li>
     *      <li><b>TC-512</b> - Technical Commitee GOST R 34.10-512 algorithm set</li>
     *      <li><b>SC-94</b> - SignalCom GOST R 34.10-94 algorithm set</li>
     *      <li><b>SC-01</b> - SignalCom GOST R 34.10-2001 algorithm set</li>
     *  </ul>
     *  
     *  Follow set can be used if it's supported your browser native WebCrypto API:
     *  <ul>
     *      <li><b>RSA-2048</b> - RSA Encryption 2048 bits with SHA-256 algorithm set</li>
     *      <li><b>ECDSA-256</b> - ECDSA-256 with SHA-256 algorithm set</li>
     *  </ul>
     *  
     *  Each provider records has follow standart algorithm identifiers:
     *  <ul>
     *      <li><b>signature</b> - Signature algorithm</li>
     *      <li><b>generation</b> - Asymmetric key generation algorithm</li>
     *      <li><b>digest</b> - Digest algorithm</li>
     *      <li><b>wrapping</b> - Key wrapping algorithm</li>
     *      <li><b>hmac</b> - Hash-based message authentication code algorithm</li>
     *      <li><b>agreement</b> - Key agreement algorithm (except RSA schema)</li>
     *      <li><b>encryption</b> - Content encription algorithm</li>
     *      <li><b>derivation</b> - Password-based derivation algorithm</li>
     *      <li><b>pbes</b> - Password-based encryption algorithm</li>
     *      <li><b>pbmac</b> - Password-based message authentication code algorithm</li>
     *  </ul>
     *  
     * @field providers
     * @memberOf GostSecurity
     */
    var providers = {
        'CP-94': {
            title: 'Crypto-Pro GOST R 34.10-94 Cryptographic Service Provider',
            signature: algorithms['id-GostR3411-94-with-GostR3410-94'],
            publicKey: {id: 'id-GostR3410-94', name: 'GOST R 34.10-94', namedParam: 'X-A'},
            privateKey: {id: 'id-GostR3410-94DH', name: 'GOST R 34.10-94-DH', namedParam: 'X-A'},
            digest: algorithms['id-GostR3411-94'],
            wrapping: {id: 'id-Gost28147-89-CryptoPro-KeyWrap', name: 'GOST 28147-89-CPKW', sBox: 'E-A'},
            hmac: algorithms['id-HMACGostR3411-94'],
            agreement: algorithms['id-GostR3410-94-CryptoPro-ESDH'],
            encryption: {id: 'id-Gost28147-89', name: 'GOST 28147-89', block: 'CFB', sBox: 'E-A', keyMeshing: 'CP'},
            derivation: {id: 'PBKDF2', name: 'GOST R 34.11-94-PBKDF2', iterations: 2000}
        },
        'CP-01': {
            title: 'Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider',
            signature: algorithms['id-GostR3411-94-with-GostR3410-2001'],
            publicKey: {id: 'id-GostR3410-2001', name: 'GOST R 34.10-2001', namedCurve: 'X-256-A'},
            privateKey: {id: 'id-GostR3410-2001DH', name: 'GOST R 34.10-2001-DH', namedCurve: 'X-256-A'},
            digest: {id: 'id-GostR3411-94', name: 'GOST R 34.11-94', sBox: 'D-A'},
            wrapping: {id: 'id-Gost28147-89-CryptoPro-KeyWrap', name: 'GOST 28147-89-CPKW', sBox: 'E-A'},
            hmac: algorithms['id-HMACGostR3411-94'],
            agreement: algorithms['id-GostR3410-2001-CryptoPro-ESDH'],
            encryption: {id: 'id-Gost28147-89', name: 'GOST 28147-89-CFB-CPKM', sBox: 'E-A'},
            derivation: {id: 'PBKDF2', name: 'GOST R 34.11-94-PBKDF2', iterations: 2000}
        },
        'TC-256': {
            title: 'Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider',
            signature: algorithms['id-tc26-signwithdigest-gost3410-12-256'],
            publicKey: {id: 'id-tc26-gost3410-12-256', name: 'GOST R 34.10-256', namedCurve: 'X-256-A'},
            privateKey: {id: 'id-tc26-agreement-gost-3410-12-256', name: 'GOST R 34.10-256-DH/GOST R 34.11-256', namedCurve: 'X-256-A'},
            digest: algorithms['id-tc26-gost3411-12-256'],
            wrapping: {id: 'id-Gost28147-89-CryptoPro-KeyWrap', name: 'GOST 28147-89-CPKW', sBox: 'E-A'},
            hmac: algorithms['id-tc26-hmac-gost-3411-12-256'],
            agreement: algorithms['id-tc26-agreement-gost-3410-12-256'],
            encryption: {id: 'id-Gost28147-89', name: 'GOST 28147-89-CFB-CPKM', sBox: 'E-A'},
            derivation: {id: 'PBKDF2', name: 'GOST R 34.11-256-12-PBKDF2', iterations: 2000}
        },
        'TC-512': {
            title: 'Crypto-Pro GOST R 34.10-2012 Strong Cryptographic Service Provider',
            signature: algorithms['id-tc26-signwithdigest-gost3410-12-512'],
            publicKey: {id: 'id-tc26-gost3410-12-512', name: 'GOST R 34.10-512', namedCurve: 'T-512-A'},
            privateKey: {id: 'id-tc26-agreement-gost-3410-12-512', name: 'GOST R 34.10-512-DH/GOST R 34.11-256', namedCurve: 'T-512-A'},
            digest: algorithms['id-tc26-gost3411-12-512'],
            wrapping: {id: 'id-Gost28147-89-CryptoPro-KeyWrap', name: 'GOST 28147-89-CPKW', sBox: 'E-A'},
            hmac: algorithms['id-tc26-hmac-gost-3411-12-512'],
            agreement: algorithms['id-tc26-agreement-gost-3410-12-512'],
            encryption: {id: 'id-Gost28147-89', name: 'GOST 28147-89-CFB-CPKM', sBox: 'E-A'},
            derivation: {id: 'PBKDF2', name: 'GOST R 34.11-256-PBKDF2', iterations: 2000}
        },
        'SC-94': {
            title: 'Signal-COM GOST Cryptographic Provider',
            signature: algorithms['id-sc-gostR3411-94-with-gostR3410-94'],
            publicKey: {id: 'id-sc-gostR3410-94', name: 'GOST R 34.10-94/SC', namedParam: 'S-A'},
            privateKey: {id: 'id-sc-gostR3410-94', name: 'GOST R 34.10-94/SC', modulusLength: 1024, param: {
                p: '0xB4E25EFB018E3C8B87505E2A67553C5EDC56C2914B7E4F89D23F03F03377E70A2903489DD60E78418D3D851EDB5317C4871E40B04228C3B7902963C4B7D85D52B9AA88F2AFDBEB28DA8869D6DF846A1D98924E925561BD69300B9DDD05D247B5922D967CBB02671881C57D10E5EF72D3E6DAD4223DC82AA1F7D0294651A480DF',
                q: '0x972432A437178B30BD96195B773789AB2FFF15594B176DD175B63256EE5AF2CF',
                a: '0x8FD36731237654BBE41F5F1F8453E71CA414FFC22C25D915309E5D2E62A2A26C7111F3FC79568DAFA028042FE1A52A0489805C0DE9A1A469C844C7CABBEE625C3078888C1D85EEA883F1AD5BC4E6776E8E1A0750912DF64F79956499F1E182475B0B60E2632ADCD8CF94E9C54FD1F3B109D81F00BF2AB8CB862ADF7D40B9369A'}},
            digest: algorithms['id-sc-gostR3411-94'],
            encryption: {id: 'id-sc-gost28147-gfb', name: 'GOST 28147-89-CFB/SC'},
            hmac: algorithms['id-sc-hmacWithGostR3411'],
            wrapping: ['id-sc-cmsGostWrap'],
            agreement: algorithms['id-sc-r3410-ESDH-r3411kdf'],
            derivation: {id: 'PBKDF2', name: 'GOST R 34.11-94-PBKDF2/SC', iterations: 2048},
            pbes: {id: 'id-sc-pbeWithGost3411AndGost28147CFB',
                derivation: {id: 'PBKDF2', name: 'GOST R 34.11-94-PBKDF2/SC', iterations: 2048},
                encryption: {id: 'id-sc-gost28147-gfb', name: 'GOST 28147-CFB/SC', iv: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0])}}
        },
        'SC-01': {
            title: 'Signal-COM ECGOST Cryptographic Provider',
            signature: algorithms['id-sc-gostR3411-94-with-gostR3410-2001'],
            publicKey: {id: 'id-sc-gostR3410-2001', name: 'GOST R 34.10-2001/SC', namedCurve: 'P-256'},
            privateKey: {id: 'id-sc-gostR3410-2001', name: 'GOST R 34.10-2001/SC', curve: {
                p: '0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF',
                a: '0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC',
                b: '0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B',
                x: '0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296',
                y: '0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5',
                q: '0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551'}},
            digest: algorithms['id-sc-gostR3411-94'],
            encryption: {id: 'id-sc-gost28147-gfb', name: 'GOST 28147-89-CFB/SC'},
            hmac: algorithms['id-sc-hmacWithGostR3411'],
            wrapping: algorithms['id-sc-cmsGostWrap'],
            agreement: algorithms['id-sc-r3410-ESDH-r3411kdf'],
            derivation: {id: 'PBKDF2', name: 'GOST R 34.11-94-PBKDF2/SC', iterations: 2048},
            pbes: {id: 'id-sc-pbeWithGost3411AndGost28147CFB',
                derivation: {id: 'PBKDF2', name: 'GOST R 34.11-94-PBKDF2/SC', iterations: 2048},
                encryption: {id: 'id-sc-gost28147-gfb', name: 'GOST 28147-CFB/SC', iv: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0])}}
        },
        'RSA-2048': {
            title: 'Microsoft Strong Cryptographic Provider',
            signature: algorithms['sha256withRSAEncryption'],
            publicKey: {id: 'rsaEncryption', name: 'RSASSA-PKCS1-v1_5', modulusLength: 2048,
                publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: algorithms['sha256']},
            privateKey: {id: 'rsaEncryption', name: 'RSASSA-PKCS1-v1_5', modulusLength: 2048,
                publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: algorithms['sha256']},
            digest: algorithms['sha256'],
            encryption: algorithms['aes256-CFB'],
            hmac: algorithms['hmacWithSHA256']
        },
        'ECDSA-256': {
            title: 'Microsoft Base DSS and Diffie-Hellman Cryptographic Provider',
            signature: algorithms['ecdsa-with-SHA256'],
            publicKey: {id: 'ecdsa', name: 'ECDSA', namedCurve: 'P-256'},
            privateKey: {id: 'ecdsa', name: 'ECDSA', namedCurve: 'P-256'},
            digest: algorithms['sha256'],
            encryption: algorithms['aes256-CFB'],
            hmac: algorithms['hmacWithSHA256'],
            agreement: algorithms['ecDH']
        }
    };
    // Russian providers extension
    ['CP-94', 'CP-01', 'TC-256', 'TC-512', 'SC-94', 'SC-01'].forEach(function (name) {
        var provider = providers[name];
        provider.hmac = expand(provider.hmac, {hash: provider.digest});
        provider.derivation = expand(provider.derivation, {hash: provider.digest, hmac: provider.hmac});
        provider.pbes = provider.pbes || {id: 'PBES2', derivation: provider.derivation,
            encryption: provider.encryption};
        provider.pbmac = provider.pbmac || {id: 'PBMAC1', derivation: provider.derivation,
            hmac: provider.hmac};
        provider.agreement = expand(provider.agreement, {wrapping: provider.wrapping});
    });
    // RSA & ECDA providers extension
    ['RSA-2048', 'ECDSA-256'].forEach(function (name) {
        var provider = providers[name];
        provider.derivation = provider.derivation || {id: 'PBKDF2', name: 'PBKDF2',
            iterations: 2048, hash: provider.digest};
        provider.pbes = provider.pbes || {id: 'PBES2',
            derivation: provider.derivation,
            encryption: provider.encryption
        };
        provider.pbmac = provider.pbmac || {id: 'PBMAC1',
            derivation: provider.derivation,
            hmac: provider.hmac
        };
    });
    // Workaround for Chrome error for RSA algorithm when hash for keys is not defined
    // if (root.crypto && root.crypto.subtle)
    //    setTimeout(function () {
    //        root.crypto.subtle.generateKey(providers['RSA-2048'].generation, false, ["sign"])['catch'](function () {
    //            providers['RSA-2048'].generation.hash = providers['RSA-2048'].digest;
    //            algorithms['rsaEncryption'].hash = providers['RSA-2048'].digest;
    //        });
    //    }); 


    /**
     * GOST and common ASN.1 Object and Algorithm Identifiers
     * @class GostSecurity
     */
    function GostSecurity() {
    }

    GostSecurity.prototype = {
        names: names,
        identifiers: identifiers,
        algorithms: algorithms,
        parameters: parameters,
        attributes: attributes,
        providers: providers
    };

    /**
     * GOST and common ASN.1 Object and Algorithm Identifiers  
     * 
     * @memberOf gostCrypto
     * @type GostSecurity
     */
    gostCrypto.security = new GostSecurity();

module.exports = GostSecurity();


/***/ }),

/***/ "./node_modules/node-gost-crypto/lib/gostSign.js":
/*!*******************************************************!*\
  !*** ./node_modules/node-gost-crypto/lib/gostSign.js ***!
  \*******************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

/**
 * @file GOST 34.10-2012 signature function with 1024/512 bits digest
 * @version 1.76
 * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *    
 * Used library JSBN http://www-cs-students.stanford.edu/~tjw/jsbn/
 * Copyright (c) 2003-2005  Tom Wu (tjw@cs.Stanford.EDU)
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

const GostRandom = __webpack_require__(/*! ./gostRandom */ "./node_modules/node-gost-crypto/lib/gostRandom.js");
const GostDigest = __webpack_require__(/*! ./gostDigest */ "./node_modules/node-gost-crypto/lib/gostDigest.js");

    /*
     * Predefined curves and params collection
     * 
     * http://tools.ietf.org/html/rfc5832
     * http://tools.ietf.org/html/rfc7091
     * http://tools.ietf.org/html/rfc4357
     * 
     */

    var root = __webpack_require__.g;
    var rootCrypto = root.crypto || root.msCrypto;
    var CryptoOperationData = root.ArrayBuffer;
    
    var OperationError = root.OperationError || root.Error,
            DataError = root.DataError || root.Error,
            NotSupportedError = root.NotSupportedError || root.Error;

    // Predefined named curve collection
    var ECGostParams = {
        'S-256-TEST': {
            a: 7,
            b: '0x5FBFF498AA938CE739B8E022FBAFEF40563F6E6A3472FC2A514C0CE9DAE23B7E',
            p: '0x8000000000000000000000000000000000000000000000000000000000000431',
            q: '0x8000000000000000000000000000000150FE8A1892976154C59CFC193ACCF5B3',
            x: 2,
            y: '0x8E2A8A0E65147D4BD6316030E16D19C85C97F0A9CA267122B96ABBCEA7E8FC8'
        },
        'S-256-A': {
            a: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94',
            b: 166,
            p: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97',
            q: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893',
            x: 1,
            y: '0x8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14'
        },
        'S-256-B': {
            a: '0x8000000000000000000000000000000000000000000000000000000000000C96',
            b: '0x3E1AF419A269A5F866A7D3C25C3DF80AE979259373FF2B182F49D4CE7E1BBC8B',
            p: '0x8000000000000000000000000000000000000000000000000000000000000C99',
            q: '0x800000000000000000000000000000015F700CFFF1A624E5E497161BCC8A198F',
            x: 1,
            y: '0x3FA8124359F96680B83D1C3EB2C070E5C545C9858D03ECFB744BF8D717717EFC'
        },
        'S-256-C': {
            a: '0x9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D7598',
            b: 32858,
            p: '0x9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D759B',
            q: '0x9B9F605F5A858107AB1EC85E6B41C8AA582CA3511EDDFB74F02F3A6598980BB9',
            x: 0,
            y: '0x41ECE55743711A8C3CBF3783CD08C0EE4D4DC440D4641A8F366E550DFDB3BB67'
        },
        'P-256': {
            p: '0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF',
            a: '0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC',
            b: '0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B',
            x: '0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296',
            y: '0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5',
            q: '0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551'
        },
        'T-512-TEST': {
            a: 7,
            b: '0x1CFF0806A31116DA29D8CFA54E57EB748BC5F377E49400FDD788B649ECA1AC4361834013B2AD7322480A89CA58E0CF74BC9E540C2ADD6897FAD0A3084F302ADC',
            p: '0x4531ACD1FE0023C7550D267B6B2FEE80922B14B2FFB90F04D4EB7C09B5D2D15DF1D852741AF4704A0458047E80E4546D35B8336FAC224DD81664BBF528BE6373',
            q: '0x4531ACD1FE0023C7550D267B6B2FEE80922B14B2FFB90F04D4EB7C09B5D2D15DA82F2D7ECB1DBAC719905C5EECC423F1D86E25EDBE23C595D644AAF187E6E6DF',
            x: '0x24D19CC64572EE30F396BF6EBBFD7A6C5213B3B3D7057CC825F91093A68CD762FD60611262CD838DC6B60AA7EEE804E28BC849977FAC33B4B530F1B120248A9A',
            y: '0x2BB312A43BD2CE6E0D020613C857ACDDCFBF061E91E5F2C3F32447C259F39B2C83AB156D77F1496BF7EB3351E1EE4E43DC1A18B91B24640B6DBB92CB1ADD371E'
        },
        'T-512-A': {
            p: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7',
            a: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4',
            b: '0xE8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760',
            q: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275',
            x: 3,
            y: '0x7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4'
        },
        'T-512-B': {
            p: '0x8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F',
            a: '0x8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C',
            b: '0x687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116',
            q: '0x800000000000000000000000000000000000000000000000000000000000000149A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD',
            x: 2,
            y: '0x1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD'
        }
    };
    ECGostParams['X-256-A'] = ECGostParams['S-256-A'];
    ECGostParams['X-256-B'] = ECGostParams['S-256-C'];
    ECGostParams['T-256-TEST'] = ECGostParams['S-256-TEST'];
    ECGostParams['T-256-A'] = ECGostParams['S-256-A'];
    ECGostParams['T-256-B'] = ECGostParams['S-256-B'];
    ECGostParams['T-256-C'] = ECGostParams['S-256-C'];


    var GostParams = {
        'S-TEST': {
            modulusLength: 512, // bit length of p (512 or 1024 bits)
            p: '0xEE8172AE8996608FB69359B89EB82A69854510E2977A4D63BC97322CE5DC3386EA0A12B343E9190F23177539845839786BB0C345D165976EF2195EC9B1C379E3',
            q: '0x98915E7EC8265EDFCDA31E88F24809DDB064BDC7285DD50D7289F0AC6F49DD2D',
            a: '0x9e96031500c8774a869582d4afde2127afad2538b4b6270a6f7c8837b50d50f206755984a49e509304d648be2ab5aab18ebe2cd46ac3d8495b142aa6ce23e21c'
        },
        'S-A': {
            modulusLength: 1024,
            p: '0xB4E25EFB018E3C8B87505E2A67553C5EDC56C2914B7E4F89D23F03F03377E70A2903489DD60E78418D3D851EDB5317C4871E40B04228C3B7902963C4B7D85D52B9AA88F2AFDBEB28DA8869D6DF846A1D98924E925561BD69300B9DDD05D247B5922D967CBB02671881C57D10E5EF72D3E6DAD4223DC82AA1F7D0294651A480DF',
            q: '0x972432A437178B30BD96195B773789AB2FFF15594B176DD175B63256EE5AF2CF',
            a: '0x8FD36731237654BBE41F5F1F8453E71CA414FFC22C25D915309E5D2E62A2A26C7111F3FC79568DAFA028042FE1A52A0489805C0DE9A1A469C844C7CABBEE625C3078888C1D85EEA883F1AD5BC4E6776E8E1A0750912DF64F79956499F1E182475B0B60E2632ADCD8CF94E9C54FD1F3B109D81F00BF2AB8CB862ADF7D40B9369A'
        },
        'S-B': {
            modulusLength: 1024,
            p: '0xC6971FC57524B30C9018C5E621DE15499736854F56A6F8AEE65A7A404632B1BCF0349FFCAFCB0A103177971FC1612ADCDB8C8CC938C70225C8FD12AFF01B1D064E0AD6FDE6AB9159166CB9F2FC171D92F0CC7B6A6B2CD7FA342ACBE2C9315A42D576B1ECCE77A963157F3D0BD96A8EB0B0F3502AD238101B05116334F1E5B7AB',
            q: '0xB09D634C10899CD7D4C3A7657403E05810B07C61A688BAB2C37F475E308B0607',
            a: '0x3D26B467D94A3FFC9D71BF8DB8934084137264F3C2E9EB16DCA214B8BC7C872485336744934FD2EF5943F9ED0B745B90AA3EC8D70CDC91682478B664A2E1F8FB56CEF2972FEE7EDB084AF746419B854FAD02CC3E3646FF2E1A18DD4BEB3C44F7F2745588029649674546CC9187C207FB8F2CECE8E2293F68395C4704AF04BAB5'
        },
        'S-C': {
            modulusLength: 1024,
            p: '0x9D88E6D7FE3313BD2E745C7CDD2AB9EE4AF3C8899E847DE74A33783EA68BC30588BA1F738C6AAF8AB350531F1854C3837CC3C860FFD7E2E106C3F63B3D8A4C034CE73942A6C3D585B599CF695ED7A3C4A93B2B947B7157BB1A1C043AB41EC8566C6145E938A611906DE0D32E562494569D7E999A0DDA5C879BDD91FE124DF1E9',
            q: '0xFADD197ABD19A1B4653EECF7ECA4D6A22B1F7F893B641F901641FBB555354FAF',
            a: '0x7447ED7156310599070B12609947A5C8C8A8625CF1CF252B407B331F93D639DDD1BA392656DECA992DD035354329A1E95A6E32D6F47882D960B8F10ACAFF796D13CD9611F853DAB6D2623483E46788708493937A1A29442598AEC2E0742022563440FE9C18740ECE6765AC05FAF024A64B026E7E408840819E962E7E5F401AE3'
        },
        'S-D': {
            modulusLength: 1024,
            p: '0x80F102D32B0FD167D069C27A307ADAD2C466091904DBAA55D5B8CC7026F2F7A1919B890CB652C40E054E1E9306735B43D7B279EDDF9102001CD9E1A831FE8A163EED89AB07CF2ABE8242AC9DEDDDBF98D62CDDD1EA4F5F15D3A42A6677BDD293B24260C0F27C0F1D15948614D567B66FA902BAA11A69AE3BCEADBB83E399C9B5',
            q: '0xF0F544C418AAC234F683F033511B65C21651A6078BDA2D69BB9F732867502149',
            a: '0x6BCC0B4FADB3889C1E06ADD23CC09B8AB6ECDEDF73F04632595EE4250005D6AF5F5ADE44CB1E26E6263C672347CFA26F9E9393681E6B759733784CDE5DBD9A14A39369DFD99FA85CC0D10241C4010343F34A91393A706CF12677CBFA1F578D6B6CFBE8A1242CFCC94B3B653A476E145E3862C18CC3FED8257CFEF74CDB205BF1'
        },
        'X-A': {
            modulusLength: 1024,
            p: '0xCA3B3F2EEE9FD46317D49595A9E7518E6C63D8F4EB4D22D10D28AF0B8839F079F8289E603B03530784B9BB5A1E76859E4850C670C7B71C0DF84CA3E0D6C177FE9F78A9D8433230A883CD82A2B2B5C7A3306980278570CDB79BF01074A69C9623348824B0C53791D53C6A78CAB69E1CFB28368611A397F50F541E16DB348DBE5F',
            q: '0xCAE4D85F80C147704B0CA48E85FB00A9057AA4ACC44668E17F1996D7152690D9',
            a: '0xBE27D652F2F1E339DA734211B85B06AE4DE236AA8FBEEB3F1ADCC52CD43853777E834A6A518138678A8ADBD3A55C70A7EAB1BA7A0719548677AAF4E609FFB47F6B9D7E45B0D06D83D7ADC53310ABD85783E7317F7EC73268B6A9C08D260B85D8485696CA39C17B17F044D1E050489036ABD381C5E6BF82BA352A1AFF136601AF'
        },
        'X-B': {
            modulusLength: 1024,
            p: '0x9286DBDA91ECCFC3060AA5598318E2A639F5BA90A4CA656157B2673FB191CD0589EE05F4CEF1BD13508408271458C30851CE7A4EF534742BFB11F4743C8F787B11193BA304C0E6BCA25701BF88AF1CB9B8FD4711D89F88E32B37D95316541BF1E5DBB4989B3DF13659B88C0F97A3C1087B9F2D5317D557DCD4AFC6D0A754E279',
            q: '0xC966E9B3B8B7CDD82FF0F83AF87036C38F42238EC50A876CD390E43D67B6013F',
            a: '0x7E9C3096676F51E3B2F9884CF0AC2156779496F410E049CED7E53D8B7B5B366B1A6008E5196605A55E89C3190DABF80B9F1163C979FCD18328DAE5E9048811B370107BB7715F82091BB9DE0E33EE2FED6255474F8769FCE5EAFAEEF1CB5A32E0D5C6C2F0FC0B3447072947F5B4C387666993A333FC06568E534AD56D2338D729'
        },
        'X-C': {
            modulusLength: 1024,
            p: '0xB194036ACE14139D36D64295AE6C50FC4B7D65D8B340711366CA93F383653908EE637BE428051D86612670AD7B402C09B820FA77D9DA29C8111A8496DA6C261A53ED252E4D8A69A20376E6ADDB3BDCD331749A491A184B8FDA6D84C31CF05F9119B5ED35246EA4562D85928BA1136A8D0E5A7E5C764BA8902029A1336C631A1D',
            q: '0x96120477DF0F3896628E6F4A88D83C93204C210FF262BCCB7DAE450355125259',
            a: '0x3F1817052BAA7598FE3E4F4FC5C5F616E122CFF9EBD89EF81DC7CE8BF56CC64B43586C80F1C4F56DD5718FDD76300BE336784259CA25AADE5A483F64C02A20CF4A10F9C189C433DEFE31D263E6C9764660A731ECCAECB74C8279303731E8CF69205BC73E5A70BDF93E5BB681DAB4EEB9C733CAAB2F673C475E0ECA921D29782E'
        }
    };

    /* 
     * BigInteger arithmetic tools 
     * optimized release of http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js 
     * 
     */

    // Bits per one element
    var DB = 28, DM = (1 << DB) - 1, DV = 1 << DB,
            FV = Math.pow(2, 52), F1 = 52 - DB, F2 = 2 * DB - 52;

    function am(y, i, x, w, j, c, n) {
        var xl = x & 0x3fff, xh = x >> 14;
        while (--n >= 0) {
            var l = y[i] & 0x3fff;
            var h = y[i++] >> 14;
            var m = xh * l + h * xl;
            l = xl * l + ((m & 0x3fff) << 14) + w[j] + c;
            c = (l >> 28) + (m >> 14) + xh * h;
            w[j++] = l & 0xfffffff;
        }
        return c;
    }

    function nbi(words) {
        var r = new Array(Math.ceil(words));
        r.s = 0;
        r.t = 0;
        return r;
    }

    function copyTo(x, r) {
        for (var i = x.t - 1; i >= 0; --i)
            r[i] = x[i];
        r.t = x.t;
        r.s = x.s;
        return r;
    }

    function copy(x) {
        return copyTo(x, nbi(x.t));
    }

    function setInt(x, i) {
        x.t = 1;
        x.s = (i < 0) ? -1 : 0;
        if (i > 0)
            x[0] = i;
        else if (i < -1)
            x[0] = i + DV;
        else
            x.t = 0;
        return x;
    }

    function nbv(i) {
        var r = nbi(1);
        setInt(r, i);
        return r;
    }

    var ZERO = nbv(0), ONE = nbv(1), THREE = nbv(3);

    function clamp(x) {
        var c = x.s & DM;
        while (x.t > 0 && x[x.t - 1] === c)
            --x.t;
        return x;
    }

    function subTo(x, a, r) {
        var i = 0, c = 0, m = Math.min(a.t, x.t);
        while (i < m) {
            c += x[i] - a[i];
            r[i++] = c & DM;
            c >>= DB;
        }
        if (a.t < x.t) {
            c -= a.s;
            while (i < x.t) {
                c += x[i];
                r[i++] = c & DM;
                c >>= DB;
            }
            c += x.s;
        }
        else {
            c += x.s;
            while (i < a.t) {
                c -= a[i];
                r[i++] = c & DM;
                c >>= DB;
            }
            c -= a.s;
        }
        r.s = (c < 0) ? -1 : 0;
        if (c < -1)
            r[i++] = DV + c;
        else if (c > 0)
            r[i++] = c;
        r.t = i;
        return clamp(r);
    }

    function sub(x, y) {
        return subTo(x, y, nbi(x.t));
    }

    function addTo(x, a, r) {
        var i = 0, c = 0, m = Math.min(a.t, x.t);
        while (i < m) {
            c += x[i] + a[i];
            r[i++] = c & DM;
            c >>= DB;
        }
        if (a.t < x.t) {
            c += a.s;
            while (i < x.t) {
                c += x[i];
                r[i++] = c & DM;
                c >>= DB;
            }
            c += x.s;
        }
        else {
            c += x.s;
            while (i < a.t) {
                c += a[i];
                r[i++] = c & DM;
                c = c >> DB;
            }
            c += a.s;
        }
        r.s = (c < 0) ? -1 : 0;
        if (c > 0)
            r[i++] = c;
        else if (c < -1)
            r[i++] = DV + c;
        r.t = i;
        return clamp(r);
    }

    function add(x, y) {
        return addTo(x, y, nbi(x.t));
    }

    function negTo(x, r) {
        return subTo(ZERO, x, r);
    }

    function neg(x) {
        return negTo(x, nbi(x.t));
    }

    function absTo(x, r) {
        return (x.s < 0) ? negTo(r) : copyTo(r);
    }

    function abs(x) {
        return (x.s < 0) ? neg(x) : x;
    }

    function compare(x, a) {
        var r = x.s - a.s;
        if (r !== 0)
            return r;
        var i = x.t;
        r = i - a.t;
        if (r !== 0)
            return (x.s < 0) ? -r : r;
        while (--i >= 0)
            if ((r = x[i] - a[i]) !== 0)
                return r;
        return 0;
    }

    function equals(x, y) {
        return(compare(x, y) === 0);
    }

    function min(x, y) {
        return(compare(x, y) < 0) ? x : y;
    }

    function max(x, y) {
        return(compare(x, y) > 0) ? x : y;
    }

    function nbits(x) {
        var r = 1, t;
        if ((t = x >>> 16) !== 0) {
            x = t;
            r += 16;
        }
        if ((t = x >> 8) !== 0) {
            x = t;
            r += 8;
        }
        if ((t = x >> 4) !== 0) {
            x = t;
            r += 4;
        }
        if ((t = x >> 2) !== 0) {
            x = t;
            r += 2;
        }
        if ((t = x >> 1) !== 0) {
            x = t;
            r += 1;
        }
        return r;
    }

    function dshlTo(x, n, r) {
        var i;
        for (i = x.t - 1; i >= 0; --i)
            r[i + n] = x[i];
        for (i = n - 1; i >= 0; --i)
            r[i] = 0;
        r.t = x.t + n;
        r.s = x.s;
        return r;
    }
    function dshrTo(x, n, r) {
        for (var i = n; i < x.t; ++i)
            r[i - n] = x[i];
        r.t = Math.max(x.t - n, 0);
        r.s = x.s;
        return r;
    }

    function shlTo(x, n, r) {
        var bs = n % DB;
        var cbs = DB - bs;
        var bm = (1 << cbs) - 1;
        var ds = Math.floor(n / DB), c = (x.s << bs) & DM, i;
        for (i = x.t - 1; i >= 0; --i) {
            r[i + ds + 1] = (x[i] >> cbs) | c;
            c = (x[i] & bm) << bs;
        }
        for (i = ds - 1; i >= 0; --i)
            r[i] = 0;
        r[ds] = c;
        r.t = x.t + ds + 1;
        r.s = x.s;
        return clamp(r);
    }

    function shrTo(x, n, r) {
        r.s = x.s;
        var ds = Math.floor(n / DB);
        if (ds >= x.t) {
            r.t = 0;
            return;
        }
        var bs = n % DB;
        var cbs = DB - bs;
        var bm = (1 << bs) - 1;
        r[0] = x[ds] >> bs;
        for (var i = ds + 1; i < x.t; ++i) {
            r[i - ds - 1] |= (x[i] & bm) << cbs;
            r[i - ds] = x[i] >> bs;
        }
        if (bs > 0)
            r[x.t - ds - 1] |= (x.s & bm) << cbs;
        r.t = x.t - ds;
        return clamp(r);
    }

    function shl(x, n) {
        var r = nbi(x.t);
        if (n < 0)
            shrTo(x, -n, r);
        else
            shlTo(x, n, r);
        return r;
    }

    function shr(x, n) {
        var r = nbi(x.t);
        if (n < 0)
            shlTo(x, -n, r);
        else
            shrTo(x, n, r);
        return r;
    }

    function bitLength(x) {
        if (x.t <= 0)
            return 0;
        return DB * (x.t - 1) + nbits(x[x.t - 1] ^ (x.s & DM));
    }

    function mulTo(b, a, r) {
        var x = abs(b), y = abs(a);
        var i = x.t;
        r.t = i + y.t;
        while (--i >= 0)
            r[i] = 0;
        for (i = 0; i < y.t; ++i)
            r[i + x.t] = am(x, 0, y[i], r, i, 0, x.t);
        r.s = 0;
        if (b.s !== a.s)
            subTo(ZERO, r, r);
        return clamp(r);
    }

    function mul(x, y) {
        return mulTo(x, y, nbi(x.t + y.t));
    }

    function sqrTo(a, r) {
        var x = abs(a);
        var i = r.t = 2 * x.t;
        while (--i >= 0)
            r[i] = 0;
        for (i = 0; i < x.t - 1; ++i) {
            var c = am(x, i, x[i], r, 2 * i, 0, 1);
            if ((r[i + x.t] += am(x, i + 1, 2 * x[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV) {
                r[i + x.t] -= x.DV;
                r[i + x.t + 1] = 1;
            }
        }
        if (r.t > 0)
            r[r.t - 1] += am(x, i, x[i], r, 2 * i, 0, 1);
        r.s = 0;
        return clamp(r);
    }

    function sqr(a) {
        return sqrTo(a, nbi(a.t * 2));
    }

    function divRemTo(n, m, q, r) {
        var pm = abs(m);
        if (pm.t <= 0)
            throw new OperationError('Division by zero');
        var pt = abs(n);
        if (pt.t < pm.t) {
            if (q)
                setInt(q, 0);
            if (r)
                copyTo(n, r);
            return q;
        }
        if (!r)
            r = nbi(m.t);
        var y = nbi(m.t), ts = n.s, ms = m.s;
        var nsh = DB - nbits(pm[pm.t - 1]);
        if (nsh > 0) {
            shlTo(pm, nsh, y);
            shlTo(pt, nsh, r);
        }
        else {
            copyTo(pm, y);
            copyTo(pt, r);
        }
        var ys = y.t;
        var y0 = y[ys - 1];
        if (y0 === 0)
            return q;
        var yt = y0 * (1 << F1) + ((ys > 1) ? y[ys - 2] >> F2 : 0);
        var d1 = FV / yt, d2 = (1 << F1) / yt, e = 1 << F2;
        var i = r.t, j = i - ys, t = !q ? nbi(Math.max(n.t - m.t, 1)) : q;
        dshlTo(y, j, t);
        if (compare(r, t) >= 0) {
            r[r.t++] = 1;
            subTo(r, t, r);
        }
        dshlTo(ONE, ys, t);
        subTo(t, y, y);
        while (y.t < ys)
            y[y.t++] = 0;
        while (--j >= 0) {
            var qd = (r[--i] === y0) ? DM : Math.floor(r[i] * d1 + (r[i - 1] + e) * d2);
            if ((r[i] += am(y, 0, qd, r, j, 0, ys)) < qd) {
                dshlTo(y, j, t);
                subTo(r, t, r);
                while (r[i] < --qd)
                    subTo(r, t, r);
            }
        }
        if (q) {
            dshrTo(r, ys, q);
            if (ts !== ms)
                subTo(ZERO, q, q);
        }
        r.t = ys;
        clamp(r);
        if (nsh > 0)
            shrTo(r, nsh, r);
        if (ts < 0)
            subTo(ZERO, r, r);
        return q;
    }

    function modTo(b, a, r) {
        divRemTo(abs(b), a, null, r);
        if (b.s < 0 && compare(r, ZERO) > 0)
            subTo(a, r, r);
        return r;
    }

    function mod(b, a) {
        return modTo(b, a, nbi(a.t));
    }

    function div(b, a) {
        return divRemTo(b, a, nbi(Math.max(b.t - a.t, 1)), null);
    }

    function isEven(x) {

        return ((x.t > 0) ? (x[0] & 1) : x.s) === 0;
    }

    function isZero(x) {
        return equals(x, ZERO);
    }

    function sig(x) {
        if (x.s < 0)
            return -1;
        else if (x.t <= 0 || (x.t === 1 && x[0] <= 0))
            return 0;
        else
            return 1;
    }

    function invMod(x, m) {
        var ac = isEven(m);
        if ((isEven(x) && ac) || sig(m) === 0)
            return ZERO;
        var u = copy(m), v = copy(x);
        var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
        while (sig(u) !== 0) {
            while (isEven(u)) {
                shrTo(u, 1, u);
                if (ac) {
                    if (!isEven(a) || !isEven(b)) {
                        addTo(a, x, a);
                        subTo(b, m, b);
                    }
                    shrTo(a, 1, a);
                }
                else if (!isEven(b))
                    subTo(b, m, b);
                shrTo(b, 1, b);
            }
            while (isEven(v)) {
                shrTo(v, 1, v);
                if (ac) {
                    if (!isEven(c) || !isEven(d)) {
                        addTo(c, x, c);
                        subTo(d, m, d);
                    }
                    shrTo(c, 1, c);
                }
                else if (!isEven(d))
                    subTo(d, m, d);
                shrTo(d, 1, d);
            }
            if (compare(u, v) >= 0) {
                subTo(u, v, u);
                if (ac)
                    subTo(a, c, a);
                subTo(b, d, b);
            }
            else {
                subTo(v, u, v);
                if (ac)
                    subTo(c, a, c);
                subTo(d, b, d);
            }
        }
        if (compare(v, ONE) !== 0)
            return ZERO;
        if (compare(d, m) >= 0)
            return subtract(d, m);
        if (sig(d) < 0)
            addTo(d, m, d);
        else
            return d;
        if (sig(d) < 0)
            return add(d, m);
        else
            return d;
    }

    function testBit(x, n) {
        var j = Math.floor(n / DB);
        if (j >= x.t)
            return (x.s !== 0);
        return ((x[j] & (1 << (n % DB))) !== 0);
    }

    function nothing(x) {
        return x;
    }

    function extend(c, o) {
        for (var i in o)
            c.prototype[i] = o[i];
    }

    /*
     * Classic, Barret, Mongomery reductions, optimized ExpMod algorithms
     * optimized release of http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn2.js
     * 
     */

    // Classic reduction
    var Classic = function (m) {
        this.m = m;
    };

    extend(Classic, {
        convert: function (x) {
            if (x.s < 0 || compare(x, this.m) >= 0)
                return mod(x, this.m);
            else
                return x;
        },
        revert: nothing,
        reduce: function (x) {
            modTo(x, this.m, x);
        },
        sqrTo: function (x, r) {
            sqrTo(x, r);
            this.reduce(r);
        },
        mulTo: function (x, y, r) {
            mulTo(x, y, r);
            this.reduce(r);
        }
    });

    function invDig(a) {
        if (a.t < 1)
            return 0;
        var x = a[0];
        if ((x & 1) === 0)
            return 0;
        var y = x & 3;
        y = (y * (2 - (x & 0xf) * y)) & 0xf;
        y = (y * (2 - (x & 0xff) * y)) & 0xff;
        y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff;
        y = (y * (2 - x * y % DV)) % DV;
        return (y > 0) ? DV - y : -y;
    }

    // Montgomery reduction
    var Montgomery = function (m) {
        this.m = m;
        this.mp = invDig(m);
        this.mpl = this.mp & 0x7fff;
        this.mph = this.mp >> 15;
        this.um = (1 << (DB - 15)) - 1;
        this.mt2 = 2 * m.t;
    };

    extend(Montgomery, {
        // xR mod m
        convert: function (x) {
            var r = nbi(x.t);
            dshlTo(abs(x), this.m.t, r);
            divRemTo(r, this.m, null, r);
            if (x.s < 0 && compare(r, ZERO) > 0)
                subTo(this.m, r, r);
            return r;
        },
        // x/R mod m
        revert: function (x) {
            var r = nbi(x.t);
            copyTo(x, r);
            this.reduce(r);
            return r;
        },
        // x = x/R mod m (HAC 14.32)
        reduce: function (x) {
            while (x.t <= this.mt2)
                x[x.t++] = 0;
            for (var i = 0; i < this.m.t; ++i) {
                var j = x[i] & 0x7fff;
                var u0 = (j * this.mpl + (((j * this.mph + (x[i] >> 15) * this.mpl) & this.um) << 15)) & DM;
                j = i + this.m.t;
                x[j] += am(this.m, 0, u0, x, i, 0, this.m.t);
                while (x[j] >= DV) {
                    x[j] -= DV;
                    x[++j]++;
                }
            }
            clamp(x);
            dshrTo(x, this.m.t, x);
            if (compare(x, this.m) >= 0)
                subTo(x, this.m, x);
        },
        // r = "x^2/R mod m"; x != r
        sqrTo: function (x, r) {
            sqrTo(x, r);
            this.reduce(r);
        },
        // r = "xy/R mod m"; x,y != r
        mulTo: function (x, y, r) {
            mulTo(x, y, r);
            this.reduce(r);
        }
    });

    function dAddOffset(x, n, w) {
        if (n === 0)
            return;
        while (x.t <= w)
            x[x.t++] = 0;
        x[w] += n;
        while (x[w] >= DV) {
            x[w] -= DV;
            if (++w >= x.t)
                x[x.t++] = 0;
            ++x[w];
        }
    }

    function mulLowerTo(x, a, n, r) {
        var i = Math.min(x.t + a.t, n);
        r.s = 0; // assumes a,x >= 0
        r.t = i;
        while (i > 0)
            r[--i] = 0;
        var j;
        for (j = r.t - x.t; i < j; ++i)
            r[i + x.t] = am(x, 0, a[i], r, i, 0, x.t);
        for (j = Math.min(a.t, n); i < j; ++i)
            am(x, 0, a[i], r, i, 0, n - i);
        return clamp(r);
    }

    function mulUpperTo(x, a, n, r) {
        --n;
        var i = r.t = x.t + a.t - n;
        r.s = 0; // assumes a,x >= 0
        while (--i >= 0)
            r[i] = 0;
        for (i = Math.max(n - x.t, 0); i < a.t; ++i)
            r[x.t + i - n] = am(x, n - i, a[i], r, 0, 0, x.t + i - n);
        clamp(r);
        return dshrTo(r, 1, r);
    }

    // Barrett modular reduction
    function Barrett(m) {
        // setup Barrett
        this.r2 = nbi(2 * m.t);
        this.q3 = nbi(2 * m.t);
        dshlTo(ONE, 2 * m.t, this.r2);
        this.mu = div(this.r2, m);
        this.m = m;
    }

    extend(Barrett, {
        convert: function (x) {
            if (x.s < 0 || x.t > 2 * this.m.t)
                return mod(x, this.m);
            else if (compare(x, this.m) < 0)
                return x;
            else {
                var r = nbi(x.t);
                copyTo(x, r);
                this.reduce(r);
                return r;
            }
        },
        revert: function (x) {
            return x;
        },
        // x = x mod m (HAC 14.42)
        reduce: function (x) {
            dshrTo(x, this.m.t - 1, this.r2);
            if (x.t > this.m.t + 1) {
                x.t = this.m.t + 1;
                clamp(x);
            }
            mulUpperTo(this.mu, this.r2, this.m.t + 1, this.q3);
            mulLowerTo(this.m, this.q3, this.m.t + 1, this.r2);
            while (compare(x, this.r2) < 0)
                dAddOffset(x, 1, this.m.t + 1);
            subTo(x, this.r2, x);
            while (compare(x, this.m) >= 0)
                subTo(x, this.m, x);
        },
        // r = x^2 mod m; x != r
        sqrTo: function (x, r) {
            sqrTo(x, r);
            this.reduce(r);
        },
        // r = x*y mod m; x,y != r
        mulTo: function (x, y, r) {
            mulTo(x, y, r);
            this.reduce(r);
        }

    });

    // x^e % m (HAC 14.85)
    function expMod(x, e, m) {
        var i = bitLength(e), k, r = nbv(1), z;
        if (i <= 0)
            return r;
        else if (i < 18)
            k = 1;
        else if (i < 48)
            k = 3;
        else if (i < 144)
            k = 4;
        else if (i < 768)
            k = 5;
        else
            k = 6;
        if (i < 8)
            z = new Classic(m);
        else if (isEven(m))
            z = new Barrett(m);
        else
            z = new Montgomery(m);

        // precomputation
        var g = new Array(), n = 3, k1 = k - 1, km = (1 << k) - 1;
        g[1] = z.convert(x);
        if (k > 1) {
            var g2 = nbi(m.t * 2);
            z.sqrTo(g[1], g2);
            while (n <= km) {
                g[n] = nbi(m.t * 2);
                z.mulTo(g2, g[n - 2], g[n]);
                n += 2;
            }
        }

        var j = e.t - 1, w, is1 = true, r2 = nbi(m.t * 2), t;
        i = nbits(e[j]) - 1;
        while (j >= 0) {
            if (i >= k1)
                w = (e[j] >> (i - k1)) & km;
            else {
                w = (e[j] & ((1 << (i + 1)) - 1)) << (k1 - i);
                if (j > 0)
                    w |= e[j - 1] >> (DB + i - k1);
            }

            n = k;
            while ((w & 1) == 0) {
                w >>= 1;
                --n;
            }
            if ((i -= n) < 0) {
                i += DB;
                --j;
            }
            if (is1) {	// ret == 1, don't bother squaring or multiplying it
                copyTo(g[w], r);
                is1 = false;
            }
            else {
                while (n > 1) {
                    z.sqrTo(r, r2);
                    z.sqrTo(r2, r);
                    n -= 2;
                }
                if (n > 0)
                    z.sqrTo(r, r2);
                else {
                    t = r;
                    r = r2;
                    r2 = t;
                }
                z.mulTo(r2, g[w], r);
            }
            while (j >= 0 && (e[j] & (1 << i)) == 0) {
                z.sqrTo(r, r2);
                t = r;
                r = r2;
                r2 = t;
                if (--i < 0) {
                    i = DB - 1;
                    --j;
                }
            }
        }
        return z.revert(r);
    }

    /*
     * EC Field Elements, Points, Curves
     * optimized release of http://www-cs-students.stanford.edu/~tjw/jsbn/ec.js
     * 
     */

    // EC Field Elemets
    function newFE(a, x) {
        a.r.reduce(x);
        x.q = a.q;
        x.r = a.r;
        return x;
    }

    function copyFE(a, x) {
        x.q = a.q;
        x.r = a.r;
        return x;
    }

    function negFE(a) {
        return copyFE(a, sub(a.q, a));
    }

    function addFE(a, b) {
        var r = add(a, b);
        if (compare(r, a.q) > 0)
            subTo(r, a.q, r);
        return copyFE(a, r);
    }

    function subFE(a, b) {
        var r = sub(a, b);
        if (r.s < 0)
            addTo(a.q, r, r);
        return copyFE(a, r);
    }

    function mulFE(a, b) {
        return newFE(a, mul(a, b));
    }

    function sqrFE(a) {
        return newFE(a, sqr(a));
    }

    function shlFE(a, i) {
        return newFE(a, shl(a, i));
    }

    function invFE(a) {
        return copyFE(a, invMod(a, a.q));
    }

    // EC Points
    function newEC(curve, x, y, z) {
        return {
            curve: curve,
            x: x,
            y: y,
            z: z || newFE(curve, ONE)
        };
    }

    function getX(point) {
        if (!point.zinv)
            point.zinv = invFE(point.z);
        return mulFE(point.x, point.zinv);
    }

    function getY(point) {
        if (!point.zinv)
            point.zinv = invFE(point.z);
        return mulFE(point.y, point.zinv);
    }

    function isInfinity(a) {
        if ((!a.x) && (!a.y))
            return true;
        return isZero(a.z) && !isZero(a.y);
    }

    function getInfinity(a) {
        return a.curve.infinity;
    }

    function equalsEC(a, b) {
        if (a === b)
            return true;
        if (isInfinity(a))
            return isInfinity(b);
        if (isInfinity(b))
            return isInfinity(a);
        var u, v;
        // u = Y2 * Z1 - Y1 * Z2
        u = subFE(mulFE(b.y, a.z), mulFE(a.y, b.z));
        if (!isZero(u))
            return false;
        // v = X2 * Z1 - X1 * Z2
        v = subFE(mulFE(b.x, a.z), mulFE(a.x, b.z));
        return isZero(v);
    }

    function negEC(a) {
        return newEC(a.curve, a.x, negFE(a.y), a.z);
    }

    function addEC(a, b) {
        if (isInfinity(a))
            return b;
        if (isInfinity(b))
            return a;

        // u = Y2 * Z1 - Y1 * Z2
        var u = subFE(mulFE(b.y, a.z), mulFE(a.y, b.z));
        // v = X2 * Z1 - X1 * Z2
        var v = subFE(mulFE(b.x, a.z), mulFE(a.x, b.z));

        if (isZero(v)) {
            if (isZero(u)) {
                return twiceEC(a); // a == b, so double
            }
            return getInfinity(a); // a = -b, so infinity
        }

        var x1 = a.x;
        var y1 = a.y;

        var v2 = sqrFE(v);
        var v3 = mulFE(v2, v);
        var x1v2 = mulFE(x1, v2);
        var zu2 = mulFE(sqrFE(u), a.z);

        // x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3)
        var x3 = mulFE(subFE(mulFE(subFE(zu2, shlFE(x1v2, 1)), b.z), v3), v);
        // y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3
        var y3 = addFE(mulFE(subFE(subFE(mulFE(mulFE(x1v2, THREE), u), mulFE(y1, v3)), mulFE(zu2, u)), b.z), mulFE(u, v3));
        // z3 = v^3 * z1 * z2
        var z3 = mulFE(mulFE(v3, a.z), b.z);

        return newEC(a.curve, x3, y3, z3);
    }

    function twiceEC(b) {
        if (isInfinity(b))
            return b;
        if (sig(b.y) === 0)
            return getInfinity(b);

        var x1 = b.x;
        var y1 = b.y;

        var y1z1 = mulFE(y1, b.z);
        var y1sqz1 = mulFE(y1z1, y1);
        var a = b.curve.a;

        // w = 3 * x1^2 + a * z1^2
        var w = mulFE(sqrFE(x1), THREE);
        if (!isZero(a)) {
            w = addFE(w, mulFE(sqrFE(b.z), a));
        }

        // x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1)
        var x3 = mulFE(shlFE(subFE(sqrFE(w), mulFE(shlFE(x1, 3), y1sqz1)), 1), y1z1);
        // y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3
        var y3 = subFE(mulFE(shlFE(subFE(mulFE(mulFE(w, THREE), x1), shlFE(y1sqz1, 1)), 2), y1sqz1), mulFE(sqrFE(w), w));
        // z3 = 8 * (y1 * z1)^3
        var z3 = shlFE(mulFE(sqrFE(y1z1), y1z1), 3);

        return newEC(b.curve, x3, y3, z3);
    }

    // Simple NAF (Non-Adjacent Form) multiplication algorithm
    function mulEC(a, k) {
        if (isInfinity(a))
            return a;
        if (sig(k) === 0)
            return getInfinity(a);

        var e = k;
        var h = mul(e, THREE);

        var neg = negEC(a);
        var R = a;

        var i;
        for (i = bitLength(h) - 2; i > 0; --i) {
            R = twiceEC(R);

            var hBit = testBit(h, i);
            var eBit = testBit(e, i);

            if (hBit !== eBit) {
                R = addEC(R, hBit ? a : neg);
            }
        }

        return R;
    }

    function mul2AndAddEC(a, k) {
        var nbits = bitLength(k);
        var R = a,
                Q = getInfinity(a);

        for (var i = 0; i < nbits - 1; i++) {
            if (testBit(k, i) === 1)
                Q = addEC(Q, R);

            R = twiceEC(R);
        }

        if (testBit(k, nbits - 1) === 1)
            Q = addEC(Q, R);

        return Q;
    }

    // Compute a*j + x*k (simultaneous multiplication)
    function mulTwoEC(a, j, x, k) {
        var i;
        if (bitLength(j) > bitLength(k))
            i = bitLength(j) - 1;
        else
            i = bitLength(k) - 1;

        var R = getInfinity(a);
        var both = addEC(a, x);
        while (i >= 0) {
            R = twiceEC(R);
            if (testBit(j, i)) {
                if (testBit(k, i)) {
                    R = addEC(R, both);
                }
                else {
                    R = addEC(R, a);
                }
            }
            else {
                if (testBit(k, i)) {
                    R = addEC(R, x);
                }
            }
            --i;
        }

        return R;
    }

    // EC Curve
    function newCurve(q, a, b) {
        var curve = {};
        curve.q = q;
        curve.r = new Barrett(q);
        curve.a = newFE(curve, a);
        curve.b = newFE(curve, b);
        curve.infinity = newEC(curve);
        return curve;
    }

    /*
     * Converion tools (hex, binary)
     * 
     */

    function atobi(d) {
        var k = 8;
        var a = new Uint8Array(d);
        var r = nbi(a.length * 8 / DB);
        r.t = 0;
        r.s = 0;
        var sh = 0;
        for (var i = 0, n = a.length; i < n; i++) {
            var x = a[i];
            if (sh === 0)
                r[r.t++] = x;
            else if (sh + k > DB) {
                r[r.t - 1] |= (x & ((1 << (DB - sh)) - 1)) << sh;
                r[r.t++] = (x >> (DB - sh));
            }
            else
                r[r.t - 1] |= x << sh;
            sh += k;
            if (sh >= DB)
                sh -= DB;
        }
        return clamp(r);
    }

    function bitoa(s, bitLength) {
        var k = 8;
        var km = (1 << k) - 1, d, m = false, r = [], i = s.t;
        var p = DB - (i * DB) % k;
        if (i-- > 0) {
            if (p < DB && (d = s[i] >> p) > 0) {
                m = true;
                r.push(d);
            }
            while (i >= 0) {
                if (p < k) {
                    d = (s[i] & ((1 << p) - 1)) << (k - p);
                    d |= s[--i] >> (p += DB - k);
                }
                else {
                    d = (s[i] >> (p -= k)) & km;
                    if (p <= 0) {
                        p += DB;
                        --i;
                    }
                }
                if (d > 0)
                    m = true;
                if (m)
                    r.push(d);
            }
        }
        var r8 = new Uint8Array(bitLength ? bitLength / 8 : r.length);
        if (m)
            r8.set(r.reverse());
        return r8.buffer;
    }


    function htobi(s) {
        if (typeof s === 'number' || s instanceof Number)
            return nbv(s);
        s = s.replace(/[^\-A-Fa-f0-9]/g, '');
        if (!s)
            s = '0';
        var k = 4;
        var r = nbi(s.length / 7);
        var i = s.length, mi = false, sh = 0;
        while (--i >= 0) {
            var c = s.charAt(i);
            if (c === '-') {
                mi = true;
                continue;
            }
            var x = parseInt(s.charAt(i), 16);
            mi = false;
            if (sh === 0)
                r[r.t++] = x;
            else if (sh + k > DB) {
                r[r.t - 1] |= (x & ((1 << (DB - sh)) - 1)) << sh;
                r[r.t++] = (x >> (DB - sh));
            }
            else
                r[r.t - 1] |= x << sh;
            sh += k;
            if (sh >= DB)
                sh -= DB;
        }
        if (mi)
            subTo(ZERO, r, r);
        return clamp(r);
    }

    function bitoh(x) {
        if (x.s < 0)
            return "-" + bitoh(negTo(x, nbi(x.t)));
        var k = 4;
        var km = (1 << k) - 1, d, m = false, r = "", i = x.t;
        var p = DB - (i * DB) % k;
        if (i-- > 0) {
            if (p < DB && (d = x[i] >> p) > 0) {
                m = true;
                r = d.toString(16);
            }
            while (i >= 0) {
                if (p < k) {
                    d = (x[i] & ((1 << p) - 1)) << (k - p);
                    d |= x[--i] >> (p += DB - k);
                }
                else {
                    d = (x[i] >> (p -= k)) & km;
                    if (p <= 0) {
                        p += DB;
                        --i;
                    }
                }
                if (d > 0)
                    m = true;
                if (m)
                    r += d.toString(16);
            }
        }
        return "0x" + (m ? r : "0");
    }

    // biginteger to big-endian integer bytearray
    function bitoi(s) {
        var i = s.t, r = [];
        r[0] = s.s;
        var p = DB - (i * DB) % 8, d, k = 0;
        if (i-- > 0) {
            if (p < DB && (d = s[i] >> p) !== (s.s & DM) >> p)
                r[k++] = d | (s.s << (DB - p));
            while (i >= 0) {
                if (p < 8) {
                    d = (s[i] & ((1 << p) - 1)) << (8 - p);
                    d |= s[--i] >> (p += DB - 8);
                }
                else {
                    d = (s[i] >> (p -= 8)) & 0xff;
                    if (p <= 0) {
                        p += DB;
                        --i;
                    }
                }
                if ((d & 0x80) !== 0)
                    d |= -256;
                if (k === 0 && (s.s & 0x80) !== (d & 0x80))
                    ++k;
                if (k > 0 || d !== s.s)
                    r[k++] = d;
            }
        }
        return new Uint8Array(r).buffer;
    }

    // big-endian integer bytearray to biginteger
    function itobi(d) {
        var k = 8, s = new Uint8Array(d),
                r = nbi(s.length / 7);
        r.t = 0;
        r.s = 0;
        var i = s.length, sh = 0;
        while (--i >= 0) {
            var x = s[i] & 0xff;
            if (sh === 0)
                r[r.t++] = x;
            else if (sh + k > DB) {
                r[r.t - 1] |= (x & ((1 << (DB - sh)) - 1)) << sh;
                r[r.t++] = (x >> (DB - sh));
            }
            else
                r[r.t - 1] |= x << sh;
            sh += k;
            if (sh >= DB)
                sh -= DB;
        }
        if ((s[0] & 0x80) !== 0) {
            r.s = -1;
            if (sh > 0)
                r[r.t - 1] |= ((1 << (DB - sh)) - 1) << sh;
        }
        return clamp(r);
    }


    // Swap bytes in buffer
    function swap(s) {
        var src = new Uint8Array(s),
                dst = new Uint8Array(src.length);
        for (var i = 0, n = src.length; i < n; i++)
            dst[n - i - 1] = src[i];
        return dst.buffer;
    }

    // Calculate hash of data
    function hash(d) {
        if (this.hash)
            d = this.hash.digest(d);
        // Swap hash for SignalCom
        if (this.procreator === 'SC' ||
                (this.procreator === 'VN' && this.hash.version === 2012))
            d = swap(d);
        return d;
    }

    // Check buffer
    function buffer(d) {
        if (d instanceof CryptoOperationData)
            return d;
        else if (d && d.buffer && d.buffer instanceof CryptoOperationData)
            return d.byteOffset === 0 && d.byteLength === d.buffer.byteLength ?
                    d.buffer : new Uint8Array(new Uint8Array(d, d.byteOffset, d.byteLength)).buffer;
        else
            throw new DataError('CryptoOperationData or CryptoOperationDataView required');
    }

    // Check double buffer
    function to2(d) {
        var b = buffer(d);
        if (b.byteLength % 2 > 0)
            throw new DataError('Buffer length must be even');
        var n = b.byteLength / 2;
        return [atobi(new Uint8Array(b, 0, n)), atobi(new Uint8Array(b, n, n))];
    }

    function from2(x, y, bitLength) {
        var a = bitoa(x, bitLength),
                b = bitoa(y, bitLength),
                d = new Uint8Array(a.byteLength + b.byteLength);
        d.set(new Uint8Array(a));
        d.set(new Uint8Array(b), a.byteLength);
        return d.buffer;
    }

    function getSeed(length) {
        var randomSource = new GostRandom();
        if (randomSource.getRandomValues) {
            var d = new Uint8Array(Math.ceil(length / 8));
            randomSource.getRandomValues(d);
            return d;
        } else
            throw new NotSupportedError('Random generator not found');
    }

    /**
     * Algorithm name GOST R 34.10<br><br>
     * 
     * The sign method returns sign data generated with the supplied privateKey.<br>
     * 
     * @memberOf GostSign
     * @method sign
     * @instance
     * @param {(CryptoOperationData|TypedArray)} privateKey Private key
     * @param {(CryptoOperationData|TypedArray)} data Data
     * @returns {CryptoOperationData} Signature
     */
    function sign(privateKey, data)
    {

        // Stage 1
        var b = buffer(data);
        var alpha = atobi(hash.call(this, b));

        var q = this.q;
        var x = mod(atobi(buffer(privateKey)), q);

        // Stage 2
        var e = mod(alpha, q);
        if (isZero(e))
            e = ONE;

        var s = ZERO;
        while (isZero(s)) {
            var r = ZERO;
            while (isZero(r)) {

                // Stage 3
                var k = mod(atobi(this.ukm ||
                        getSeed(this.bitLength)), q); // pseudo random 0 < k < q
                // Stage 4
                if (this.curve) {
                    // Gost R 34.10-2001 || Gost R 34.10-2012 
                    var P = this.P;
                    var C = mulEC(P, k);
                    r = mod(getX(C), q);
                } else {
                    // Gost R 34.10-94
                    var p = this.p, a = this.a;
                    r = mod(expMod(a, k, p), q);
                }
            }
            // Stage 5
            s = mod(add(mul(r, x), mul(k, e)), q);
        }
        // Stage 6
        // console.log('s', bitoh(s));
        // console.log('r', bitoh(r));
        var zetta;
        // Integer structure for SignalCom algorithm
        if (this.procreator === 'SC') {
            zetta = {
                r: bitoh(r),
                s: bitoh(s)
            };
        } else {
            zetta = from2(r, s, this.bitLength);
            // Swap bytes for CryptoPro algorithm
            if (this.procreator === 'CP' || this.procreator === 'VN')
                zetta = swap(zetta);
        }
        return zetta;
    }

    /**
     * Algorithm name GOST R 34.10<br><br>
     * 
     * The verify method returns signature verification for the supplied publicKey.<br>
     * 
     * @memberOf GostSign
     * @method sign
     * @instance
     * @param {(CryptoOperationData|TypedArray)} publicKey Public key
     * @param {(CryptoOperationData|TypedArray)} signature Signature
     * @param {(CryptoOperationData|TypedArray)} data Data
     * @returns {boolean} Signature verified = true
     */
    function verify(publicKey, signature, data)
    {

        // Stage 1
        var q = this.q;
        var r, s;
        // Ready int for SignalCom algorithm
        if (this.procreator === 'SC') {
            r = htobi(signature.r);
            s = htobi(signature.s);
        } else {
            if (this.procreator === 'CP' || this.procreator === 'VN')
                signature = swap(signature);
            var zetta = to2(signature);
            // Swap bytes for CryptoPro algorithm
            s = zetta[1]; //  first 32 octets contain the big-endian representation of s 
            r = zetta[0]; //  and second 32 octets contain the big-endian representation of r
        }
        if (compare(r, q) >= 0 || compare(s, q) >= 0)
            return false;
        // Stage 2
        var b = buffer(data);
        var alpha = atobi(hash.call(this, b));
        // Stage 3
        var e = mod(alpha, q);
        if (isZero(e) === 0)
            e = ONE;
        // Stage 4
        var v = invMod(e, q);
        // Stage 5
        var z1 = mod(mul(s, v), q);
        var z2 = sub(q, mod(mul(r, v), q));
        // Stage 6
        if (this.curve) {
            // Gost R 34.10-2001 || Gost R 34.10-2012 
            var k2 = to2(publicKey),
                    curve = this.curve,
                    P = this.P,
                    x = newFE(curve, k2[0]), // first 32 octets contain the little-endian representation of x
                    y = newFE(curve, k2[1]), // and second 32 octets contain the little-endian representation of y.
                    Q = new newEC(curve, x, y); // This corresponds to the binary representation of (<y>256||<x>256) 
            var C = mulTwoEC(P, z1, Q, z2);
            var R = mod(getX(C), q);
        } else {
            // Gost R 34.10-94
            var p = this.p, a = this.a;
            var y = atobi(publicKey);
            var R = mod(mod(mul(expMod(a, z1, p), expMod(y, z2, p)), p), q);
        }
        // Stage 7
        return (compare(R, r) === 0);
    }

    /**
     * Algorithm name GOST R 34.10<br><br>
     * 
     * The generateKey method returns a new generated key pair using the specified 
     * AlgorithmIdentifier.
     * 
     * @memberOf GostSign
     * @method generateKey
     * @instance
     * @returns {Object} Object with two CryptoOperationData members: privateKey and publicKey
     */
    function generateKey()
    {
        var curve = this.curve;
        if (curve) {

            var Q = curve.infinity;
            while (isInfinity(Q)) {

                // Generate random private key
                var d = ZERO;
                if (this.ukm) {
                    d = atobi(this.ukm);
                } else {
                    while (isZero(d))
                        d = mod(atobi(getSeed(this.bitLength)), this.q); // 0 < d < q
                }

                // Calculate public key
                Q = mulEC(this.P, d);
                var x = getX(Q), y = getY(Q);
                // console.log('d', bitoh(d));
                // console.log('x', bitoh(x));
                // console.log('y', bitoh(y));
            }

            // Return result
            return {
                privateKey: bitoa(d, this.bitLength),
                publicKey: from2(x, y, this.bitLength) // This corresponds to the binary representation of (<y>256||<x>256)
            };

        } else
            throw new NotSupportedError('Key generation for GOST R 34.10-94 not supported');
    }

    /**
     * Algorithm name GOST R 34.10 mode MASK<br><br>
     * 
     * The generateMaskKey method returns a new generated key mask using for wrapping.
     * 
     * @memberOf GostSign
     * @method generateMaskKey
     * @instance
     * @returns {Object} Object with two CryptoOperationData members: privateKey and publicKey
     */
    function generateMaskKey()
    {
        var curve = this.curve;
        if (curve) {
            // Generate random private key
            var d = ZERO;
            while (isZero(d))
                d = mod(atobi(getSeed(this.bitLength)), this.q); // 0 < d < q

            // Return result
            return bitoa(d, this.bitLength);
        } else
            throw new NotSupportedError('Key generation for GOST R 34.10-94 not supported');
    }

    /**
     * Algorithm name GOST R 34.10<br><br>
     * 
     * Unwrap private key from private key and ukm (mask)
     * 
     * @memberOf GostSign
     * @method unwrap
     * @instance
     * @param {(CryptoOperationData|TypedArray)} baseKey Unwrapping key
     * @param {(CryptoOperationData|TypedArray)} data Wrapped key
     * @returns {Object} CryptoOperationData unwrapped privateKey
     */
    function unwrapKey(baseKey, data)
    {
        var curve = this.curve;
        if (curve) {
            var q = this.q;
            var x = mod(atobi(buffer(data)), q);
            var y = mod(atobi(buffer(baseKey)), q);
            var z = this.procreator === 'VN' ? mod(mul(x, y), q) : mod(mul(x, invMod(y, q)), q);
            return bitoa(z);
        } else
            throw new NotSupportedError('Key wrapping GOST R 34.10-94 not supported');
    }

    /**
     * Algorithm name GOST R 34.10<br><br>
     * 
     * Wrap private key with private key and ukm (mask)
     * 
     * @memberOf GostSign
     * @method unwrap
     * @instance
     * @param {(CryptoOperationData|TypedArray)} baseKey Wrapping key
     * @param {(CryptoOperationData|TypedArray)} data Key
     * @returns {Object} CryptoOperationData unwrapped privateKey
     */
    function wrapKey(baseKey, data)
    {
        var curve = this.curve;
        if (curve) {
            var q = this.q;
            var x = mod(atobi(buffer(data)), q);
            var y = mod(atobi(buffer(baseKey)), q);
            var z = this.procreator === 'VN' ? mod(mul(x, invMod(y, q)), q) : mod(mul(x, y), q);
            return bitoa(z);
        } else
            throw new NotSupportedError('Key wrapping GOST R 34.10-94 not supported');
    }

    /**
     * Algorithm name GOST R 34.10<br><br>
     * 
     * @memberOf GostSign
     * @method derive
     * @instance
     * @private
     * @param {CryptoOperationData} baseKey Key for deriviation
     * @returns {CryptoOperationData}
     */
    function derive(baseKey)
    {

        var k, ukm = atobi(this.ukm);
        var q = this.q;
        var x = mod(atobi(buffer(baseKey)), q);

        if (this.curve) {
            // 1) Let K(x,y,UKM) = ((UKM*x)(mod q)) . (y.P) (512 bit), where      
            // x - sender’s private key (256 bit)      
            // x.P - sender’s public key (512 bit)      
            // y - recipient’s private key (256 bit)      
            // y.P - recipient’s public key (512 bit)      
            // UKM - non-zero integer, produced as in step 2 p. 6.1 [GOSTR341001]      
            // P - base point on the elliptic curve (two 256-bit coordinates)      
            // UKM*x - x multiplied by UKM as integers      
            // x.P - a multiple point   
            var K = mulEC(this.peer_Q, mod(mul(ukm, x), q));
            k = from2(getX(K), getY(K), // This corresponds to the binary representation of (<y>256||<x>256)
                    this.bitLength);
        } else {
            // 1) Let K(x,y) = a^(x*y) (mod p), where      
            // x - sender’s private key, a^x - sender’s public key      
            // y - recipient’s private key, a^y - recipient’s public key      
            // a, p - parameters
            var p = this.p, a = this.a;
            k = bitoa(expMod(this.peer_y, x, p));
        }
        // 2) Calculate a 256-bit hash of K(x,y,UKM):      
        // KEK(x,y,UKM) = gostSign (K(x,y,UKM)
        return hash.call(this, k);
    }

    /**
     * Algorithm name GOST R 34.10<br><br>
     * 
     * The deriveBits method returns length bits on baseKey.
     * 
     * @memberOf GostSign
     * @method deriveBits
     * @instance
     * @param {(CryptoOperationData|TypedArray)} baseKey Key for deriviation
     * @param {number} length output bit-length
     * @returns {CryptoOperationData} result
     */
    function deriveBits(baseKey, length)
    {
        if (length < 8 || length > this.bitLength || length % 8 > 0)
            throw new DataError('Length must be no more than ' + this.bitLength + ' bits and multiple of 8');
        var n = length / 8,
                b = derive.call(this, baseKey),
                r = new Uint8Array(n);

        r.set(new Uint8Array(b, 0, n));
        return r.buffer;
    }

    /**
     * Algorithm name GOST R 34.10<br><br>
     * 
     * The deriveKey method returns 256 bit Key encryption key on baseKey.
     * 
     * This algorithm creates a key encryption key (KEK) using 64 bit UKM,   
     * the sender’s private key, and the recipient’s public key (or the   
     * reverse of the latter pair
     * 
     * @memberOf GostSign
     * @method deriveKey
     * @instance
     * @param {(CryptoOperationData|TypedArray)} baseKey Key for deriviation
     * @returns {CryptoOperationData} result
     */
    function deriveKey(baseKey)
    {
        var b = derive.call(this, baseKey),
                r = new Uint8Array(32);

        r.set(new Uint8Array(b, 0, 32));
        return r.buffer;
    }


    /**
     * Gost R 34.10 universal object<br><br>
     * 
     * References: {@link http://tools.ietf.org/html/rfc6986} and {@link http://tools.ietf.org/html/rfc5831}<br><br>
     * 
     * Normalized algorithm identifier common parameters:
     * 
     *  <ul>
     *      <li><b>name</b> Algorithm name 'GOST R 34.10'</li>
     *      <li><b>version</b> Algorithm version
     *          <ul>
     *              <li><b>1994</b> - Old-style GOST R 34.10-94 ExpMod algorithm with GOST R 34.11-94 hash</li>
     *              <li><b>2001</b> - GOST R 34.10-2001 Eliptic curve algorithm with old GOST R 34.11-94 hash</li>
     *              <li><b>2012</b> - GOST R 34.10-2012 Eliptic curve algorithm with GOST R 34.11-12 hash, default mode</li>
     *          </ul>
     *      </li>
     *      <li><b>length</b> Length of hash and signature. Key length == hash length for EC algorithms and 2 * hash length for ExpMod algorithm
     *          <ul>
     *              <li><b>GOST R 34.10-256</b> - 256 bits digest, default mode</li>
     *              <li><b>GOST R 34.10-512</b> - 512 bits digest only for GOST R 34.11-2012 hash</li>
     *          </ul>
     *      </li>
     *      <li><b>mode</b> Algorithm mode
     *          <ul>
     *              <li><b>SIGN</b> Digital signature mode (default)</li>
     *              <li><b>DH</b> Diffie-Hellman key generation and key agreement mode</li>
     *          </ul>
     *      </li>
     *      <li><b>sBox</b> Paramset sBox for GOST 34.11-94. Used only if version = 1994 or 2001</li>
     *  </ul>
     *  
     * Supported algorithms, modes and parameters:
     * 
     *  <ul>
     *      <li>Sign/Verify mode (SIGN)</li>
     *      <li>DeriveKey/DeriveBits mode (DH)
     *          <ul>
     *              <li>{@link CryptoOperationData} <b>ukm</b> User key material. Default - random generated value</li>
     *              <li>{@link CryptoOperationData} <b>public</b> The peer's EC public key data</li>
     *          </ul>
     *      </li>
     *      <li>GenerateKey mode (SIGN and DH) version = 1994
     *          <ul>
     *              <li><b>namedParam</b> Paramset for key generation algorithm. If specified no additianal parameters required</li>
     *          </ul>
     *          Additional parameters, if namedParam not specified
     *          <ul>
     *              <li><b>modulusLength</b> Bit length of p (512 or 1024 bits). Default = 1024</li>
     *              <li><b>p</b> {@link CryptoOperationData} Modulus, prime number, 2^(t-1)<p<2^t</li>
     *              <li><b>q</b> {@link CryptoOperationData} Order of cyclic group, prime number, 2^254<q<2^256, q is a factor of p-1</li>
     *              <li><b>a</b> {@link CryptoOperationData} Generator, integer, 1<a<p-1, at that aq (mod p) = 1</li>
     *          </ul>
     *      </li>
     *      <li>GenerateKey mode (SIGN and DH) version = 2001 or 2012
     *          <ul>
     *              <li><b>namedCurve</b> Paramset for key generation algorithm. If specified no additianal parameters required</li>
     *          </ul>
     *          Additional EC parameters, if namedCurve not specified
     *          <ul>
     *              <li><b>p</b> {@link CryptoOperationData} Prime number - elliptic curve modulus</li>
     *              <li><b>a</b> {@link CryptoOperationData} Coefficients a of the elliptic curve E</li>
     *              <li><b>b</b> {@link CryptoOperationData} Coefficients b of the elliptic curve E</li>
     *              <li><b>q</b> {@link CryptoOperationData} Prime number - order of cyclic group</li>
     *              <li><b>x</b> {@link CryptoOperationData} Base point p x-coordinate</li>
     *              <li><b>y</b> {@link CryptoOperationData} Base point p y-coordinate</li>
     *          </ul>
     *      </li>
     *  </ul>
     *  
     * @class GostSign
     * @param {AlgorithmIndentifier} algorithm
     */
    function GostSign(algorithm)
    {
        algorithm = algorithm || {};
        this.name = (algorithm.name || 'GOST R 34.10') + '-' +
                ((algorithm.version || 2012) % 100) + '-' + (algorithm.length || 256) +
                (((algorithm.mode || 'SIGN') !== 'SIGN') ? '-' + algorithm.mode : '') +
                (typeof algorithm.namedParam === 'string' ? '/' + algorithm.namedParam : '') +
                (typeof algorithm.namedCurve === 'string' ? '/' + algorithm.namedCurve : '') +
                (typeof algorithm.sBox === 'string' ? '/' + algorithm.sBox : '');

        var version = algorithm.version || 2012;

        // Functions
        switch (algorithm.mode || 'SIGN') {
            case 'SIGN':
                this.sign = sign;
                this.verify = verify;
                this.generateKey = generateKey;
                break;
            case 'DH':
                this.deriveBits = deriveBits;
                this.deriveKey = deriveKey;
                this.generateKey = generateKey;
                break;
            case 'MASK':
                this.wrapKey = wrapKey;
                this.unwrapKey = unwrapKey;
                this.generateKey = generateMaskKey;
                break;
        }

        // Define parameters
        if (version === 1994) {
            // Named or parameters algorithm
            var param = algorithm.param;
            if (!param)
                param = GostParams[this.namedParam = (algorithm.namedParam || 'S-A').toUpperCase()];
            this.modulusLength = algorithm.modulusLength || param.modulusLength || 1024;
            this.p = htobi(param.p);
            this.q = htobi(param.q);
            this.a = htobi(param.a);
            // Public key for derive
            if (algorithm['public'])
                this.peer_y = atobi(algorithm['public']);
        } else {
            // Named or parameters algorithm
            var param = algorithm.curve;
            if (!param)
                param = ECGostParams[this.namedCurve = (algorithm.namedCurve || 'S-256-A').toUpperCase()];
            var curve = this.curve = newCurve(htobi(param.p), htobi(param.a), htobi(param.b));
            this.P = newEC(curve,
                    newFE(curve, htobi(param.x)),
                    newFE(curve, htobi(param.y)));
            this.q = htobi(param.q);
            // Public key for derive
            if (algorithm['public']) {
                var k2 = to2(algorithm['public']);
                this.peer_Q = new newEC(this.curve, // This corresponds to the binary representation of (<y>256||<x>256)
                        newFE(this.curve, k2[0]), // first 32 octets contain the little-endian representation of x
                        newFE(this.curve, k2[1])); // and second 32 octets contain the little-endian representation of y.
            }
        }

        // Check bit length
        var hashLen, keyLen;
        if (this.curve) {
            keyLen = algorithm.length || bitLength(this.q);
            if (keyLen > 508 && keyLen <= 512)
                keyLen = 512;
            else if (keyLen > 254 && keyLen <= 256)
                keyLen = 256;
            else
                throw new NotSupportedError('Support keys only 256 or 512 bits length');
            hashLen = keyLen;
        } else {
            keyLen = algorithm.modulusLength || bitLength(this.p);
            if (keyLen > 1016 && keyLen <= 1024)
                keyLen = 1024;
            else if (keyLen > 508 && keyLen <= 512)
                keyLen = 512;
            else
                throw new NotSupportedError('Support keys only 512 or 1024 bits length');
            hashLen = 256;
        }
        this.bitLength = hashLen;
        this.keyLength = keyLen;

        // Algorithm proceator for result conversion
        this.procreator = algorithm.procreator;

        // Hash function definition
        var hash = algorithm.hash;
        if (hash) {
            if (typeof hash === 'string' || hash instanceof String)
                hash = {name: hash};
            if (algorithm.version === 1994 || algorithm.version === 2001) {
                hash.version = 1994;
                hash.length = 256;
                hash.sBox = algorithm.sBox || hash.sBox;
            } else {
                hash.version = 2012;
                hash.length = hashLen;
            }
            hash.procreator = hash.procreator || algorithm.procreator;

            if (!GostDigest)
                throw new NotSupportedError('Object GostDigest not found');

            this.hash = new GostDigest(hash);
        }

        // Pregenerated seed for key exchange algorithms
        if (algorithm.ukm) // Now don't check size 
            this.ukm = algorithm.ukm;

    }

module.exports = GostSign;



/***/ }),

/***/ "./node_modules/node-gost-crypto/lib/index.js":
/*!****************************************************!*\
  !*** ./node_modules/node-gost-crypto/lib/index.js ***!
  \****************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

const gostCrypto = __webpack_require__(/*! ./gostCrypto */ "./node_modules/node-gost-crypto/lib/gostCrypto.js");
const gostEngine = __webpack_require__(/*! ./gostEngine */ "./node_modules/node-gost-crypto/lib/gostEngine.js");

__webpack_require__(/*! ./gostSecurity */ "./node_modules/node-gost-crypto/lib/gostSecurity.js");
__webpack_require__(/*! ./gostCoding */ "./node_modules/node-gost-crypto/lib/gostCoding.js");
__webpack_require__(/*! ./gostASN1 */ "./node_modules/node-gost-crypto/lib/gostASN1.js");
__webpack_require__(/*! ./gostCMS */ "./node_modules/node-gost-crypto/lib/gostCMS.js");
__webpack_require__(/*! ./gostCert */ "./node_modules/node-gost-crypto/lib/gostCert.js");
__webpack_require__(/*! ./gostCipher */ "./node_modules/node-gost-crypto/lib/gostCipher.js");
__webpack_require__(/*! ./gostDigest */ "./node_modules/node-gost-crypto/lib/gostDigest.js");
__webpack_require__(/*! ./gostKeys */ "./node_modules/node-gost-crypto/lib/gostKeys.js");
__webpack_require__(/*! ./gostRandom */ "./node_modules/node-gost-crypto/lib/gostRandom.js");
__webpack_require__(/*! ./gostSign */ "./node_modules/node-gost-crypto/lib/gostSign.js");

module.exports = {
    gostCrypto,
    gostEngine,
};


/***/ }),

/***/ "./node_modules/qrcode-reader/src/alignpat.js":
/*!****************************************************!*\
  !*** ./node_modules/qrcode-reader/src/alignpat.js ***!
  \****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   AlignmentPatternFinder: () => (/* binding */ AlignmentPatternFinder),
/* harmony export */   "default": () => (/* binding */ AlignmentPattern)
/* harmony export */ });
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


function AlignmentPattern(posX, posY,  estimatedModuleSize) {
  this.x = posX;
  this.y = posY;
  this.count = 1;
  this.estimatedModuleSize = estimatedModuleSize;
}

Object.defineProperty(AlignmentPattern.prototype, "X", {
  get: function() {
    return Math.floor(this.x);
  }
});

Object.defineProperty(AlignmentPattern.prototype, "Y", {
  get: function() {
    return Math.floor(this.y);
  }
});

AlignmentPattern.prototype.incrementCount = function() {
  this.count++;
};

AlignmentPattern.prototype.aboutEquals = function(moduleSize,  i,  j) {
  if (Math.abs(i - this.y) <= moduleSize && Math.abs(j - this.x) <= moduleSize) {
    var moduleSizeDiff = Math.abs(moduleSize - this.estimatedModuleSize);
    return moduleSizeDiff <= 1.0 || moduleSizeDiff / this.estimatedModuleSize <= 1.0;
  }
  return false;
};

function AlignmentPatternFinder(image,  startX,  startY,  width,  height,  moduleSize,  resultPointCallback) {
  this.image = image;
  this.possibleCenters = [];
  this.startX = startX;
  this.startY = startY;
  this.width = width;
  this.height = height;
  this.moduleSize = moduleSize;
  this.crossCheckStateCount = [0, 0, 0];
  this.resultPointCallback = resultPointCallback;
}

AlignmentPatternFinder.prototype.centerFromEnd = function(stateCount,  end) {
  return  (end - stateCount[2]) - stateCount[1] / 2.0;
};

AlignmentPatternFinder.prototype.foundPatternCross = function(stateCount) {
  var moduleSize = this.moduleSize;
  var maxVariance = moduleSize / 2.0;
  for (var i = 0; i < 3; i++) {
    if (Math.abs(moduleSize - stateCount[i]) >= maxVariance) {
      return false;
    }
  }
  return true;
};

AlignmentPatternFinder.prototype.crossCheckVertical = function(startI,  centerJ,  maxCount,  originalStateCountTotal) {
  var image = this.image;

  var maxI = image.height;
  var stateCount = this.crossCheckStateCount;
  stateCount[0] = 0;
  stateCount[1] = 0;
  stateCount[2] = 0;

  // Start counting up from center
  var i = startI;
  while (i >= 0 && image.data[centerJ + i * image.width] && stateCount[1] <= maxCount) {
    stateCount[1]++;
    i--;
  }
  // If already too many modules in this state or ran off the edge:
  if (i < 0 || stateCount[1] > maxCount) {
    return NaN;
  }
  while (i >= 0 && !image.data[centerJ + i * image.width] && stateCount[0] <= maxCount) {
    stateCount[0]++;
    i--;
  }
  if (stateCount[0] > maxCount) {
    return NaN;
  }

  // Now also count down from center
  i = startI + 1;
  while (i < maxI && image.data[centerJ + i * image.width] && stateCount[1] <= maxCount) {
    stateCount[1]++;
    i++;
  }
  if (i == maxI || stateCount[1] > maxCount) {
    return NaN;
  }
  while (i < maxI && !image.data[centerJ + i * image.width] && stateCount[2] <= maxCount) {
    stateCount[2]++;
    i++;
  }
  if (stateCount[2] > maxCount) {
    return NaN;
  }

  var stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
  if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {
    return NaN;
  }

  return this.foundPatternCross(stateCount) ? this.centerFromEnd(stateCount, i) : NaN;
};

AlignmentPatternFinder.prototype.handlePossibleCenter = function(stateCount,  i,  j) {
  var stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
  var centerJ = this.centerFromEnd(stateCount, j);
  var centerI = this.crossCheckVertical(i, Math.floor(centerJ), 2 * stateCount[1], stateCountTotal);
  if (!isNaN(centerI)) {
    var estimatedModuleSize = (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0;
    var max = this.possibleCenters.length;
    for (var index = 0; index < max; index++) {
      var center =  this.possibleCenters[index];
      // Look for about the same center and module size:
      if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {
        return new AlignmentPattern(centerJ, centerI, estimatedModuleSize);
      }
    }
    // Hadn't found this before; save it
    var point = new AlignmentPattern(centerJ, centerI, estimatedModuleSize);
    this.possibleCenters.push(point);
    if (this.resultPointCallback != null) {
      this.resultPointCallback.foundPossibleResultPoint(point);
    }
  }
  return null;
};

AlignmentPatternFinder.prototype.find = function() {
  var image = this.image;
  var startX = this.startX;
  var height = this.height;
  var maxJ = startX + this.width;
  var middleI = this.startY + (height >> 1);
  // We are looking for black/white/black modules in 1:1:1 ratio;
  // this tracks the number of black/white/black modules seen so far
  var stateCount = [0, 0, 0];
  for (var iGen = 0; iGen < height; iGen++) {
    // Search from middle outwards
    var i = middleI + ((iGen & 0x01) == 0 ? ((iGen + 1) >> 1) : -((iGen + 1) >> 1));
    stateCount[0] = 0;
    stateCount[1] = 0;
    stateCount[2] = 0;
    var j = startX;
    // Burn off leading white pixels before anything else; if we start in the middle of
    // a white run, it doesn't make sense to count its length, since we don't know if the
    // white run continued to the left of the start point
    while (j < maxJ && !image.data[j + image.width * i]) {
      j++;
    }
    var currentState = 0;
    while (j < maxJ) {
      if (image.data[j + i * image.width]) {
        // Black pixel
        if (currentState == 1) {
          // Counting black pixels
          stateCount[currentState]++;
        } else {
          // Counting white pixels
          if (currentState == 2) {
            // A winner?
            if (this.foundPatternCross(stateCount)) {
              // Yes
              var confirmed = this.handlePossibleCenter(stateCount, i, j);
              if (confirmed != null) {
                return confirmed;
              }
            }
            stateCount[0] = stateCount[2];
            stateCount[1] = 1;
            stateCount[2] = 0;
            currentState = 1;
          } else {
            stateCount[++currentState]++;
          }
        }
      } else {
        // White pixel
        if (currentState == 1) {
          // Counting black pixels
          currentState++;
        }
        stateCount[currentState]++;
      }
      j++;
    }
    if (this.foundPatternCross(stateCount)) {
      var confirmed = this.handlePossibleCenter(stateCount, i, maxJ);
      if (confirmed != null) {
        return confirmed;
      }
    }
  }

  // Hmm, nothing we saw was observed and confirmed twice. If we had
  // any guess at all, return it.
  if (!(this.possibleCenters.length == 0)) {
    return  this.possibleCenters[0];
  }

  throw "Couldn't find enough alignment patterns";
};


/***/ }),

/***/ "./node_modules/qrcode-reader/src/bitmat.js":
/*!**************************************************!*\
  !*** ./node_modules/qrcode-reader/src/bitmat.js ***!
  \**************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ BitMatrix)
/* harmony export */ });
/* harmony import */ var _qrcode__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./qrcode */ "./node_modules/qrcode-reader/src/qrcode.js");
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/



function BitMatrix(width,  height) {
  if (!height)
    height = width;
  if (width < 1 || height < 1) {
    throw "Both dimensions must be greater than 0";
  }
  this.width = width;
  this.height = height;
  var rowSize = width >> 5;
  if ((width & 0x1f) != 0) {
    rowSize++;
  }
  this.rowSize = rowSize;
  this.bits = new Array(rowSize * height);
  for (var i = 0; i < this.bits.length; i++)
    this.bits[i] = 0;
}

Object.defineProperty(BitMatrix.prototype, "Dimension", {
  get: function() {
    if (this.width != this.height) {
      throw "Can't call getDimension() on a non-square matrix";
    }
    return this.width;
  }
});

BitMatrix.prototype.get_Renamed = function(x, y) {
  var offset = y * this.rowSize + (x >> 5);
  return (((0,_qrcode__WEBPACK_IMPORTED_MODULE_0__.URShift)(this.bits[offset], (x & 0x1f))) & 1) != 0;
};

BitMatrix.prototype.set_Renamed = function(x, y) {
  var offset = y * this.rowSize + (x >> 5);
  this.bits[offset] |= 1 << (x & 0x1f);
};

BitMatrix.prototype.flip = function(x, y) {
  var offset = y * this.rowSize + (x >> 5);
  this.bits[offset] ^= 1 << (x & 0x1f);
};

BitMatrix.prototype.clear = function() {
  var max = this.bits.length;
  for (var i = 0; i < max; i++) {
    this.bits[i] = 0;
  }
};

BitMatrix.prototype.setRegion = function(left, top, width, height) {
  if (top < 0 || left < 0) {
    throw "Left and top must be nonnegative";
  }
  if (height < 1 || width < 1) {
    throw "Height and width must be at least 1";
  }
  var right = left + width;
  var bottom = top + height;
  if (bottom > this.height || right > this.width) {
    throw "The region must fit inside the matrix";
  }
  for (var y = top; y < bottom; y++) {
    var offset = y * this.rowSize;
    for (var x = left; x < right; x++) {
      this.bits[offset + (x >> 5)] |= 1 << (x & 0x1f);
    }
  }
};


/***/ }),

/***/ "./node_modules/qrcode-reader/src/bmparser.js":
/*!****************************************************!*\
  !*** ./node_modules/qrcode-reader/src/bmparser.js ***!
  \****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ BitMatrixParser)
/* harmony export */ });
/* harmony import */ var _formatinf__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./formatinf */ "./node_modules/qrcode-reader/src/formatinf.js");
/* harmony import */ var _version__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./version */ "./node_modules/qrcode-reader/src/version.js");
/* harmony import */ var _datamask__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./datamask */ "./node_modules/qrcode-reader/src/datamask.js");
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/





function BitMatrixParser(bitMatrix) {
  var dimension = bitMatrix.Dimension;
  if (dimension < 21 || (dimension & 0x03) != 1) {
    throw "Error BitMatrixParser";
  }
  this.bitMatrix = bitMatrix;
  this.parsedVersion = null;
  this.parsedFormatInfo = null;
}

BitMatrixParser.prototype.copyBit = function(i,  j,  versionBits) {
  return this.bitMatrix.get_Renamed(i, j) ? (versionBits << 1) | 0x1 : versionBits << 1;
};

BitMatrixParser.prototype.readFormatInformation = function() {
  if (this.parsedFormatInfo != null) {
    return this.parsedFormatInfo;
  }

  // Read top-left format info bits
  var formatInfoBits = 0;
  for (var i = 0; i < 6; i++) {
    formatInfoBits = this.copyBit(i, 8, formatInfoBits);
  }
  // .. and skip a bit in the timing pattern ...
  formatInfoBits = this.copyBit(7, 8, formatInfoBits);
  formatInfoBits = this.copyBit(8, 8, formatInfoBits);
  formatInfoBits = this.copyBit(8, 7, formatInfoBits);
  // .. and skip a bit in the timing pattern ...
  for (var j = 5; j >= 0; j--) {
    formatInfoBits = this.copyBit(8, j, formatInfoBits);
  }

  this.parsedFormatInfo = _formatinf__WEBPACK_IMPORTED_MODULE_0__["default"].decodeFormatInformation(formatInfoBits);
  if (this.parsedFormatInfo != null) {
    return this.parsedFormatInfo;
  }

  // Hmm, failed. Try the top-right/bottom-left pattern
  var dimension = this.bitMatrix.Dimension;
  formatInfoBits = 0;
  var iMin = dimension - 8;
  for (var i = dimension - 1; i >= iMin; i--) {
    formatInfoBits = this.copyBit(i, 8, formatInfoBits);
  }
  for (var j = dimension - 7; j < dimension; j++) {
    formatInfoBits = this.copyBit(8, j, formatInfoBits);
  }

  this.parsedFormatInfo = _formatinf__WEBPACK_IMPORTED_MODULE_0__["default"].decodeFormatInformation(formatInfoBits);
  if (this.parsedFormatInfo != null) {
    return this.parsedFormatInfo;
  }
  throw "Error readFormatInformation";
};

BitMatrixParser.prototype.readVersion = function() {
  if (this.parsedVersion != null) {
    return this.parsedVersion;
  }

  var dimension = this.bitMatrix.Dimension;

  var provisionalVersion = (dimension - 17) >> 2;
  if (provisionalVersion <= 6) {
    return _version__WEBPACK_IMPORTED_MODULE_1__["default"].getVersionForNumber(provisionalVersion);
  }

  // Read top-right version info: 3 wide by 6 tall
  var versionBits = 0;
  var ijMin = dimension - 11;
  for (var j = 5; j >= 0; j--) {
    for (var i = dimension - 9; i >= ijMin; i--) {
      versionBits = this.copyBit(i, j, versionBits);
    }
  }

  this.parsedVersion = _version__WEBPACK_IMPORTED_MODULE_1__["default"].decodeVersionInformation(versionBits);
  if (this.parsedVersion != null && this.parsedVersion.DimensionForVersion == dimension) {
    return this.parsedVersion;
  }

  // Hmm, failed. Try bottom left: 6 wide by 3 tall
  versionBits = 0;
  for (var i = 5; i >= 0; i--) {
    for (var j = dimension - 9; j >= ijMin; j--) {
      versionBits = this.copyBit(i, j, versionBits);
    }
  }

  this.parsedVersion = _version__WEBPACK_IMPORTED_MODULE_1__["default"].decodeVersionInformation(versionBits);
  if (this.parsedVersion != null && this.parsedVersion.DimensionForVersion == dimension) {
    return this.parsedVersion;
  }
  throw "Error readVersion";
};

BitMatrixParser.prototype.readCodewords = function() {
  var formatInfo = this.readFormatInformation();
  var version = this.readVersion();

  // Get the data mask for the format used in this QR Code. This will exclude
  // some bits from reading as we wind through the bit matrix.
  var dataMask = _datamask__WEBPACK_IMPORTED_MODULE_2__["default"].forReference(formatInfo.dataMask);
  var dimension = this.bitMatrix.Dimension;
  dataMask.unmaskBitMatrix(this.bitMatrix, dimension);

  var functionPattern = version.buildFunctionPattern();

  var readingUp = true;
  var result = new Array(version.totalCodewords);
  var resultOffset = 0;
  var currentByte = 0;
  var bitsRead = 0;
  // Read columns in pairs, from right to left
  for (var j = dimension - 1; j > 0; j -= 2) {
    if (j == 6) {
      // Skip whole column with vertical alignment pattern;
      // saves time and makes the other code proceed more cleanly
      j--;
    }
    // Read alternatingly from bottom to top then top to bottom
    for (var count = 0; count < dimension; count++) {
      var i = readingUp ? dimension - 1 - count : count;
      for (var col = 0; col < 2; col++) {
        // Ignore bits covered by the function pattern
        if (!functionPattern.get_Renamed(j - col, i)) {
          // Read a bit
          bitsRead++;
          currentByte <<= 1;
          if (this.bitMatrix.get_Renamed(j - col, i)) {
            currentByte |= 1;
          }
          // If we've made a whole byte, save it off
          if (bitsRead == 8) {
            result[resultOffset++] =  currentByte;
            bitsRead = 0;
            currentByte = 0;
          }
        }
      }
    }
    readingUp ^= true; // readingUp = !readingUp; // switch directions
  }
  if (resultOffset != version.totalCodewords) {
    throw "Error readCodewords";
  }
  return result;
};


/***/ }),

/***/ "./node_modules/qrcode-reader/src/datablock.js":
/*!*****************************************************!*\
  !*** ./node_modules/qrcode-reader/src/datablock.js ***!
  \*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ DataBlock)
/* harmony export */ });
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


function DataBlock(numDataCodewords,  codewords) {
  this.numDataCodewords = numDataCodewords;
  this.codewords = codewords;
}

DataBlock.getDataBlocks = function(rawCodewords,  version,  ecLevel) {

  if (rawCodewords.length != version.totalCodewords) {
    throw "ArgumentException";
  }

  // Figure out the number and size of data blocks used by this version and
  // error correction level
  var ecBlocks = version.getECBlocksForLevel(ecLevel);

  // First count the total number of data blocks
  var totalBlocks = 0;
  var ecBlockArray = ecBlocks.getECBlocks();
  for (var i = 0; i < ecBlockArray.length; i++) {
    totalBlocks += ecBlockArray[i].count;
  }

  // Now establish DataBlocks of the appropriate size and number of data codewords
  var result = new Array(totalBlocks);
  var numResultBlocks = 0;
  for (var j = 0; j < ecBlockArray.length; j++) {
    var ecBlock = ecBlockArray[j];
    for (var i = 0; i < ecBlock.count; i++) {
      var numDataCodewords = ecBlock.dataCodewords;
      var numBlockCodewords = ecBlocks.ecCodewordsPerBlock + numDataCodewords;
      result[numResultBlocks++] = new DataBlock(numDataCodewords, new Array(numBlockCodewords));
    }
  }

  // All blocks have the same amount of data, except that the last n
  // (where n may be 0) have 1 more byte. Figure out where these start.
  var shorterBlocksTotalCodewords = result[0].codewords.length;
  var longerBlocksStartAt = result.length - 1;
  while (longerBlocksStartAt >= 0) {
    var numCodewords = result[longerBlocksStartAt].codewords.length;
    if (numCodewords == shorterBlocksTotalCodewords) {
      break;
    }
    longerBlocksStartAt--;
  }
  longerBlocksStartAt++;

  var shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.ecCodewordsPerBlock;
  // The last elements of result may be 1 element longer;
  // first fill out as many elements as all of them have
  var rawCodewordsOffset = 0;
  for (var i = 0; i < shorterBlocksNumDataCodewords; i++) {
    for (var j = 0; j < numResultBlocks; j++) {
      result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];
    }
  }
  // Fill out the last data block in the longer ones
  for (var j = longerBlocksStartAt; j < numResultBlocks; j++) {
    result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++];
  }
  // Now add in error correction blocks
  var max = result[0].codewords.length;
  for (var i = shorterBlocksNumDataCodewords; i < max; i++) {
    for (var j = 0; j < numResultBlocks; j++) {
      var iOffset = j < longerBlocksStartAt ? i : i + 1;
      result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];
    }
  }
  return result;
};


/***/ }),

/***/ "./node_modules/qrcode-reader/src/databr.js":
/*!**************************************************!*\
  !*** ./node_modules/qrcode-reader/src/databr.js ***!
  \**************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ QRCodeDataBlockReader)
/* harmony export */ });
/* harmony import */ var _qrcode__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./qrcode */ "./node_modules/qrcode-reader/src/qrcode.js");
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/



function QRCodeDataBlockReader(blocks,  version,  numErrorCorrectionCode) {
  this.blockPointer = 0;
  this.bitPointer = 7;
  this.dataLength = 0;
  this.blocks = blocks;
  this.numErrorCorrectionCode = numErrorCorrectionCode;
  if (version <= 9)
    this.dataLengthMode = 0;
  else if (version >= 10 && version <= 26)
    this.dataLengthMode = 1;
  else if (version >= 27 && version <= 40)
    this.dataLengthMode = 2;
}

QRCodeDataBlockReader.prototype.getNextBits = function(numBits) {
  var bits = 0;
  if (numBits < this.bitPointer + 1) {
    // next word fits into current data block
    var mask = 0;
    for (var i = 0; i < numBits; i++) {
      mask += (1 << i);
    }
    mask <<= (this.bitPointer - numBits + 1);

    bits = (this.blocks[this.blockPointer] & mask) >> (this.bitPointer - numBits + 1);
    this.bitPointer -= numBits;
    return bits;
  } else if (numBits < this.bitPointer + 1 + 8) {
    // next word crosses 2 data blocks
    var mask1 = 0;
    for (var i = 0; i < this.bitPointer + 1; i++) {
      mask1 += (1 << i);
    }
    bits = (this.blocks[this.blockPointer] & mask1) << (numBits - (this.bitPointer + 1));
    this.blockPointer++;
    bits += ((this.blocks[this.blockPointer]) >> (8 - (numBits - (this.bitPointer + 1))));

    this.bitPointer = this.bitPointer - numBits % 8;
    if (this.bitPointer < 0) {
      this.bitPointer = 8 + this.bitPointer;
    }
    return bits;
  } else if (numBits < this.bitPointer + 1 + 16) {
    // next word crosses 3 data blocks
    var mask1 = 0; // mask of first block
    var mask3 = 0; // mask of 3rd block
    //bitPointer + 1 : number of bits of the 1st block
    //8 : number of the 2nd block (note that use already 8bits because next word uses 3 data blocks)
    //numBits - (bitPointer + 1 + 8) : number of bits of the 3rd block
    for (var i = 0; i < this.bitPointer + 1; i++) {
      mask1 += (1 << i);
    }
    var bitsFirstBlock = (this.blocks[this.blockPointer] & mask1) << (numBits - (this.bitPointer + 1));
    this.blockPointer++;

    var bitsSecondBlock = this.blocks[this.blockPointer] << (numBits - (this.bitPointer + 1 + 8));
    this.blockPointer++;

    for (var i = 0; i < numBits - (this.bitPointer + 1 + 8); i++) {
      mask3 += (1 << i);
    }
    mask3 <<= 8 - (numBits - (this.bitPointer + 1 + 8));
    var bitsThirdBlock = (this.blocks[this.blockPointer] & mask3) >> (8 - (numBits - (this.bitPointer + 1 + 8)));

    bits = bitsFirstBlock + bitsSecondBlock + bitsThirdBlock;
    this.bitPointer = this.bitPointer - (numBits - 8) % 8;
    if (this.bitPointer < 0) {
      this.bitPointer = 8 + this.bitPointer;
    }
    return bits;
  } else {
    return 0;
  }
};

QRCodeDataBlockReader.prototype.NextMode = function() {
  if ((this.blockPointer > this.blocks.length - this.numErrorCorrectionCode - 2))
    return 0;
  else
    return this.getNextBits(4);
};

QRCodeDataBlockReader.prototype.getDataLength = function(modeIndicator) {
  var index = 0;
  while (true) {
    if ((modeIndicator >> index) == 1)
      break;
    index++;
  }

  return this.getNextBits(_qrcode__WEBPACK_IMPORTED_MODULE_0__.qrcode.sizeOfDataLengthInfo[this.dataLengthMode][index]);
};

QRCodeDataBlockReader.prototype.getRomanAndFigureString = function(dataLength) {
  var length = dataLength;
  var intData = 0;
  var strData = "";
  var tableRomanAndFigure = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*', '+', '-', '.', '/', ':'];
  do {
    if (length > 1) {
      intData = this.getNextBits(11);
      var firstLetter = Math.floor(intData / 45);
      var secondLetter = intData % 45;
      strData += tableRomanAndFigure[firstLetter];
      strData += tableRomanAndFigure[secondLetter];
      length -= 2;
    } else if (length == 1) {
      intData = this.getNextBits(6);
      strData += tableRomanAndFigure[intData];
      length -= 1;
    }
  }
  while (length > 0);

  return strData;
};

QRCodeDataBlockReader.prototype.getFigureString = function(dataLength) {
  var length = dataLength;
  var intData = 0;
  var strData = "";
  do {
    if (length >= 3) {
      intData = this.getNextBits(10);
      if (intData < 100)
        strData += "0";
      if (intData < 10)
        strData += "0";
      length -= 3;
    } else if (length == 2) {
      intData = this.getNextBits(7);
      if (intData < 10)
        strData += "0";
      length -= 2;
    } else if (length == 1) {
      intData = this.getNextBits(4);
      length -= 1;
    }
    strData += intData;
  }
  while (length > 0);

  return strData;
};

QRCodeDataBlockReader.prototype.get8bitByteArray = function(dataLength) {
  var length = dataLength;
  var intData = 0;
  var output = [];

  do {
    intData = this.getNextBits(8);
    output.push(intData);
    length--;
  }
  while (length > 0);
  return output;
};

QRCodeDataBlockReader.prototype.getKanjiString = function(dataLength) {
  var length = dataLength;
  var intData = 0;
  var unicodeString = "";
  do {
    intData = this.getNextBits(13);
    var lowerByte = intData % 0xC0;
    var higherByte = intData / 0xC0;

    var tempWord = (higherByte << 8) + lowerByte;
    var shiftjisWord = 0;
    if (tempWord + 0x8140 <= 0x9FFC) {
      // between 8140 - 9FFC on Shift_JIS character set
      shiftjisWord = tempWord + 0x8140;
    } else {
      // between E040 - EBBF on Shift_JIS character set
      shiftjisWord = tempWord + 0xC140;
    }

    unicodeString += String.fromCharCode(shiftjisWord);
    length--;
  }
  while (length > 0);


  return unicodeString;
};

Object.defineProperty(QRCodeDataBlockReader.prototype, "DataByte", {
  get: function() {
    var output = [];
    var MODE_NUMBER = 1;
    var MODE_ROMAN_AND_NUMBER = 2;
    var MODE_8BIT_BYTE = 4;
    var MODE_KANJI = 8;
    do {
      var mode = this.NextMode();
      if (mode == 0) {
        if (output.length > 0)
          break;
        else
          throw "Empty data block";
      }
      //if (mode != 1 && mode != 2 && mode != 4 && mode != 8)
      //}
      if (mode != MODE_NUMBER && mode != MODE_ROMAN_AND_NUMBER && mode != MODE_8BIT_BYTE && mode != MODE_KANJI && mode != 7) {
        /*          canvas.println("Invalid mode: " + mode);
         mode = guessMode(mode);
         canvas.println("Guessed mode: " + mode); */
        throw "Invalid mode: " + mode + " in (block:" + this.blockPointer + " bit:" + this.bitPointer + ")";
      }
      var dataLength = this.getDataLength(mode);
      if (dataLength < 1)
        throw "Invalid data length: " + dataLength;
      switch (mode) {

      case MODE_NUMBER:
        var temp_str = this.getFigureString(dataLength);
        var ta = new Array(temp_str.length);
        for (var j = 0; j < temp_str.length; j++)
          ta[j] = temp_str.charCodeAt(j);
        output.push(ta);
        break;

      case MODE_ROMAN_AND_NUMBER:
        var temp_str = this.getRomanAndFigureString(dataLength);
        var ta = new Array(temp_str.length);
        for (var j = 0; j < temp_str.length; j++)
          ta[j] = temp_str.charCodeAt(j);
        output.push(ta);
        break;

      case MODE_8BIT_BYTE:
        var temp_sbyteArray3 = this.get8bitByteArray(dataLength);
        output.push(temp_sbyteArray3);
        break;

      case MODE_KANJI:
        var temp_str = this.getKanjiString(dataLength);
        output.push(temp_str);
        break;
      }
      //
    }
    while (true);
    return output;
  }
});


/***/ }),

/***/ "./node_modules/qrcode-reader/src/datamask.js":
/*!****************************************************!*\
  !*** ./node_modules/qrcode-reader/src/datamask.js ***!
  \****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _qrcode__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./qrcode */ "./node_modules/qrcode-reader/src/qrcode.js");
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/



var DataMask = {};

DataMask.forReference = function(reference) {
  if (reference < 0 || reference > 7) {
    throw "System.ArgumentException";
  }
  return DataMask.DATA_MASKS[reference];
};

function DataMask000() {
  this.unmaskBitMatrix = function(bits,  dimension) {
    for (var i = 0; i < dimension; i++) {
      for (var j = 0; j < dimension; j++) {
        if (this.isMasked(i, j)) {
          bits.flip(j, i);
        }
      }
    }
  };
  this.isMasked = function(i,  j) {
    return ((i + j) & 0x01) == 0;
  };
}

function DataMask001() {
  this.unmaskBitMatrix = function(bits,  dimension) {
    for (var i = 0; i < dimension; i++) {
      for (var j = 0; j < dimension; j++) {
        if (this.isMasked(i, j)) {
          bits.flip(j, i);
        }
      }
    }
  };
  this.isMasked = function(i,  j) {
    return (i & 0x01) == 0;
  };
}

function DataMask010() {
  this.unmaskBitMatrix = function(bits,  dimension) {
    for (var i = 0; i < dimension; i++) {
      for (var j = 0; j < dimension; j++) {
        if (this.isMasked(i, j)) {
          bits.flip(j, i);
        }
      }
    }
  };
  this.isMasked = function(i,  j) {
    return j % 3 == 0;
  };
}

function DataMask011() {
  this.unmaskBitMatrix = function(bits,  dimension) {
    for (var i = 0; i < dimension; i++) {
      for (var j = 0; j < dimension; j++) {
        if (this.isMasked(i, j)) {
          bits.flip(j, i);
        }
      }
    }
  };
  this.isMasked = function(i,  j) {
    return (i + j) % 3 == 0;
  };
}

function DataMask100() {
  this.unmaskBitMatrix = function(bits,  dimension) {
    for (var i = 0; i < dimension; i++) {
      for (var j = 0; j < dimension; j++) {
        if (this.isMasked(i, j)) {
          bits.flip(j, i);
        }
      }
    }
  };
  this.isMasked = function(i,  j) {
    return ((((0,_qrcode__WEBPACK_IMPORTED_MODULE_0__.URShift)(i, 1)) + (j / 3)) & 0x01) == 0;
  };
}

function DataMask101() {
  this.unmaskBitMatrix = function(bits,  dimension) {
    for (var i = 0; i < dimension; i++) {
      for (var j = 0; j < dimension; j++) {
        if (this.isMasked(i, j)) {
          bits.flip(j, i);
        }
      }
    }
  };
  this.isMasked = function(i,  j) {
    var temp = i * j;
    return (temp & 0x01) + (temp % 3) == 0;
  };
}

function DataMask110() {
  this.unmaskBitMatrix = function(bits,  dimension) {
    for (var i = 0; i < dimension; i++) {
      for (var j = 0; j < dimension; j++) {
        if (this.isMasked(i, j)) {
          bits.flip(j, i);
        }
      }
    }
  };
  this.isMasked = function(i,  j) {
    var temp = i * j;
    return (((temp & 0x01) + (temp % 3)) & 0x01) == 0;
  };
}
function DataMask111() {
  this.unmaskBitMatrix = function(bits,  dimension) {
    for (var i = 0; i < dimension; i++) {
      for (var j = 0; j < dimension; j++) {
        if (this.isMasked(i, j)) {
          bits.flip(j, i);
        }
      }
    }
  };
  this.isMasked = function(i,  j) {
    return ((((i + j) & 0x01) + ((i * j) % 3)) & 0x01) == 0;
  };
}

DataMask.DATA_MASKS = [new DataMask000(), new DataMask001(), new DataMask010(), new DataMask011(), new DataMask100(), new DataMask101(), new DataMask110(), new DataMask111()];

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DataMask);


/***/ }),

/***/ "./node_modules/qrcode-reader/src/decoder.js":
/*!***************************************************!*\
  !*** ./node_modules/qrcode-reader/src/decoder.js ***!
  \***************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _rsdecoder__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./rsdecoder */ "./node_modules/qrcode-reader/src/rsdecoder.js");
/* harmony import */ var _gf256__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./gf256 */ "./node_modules/qrcode-reader/src/gf256.js");
/* harmony import */ var _bmparser__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./bmparser */ "./node_modules/qrcode-reader/src/bmparser.js");
/* harmony import */ var _datablock__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./datablock */ "./node_modules/qrcode-reader/src/datablock.js");
/* harmony import */ var _databr__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./databr */ "./node_modules/qrcode-reader/src/databr.js");
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/







var Decoder = {};
Decoder.rsDecoder = new _rsdecoder__WEBPACK_IMPORTED_MODULE_0__["default"](_gf256__WEBPACK_IMPORTED_MODULE_1__["default"].QR_CODE_FIELD);

Decoder.correctErrors = function(codewordBytes,  numDataCodewords) {
  var numCodewords = codewordBytes.length;
  // First read into an array of ints
  var codewordsInts = new Array(numCodewords);
  for (var i = 0; i < numCodewords; i++) {
    codewordsInts[i] = codewordBytes[i] & 0xFF;
  }
  var numECCodewords = codewordBytes.length - numDataCodewords;
  try {
    Decoder.rsDecoder.decode(codewordsInts, numECCodewords);
  } catch (rse) {
    throw rse;
  }
  // Copy back into array of bytes -- only need to worry about the bytes that were data
  // We don't care about errors in the error-correction codewords
  for (var i = 0; i < numDataCodewords; i++) {
    codewordBytes[i] =  codewordsInts[i];
  }
};

Decoder.decode = function(bits) {
  var parser = new _bmparser__WEBPACK_IMPORTED_MODULE_2__["default"](bits);
  var version = parser.readVersion();
  var ecLevel = parser.readFormatInformation().errorCorrectionLevel;

  // Read codewords
  var codewords = parser.readCodewords();

  // Separate into data blocks
  var dataBlocks = _datablock__WEBPACK_IMPORTED_MODULE_3__["default"].getDataBlocks(codewords, version, ecLevel);

  // Count total number of data bytes
  var totalBytes = 0;
  for (var i = 0; i < dataBlocks.length; i++) {
    totalBytes += dataBlocks[i].numDataCodewords;
  }
  var resultBytes = new Array(totalBytes);
  var resultOffset = 0;

  // Error-correct and copy data blocks together into a stream of bytes
  for (var j = 0; j < dataBlocks.length; j++) {
    var dataBlock = dataBlocks[j];
    var codewordBytes = dataBlock.codewords;
    var numDataCodewords = dataBlock.numDataCodewords;
    Decoder.correctErrors(codewordBytes, numDataCodewords);
    for (var i = 0; i < numDataCodewords; i++) {
      resultBytes[resultOffset++] = codewordBytes[i];
    }
  }

  // Decode the contents of that stream of bytes
  var reader = new _databr__WEBPACK_IMPORTED_MODULE_4__["default"](resultBytes, version.versionNumber, ecLevel.bits);
  return reader;
};

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Decoder);


/***/ }),

/***/ "./node_modules/qrcode-reader/src/detector.js":
/*!****************************************************!*\
  !*** ./node_modules/qrcode-reader/src/detector.js ***!
  \****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ Detector)
/* harmony export */ });
/* harmony import */ var _version__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./version */ "./node_modules/qrcode-reader/src/version.js");
/* harmony import */ var _alignpat__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./alignpat */ "./node_modules/qrcode-reader/src/alignpat.js");
/* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./grid */ "./node_modules/qrcode-reader/src/grid.js");
/* harmony import */ var _findpat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./findpat */ "./node_modules/qrcode-reader/src/findpat.js");
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/






function PerspectiveTransform(a11,  a21,  a31,  a12,  a22,  a32,  a13,  a23,  a33) {
  this.a11 = a11;
  this.a12 = a12;
  this.a13 = a13;
  this.a21 = a21;
  this.a22 = a22;
  this.a23 = a23;
  this.a31 = a31;
  this.a32 = a32;
  this.a33 = a33;
}

PerspectiveTransform.prototype.transformPoints1 = function(points) {
  var max = points.length;
  var a11 = this.a11;
  var a12 = this.a12;
  var a13 = this.a13;
  var a21 = this.a21;
  var a22 = this.a22;
  var a23 = this.a23;
  var a31 = this.a31;
  var a32 = this.a32;
  var a33 = this.a33;
  for (var i = 0; i < max; i += 2) {
    var x = points[i];
    var y = points[i + 1];
    var denominator = a13 * x + a23 * y + a33;
    points[i] = (a11 * x + a21 * y + a31) / denominator;
    points[i + 1] = (a12 * x + a22 * y + a32) / denominator;
  }
};

PerspectiveTransform.prototype.transformPoints2 = function(xValues, yValues) {
  var n = xValues.length;
  for (var i = 0; i < n; i++) {
    var x = xValues[i];
    var y = yValues[i];
    var denominator = this.a13 * x + this.a23 * y + this.a33;
    xValues[i] = (this.a11 * x + this.a21 * y + this.a31) / denominator;
    yValues[i] = (this.a12 * x + this.a22 * y + this.a32) / denominator;
  }
};

PerspectiveTransform.prototype.buildAdjoint = function() {
  // Adjoint is the transpose of the cofactor matrix:
  return new PerspectiveTransform(this.a22 * this.a33 - this.a23 * this.a32, this.a23 * this.a31 - this.a21 * this.a33, this.a21 * this.a32 - this.a22 * this.a31, this.a13 * this.a32 - this.a12 * this.a33, this.a11 * this.a33 - this.a13 * this.a31, this.a12 * this.a31 - this.a11 * this.a32, this.a12 * this.a23 - this.a13 * this.a22, this.a13 * this.a21 - this.a11 * this.a23, this.a11 * this.a22 - this.a12 * this.a21);
};

PerspectiveTransform.prototype.times = function(other) {
  return new PerspectiveTransform(this.a11 * other.a11 + this.a21 * other.a12 + this.a31 * other.a13, this.a11 * other.a21 + this.a21 * other.a22 + this.a31 * other.a23, this.a11 * other.a31 + this.a21 * other.a32 + this.a31 * other.a33, this.a12 * other.a11 + this.a22 * other.a12 + this.a32 * other.a13, this.a12 * other.a21 + this.a22 * other.a22 + this.a32 * other.a23, this.a12 * other.a31 + this.a22 * other.a32 + this.a32 * other.a33, this.a13 * other.a11 + this.a23 * other.a12 + this.a33 * other.a13, this.a13 * other.a21 + this.a23 * other.a22 + this.a33 * other.a23, this.a13 * other.a31 + this.a23 * other.a32 + this.a33 * other.a33);
};

PerspectiveTransform.quadrilateralToQuadrilateral = function(x0,  y0,  x1,  y1,  x2,  y2,  x3,  y3,  x0p,  y0p,  x1p,  y1p,  x2p,  y2p,  x3p,  y3p) {

  var qToS = this.quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);
  var sToQ = this.squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
  return sToQ.times(qToS);
};

PerspectiveTransform.squareToQuadrilateral = function(x0,  y0,  x1,  y1,  x2,  y2,  x3,  y3) {
  var dy2 = y3 - y2;
  var dy3 = y0 - y1 + y2 - y3;
  if (dy2 == 0.0 && dy3 == 0.0) {
    return new PerspectiveTransform(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0, 0.0, 1.0);
  } else {
    var dx1 = x1 - x2;
    var dx2 = x3 - x2;
    var dx3 = x0 - x1 + x2 - x3;
    var dy1 = y1 - y2;
    var denominator = dx1 * dy2 - dx2 * dy1;
    var a13 = (dx3 * dy2 - dx2 * dy3) / denominator;
    var a23 = (dx1 * dy3 - dx3 * dy1) / denominator;
    return new PerspectiveTransform(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0, a13, a23, 1.0);
  }
};

PerspectiveTransform.quadrilateralToSquare = function(x0,  y0,  x1,  y1,  x2,  y2,  x3,  y3) {
  // Here, the adjoint serves as the inverse:
  return this.squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint();
};

function DetectorResult(bits,  points) {
  this.bits = bits;
  this.points = points;
}

function Detector(image) {
  this.image = image;
  this.resultPointCallback = null;
}

Detector.prototype.sizeOfBlackWhiteBlackRun = function(fromX,  fromY,  toX,  toY) {
  // Mild variant of Bresenham's algorithm;
  // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
  var steep = Math.abs(toY - fromY) > Math.abs(toX - fromX);
  if (steep) {
    var temp = fromX;
    fromX = fromY;
    fromY = temp;
    temp = toX;
    toX = toY;
    toY = temp;
  }

  var dx = Math.abs(toX - fromX);
  var dy = Math.abs(toY - fromY);
  var error = -dx >> 1;
  var ystep = fromY < toY ? 1 : -1;
  var xstep = fromX < toX ? 1 : -1;
  var state = 0; // In black pixels, looking for white, first or second time
  for (var x = fromX, y = fromY; x != toX; x += xstep) {

    var realX = steep ? y : x;
    var realY = steep ? x : y;
    if (state == 1) {
      // In white pixels, looking for black
      if (this.image.data[realX + realY * this.image.width]) {
        state++;
      }
    } else {
      if (!this.image.data[realX + realY * this.image.width]) {
        state++;
      }
    }

    if (state == 3) {
      // Found black, white, black, and stumbled back onto white; done
      var diffX = x - fromX;
      var diffY = y - fromY;
      return  Math.sqrt((diffX * diffX + diffY * diffY));
    }
    error += dy;
    if (error > 0) {
      if (y == toY) {
        break;
      }
      y += ystep;
      error -= dx;
    }
  }
  var diffX2 = toX - fromX;
  var diffY2 = toY - fromY;
  return  Math.sqrt((diffX2 * diffX2 + diffY2 * diffY2));
};

Detector.prototype.sizeOfBlackWhiteBlackRunBothWays = function(fromX,  fromY,  toX,  toY) {

  var result = this.sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY);

  // Now count other way -- don't run off image though of course
  var scale = 1.0;
  var otherToX = fromX - (toX - fromX);
  if (otherToX < 0) {
    scale =  fromX /  (fromX - otherToX);
    otherToX = 0;
  } else if (otherToX >= this.image.width) {
    scale =  (this.image.width - 1 - fromX) /  (otherToX - fromX);
    otherToX = this.image.width - 1;
  }
  var otherToY = Math.floor(fromY - (toY - fromY) * scale);

  scale = 1.0;
  if (otherToY < 0) {
    scale =  fromY /  (fromY - otherToY);
    otherToY = 0;
  } else if (otherToY >= this.image.height) {
    scale =  (this.image.height - 1 - fromY) /  (otherToY - fromY);
    otherToY = this.image.height - 1;
  }
  otherToX = Math.floor(fromX + (otherToX - fromX) * scale);

  result += this.sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY);
  return result - 1.0; // -1 because we counted the middle pixel twice
};

Detector.prototype.calculateModuleSizeOneWay = function(pattern,  otherPattern) {
  var moduleSizeEst1 = this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(pattern.X), Math.floor(pattern.Y), Math.floor(otherPattern.X), Math.floor(otherPattern.Y));
  var moduleSizeEst2 = this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(otherPattern.X), Math.floor(otherPattern.Y), Math.floor(pattern.X), Math.floor(pattern.Y));
  if (isNaN(moduleSizeEst1)) {
    return moduleSizeEst2 / 7.0;
  }
  if (isNaN(moduleSizeEst2)) {
    return moduleSizeEst1 / 7.0;
  }
  // Average them, and divide by 7 since we've counted the width of 3 black modules,
  // and 1 white and 1 black module on either side. Ergo, divide sum by 14.
  return (moduleSizeEst1 + moduleSizeEst2) / 14.0;
};

Detector.prototype.calculateModuleSize = function(topLeft,  topRight,  bottomLeft) {
  // Take the average
  return (this.calculateModuleSizeOneWay(topLeft, topRight) + this.calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0;
};

Detector.prototype.distance = function(pattern1,  pattern2) {
  var xDiff = pattern1.X - pattern2.X;
  var yDiff = pattern1.Y - pattern2.Y;
  return  Math.sqrt((xDiff * xDiff + yDiff * yDiff));
};

Detector.prototype.computeDimension = function(topLeft,  topRight,  bottomLeft,  moduleSize) {
  var tltrCentersDimension = Math.round(this.distance(topLeft, topRight) / moduleSize);
  var tlblCentersDimension = Math.round(this.distance(topLeft, bottomLeft) / moduleSize);
  var dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;
  switch (dimension & 0x03) {
  // mod 4
  case 0:
    dimension++;
    break;
  // 1? do nothing

  case 2:
    dimension--;
    break;

  case 3:
    throw "Error";
  }
  return dimension;
};

Detector.prototype.findAlignmentInRegion = function(overallEstModuleSize,  estAlignmentX,  estAlignmentY,  allowanceFactor) {
  // Look for an alignment pattern (3 modules in size) around where it
  // should be
  var allowance = Math.floor(allowanceFactor * overallEstModuleSize);
  var alignmentAreaLeftX = Math.max(0, estAlignmentX - allowance);
  var alignmentAreaRightX = Math.min(this.image.width - 1, estAlignmentX + allowance);
  if (alignmentAreaRightX - alignmentAreaLeftX < overallEstModuleSize * 3) {
    throw "Error";
  }

  var alignmentAreaTopY = Math.max(0, estAlignmentY - allowance);
  var alignmentAreaBottomY = Math.min(this.image.height - 1, estAlignmentY + allowance);

  var alignmentFinder = new _alignpat__WEBPACK_IMPORTED_MODULE_1__.AlignmentPatternFinder(this.image, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX - alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize, this.resultPointCallback);
  return alignmentFinder.find();
};

Detector.prototype.createTransform = function(topLeft,  topRight,  bottomLeft, alignmentPattern, dimension) {
  var dimMinusThree =  dimension - 3.5;
  var bottomRightX;
  var bottomRightY;
  var sourceBottomRightX;
  var sourceBottomRightY;
  if (alignmentPattern != null) {
    bottomRightX = alignmentPattern.X;
    bottomRightY = alignmentPattern.Y;
    sourceBottomRightX = sourceBottomRightY = dimMinusThree - 3.0;
  } else {
    // Don't have an alignment pattern, just make up the bottom-right point
    bottomRightX = (topRight.X - topLeft.X) + bottomLeft.X;
    bottomRightY = (topRight.Y - topLeft.Y) + bottomLeft.Y;
    sourceBottomRightX = sourceBottomRightY = dimMinusThree;
  }

  var transform = PerspectiveTransform.quadrilateralToQuadrilateral(3.5, 3.5, dimMinusThree, 3.5, sourceBottomRightX, sourceBottomRightY, 3.5, dimMinusThree, topLeft.X, topLeft.Y, topRight.X, topRight.Y, bottomRightX, bottomRightY, bottomLeft.X, bottomLeft.Y);

  return transform;
};

Detector.prototype.sampleGrid = function(image,  transform,  dimension) {

  var sampler = _grid__WEBPACK_IMPORTED_MODULE_2__["default"];
  return sampler.sampleGrid3(image, dimension, transform);
};

Detector.prototype.processFinderPatternInfo = function(info) {

  var topLeft = info.topLeft;
  var topRight = info.topRight;
  var bottomLeft = info.bottomLeft;

  var moduleSize = this.calculateModuleSize(topLeft, topRight, bottomLeft);
  if (moduleSize < 1.0) {
    throw "Error";
  }
  var dimension = this.computeDimension(topLeft, topRight, bottomLeft, moduleSize);
  var provisionalVersion = _version__WEBPACK_IMPORTED_MODULE_0__["default"].getProvisionalVersionForDimension(dimension);
  var modulesBetweenFPCenters = provisionalVersion.DimensionForVersion - 7;

  var alignmentPattern = null;
  // Anything above version 1 has an alignment pattern
  if (provisionalVersion.alignmentPatternCenters.length > 0) {

    // Guess where a "bottom right" finder pattern would have been
    var bottomRightX = topRight.X - topLeft.X + bottomLeft.X;
    var bottomRightY = topRight.Y - topLeft.Y + bottomLeft.Y;

    // Estimate that alignment pattern is closer by 3 modules
    // from "bottom right" to known top left location
    var correctionToTopLeft = 1.0 - 3.0 /  modulesBetweenFPCenters;
    var estAlignmentX = Math.floor(topLeft.X + correctionToTopLeft * (bottomRightX - topLeft.X));
    var estAlignmentY = Math.floor(topLeft.Y + correctionToTopLeft * (bottomRightY - topLeft.Y));

    // Kind of arbitrary -- expand search radius before giving up
    for (var i = 4; i <= 16; i <<= 1) {
      //try
      //{
      alignmentPattern = this.findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY,  i);
      break;
      //}
      //catch (re)
      //{
      // try next round
      //}
    }
    // If we didn't find alignment pattern... well try anyway without it
  }

  var transform = this.createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);

  var bits = this.sampleGrid(this.image, transform, dimension);

  var points;
  if (alignmentPattern == null) {
    points = [bottomLeft, topLeft, topRight];
  } else {
    points = [bottomLeft, topLeft, topRight, alignmentPattern];
  }
  return new DetectorResult(bits, points);
};

Detector.prototype.detect = function() {
  var info =  new _findpat__WEBPACK_IMPORTED_MODULE_3__.FinderPatternFinder().findFinderPattern(this.image);

  return this.processFinderPatternInfo(info);
};


/***/ }),

/***/ "./node_modules/qrcode-reader/src/errorlevel.js":
/*!******************************************************!*\
  !*** ./node_modules/qrcode-reader/src/errorlevel.js ***!
  \******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ ErrorCorrectionLevel)
/* harmony export */ });
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


function ErrorCorrectionLevel(ordinal,  bits, name) {
  this.ordinal_Renamed_Field = ordinal;
  this.bits = bits;
  this.name = name;
}

ErrorCorrectionLevel.prototype.ordinal = function() {
  return this.ordinal_Renamed_Field;
};

ErrorCorrectionLevel.forBits = function(bits) {
  if (bits < 0 || bits >= FOR_BITS.length) {
    throw "ArgumentException";
  }
  return FOR_BITS[bits];
};

var FOR_BITS = [
  new ErrorCorrectionLevel(1, 0x00, "M"),
  new ErrorCorrectionLevel(0, 0x01, "L"),
  new ErrorCorrectionLevel(3, 0x02, "H"),
  new ErrorCorrectionLevel(2, 0x03, "Q"),
];


/***/ }),

/***/ "./node_modules/qrcode-reader/src/findpat.js":
/*!***************************************************!*\
  !*** ./node_modules/qrcode-reader/src/findpat.js ***!
  \***************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   FinderPatternFinder: () => (/* binding */ FinderPatternFinder)
/* harmony export */ });
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

var MIN_SKIP = 3;
var MAX_MODULES = 57;
var INTEGER_MATH_SHIFT = 8;
var CENTER_QUORUM = 2;

function orderBestPatterns(patterns) {

  function distance(pattern1,  pattern2) {
    var xDiff = pattern1.X - pattern2.X;
    var yDiff = pattern1.Y - pattern2.Y;
    return  Math.sqrt((xDiff * xDiff + yDiff * yDiff));
  }

  /// <summary> Returns the z component of the cross product between vectors BC and BA.</summary>
  function crossProductZ(pointA,  pointB,  pointC) {
    var bX = pointB.x;
    var bY = pointB.y;
    return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX));
  }


  // Find distances between pattern centers
  var zeroOneDistance = distance(patterns[0], patterns[1]);
  var oneTwoDistance = distance(patterns[1], patterns[2]);
  var zeroTwoDistance = distance(patterns[0], patterns[2]);

  var pointA, pointB, pointC;
  // Assume one closest to other two is B; A and C will just be guesses at first
  if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) {
    pointB = patterns[0];
    pointA = patterns[1];
    pointC = patterns[2];
  } else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) {
    pointB = patterns[1];
    pointA = patterns[0];
    pointC = patterns[2];
  } else {
    pointB = patterns[2];
    pointA = patterns[0];
    pointC = patterns[1];
  }

  // Use cross product to figure out whether A and C are correct or flipped.
  // This asks whether BC x BA has a positive z component, which is the arrangement
  // we want for A, B, C. If it's negative, then we've got it flipped around and
  // should swap A and C.
  if (crossProductZ(pointA, pointB, pointC) < 0.0) {
    var temp = pointA;
    pointA = pointC;
    pointC = temp;
  }

  patterns[0] = pointA;
  patterns[1] = pointB;
  patterns[2] = pointC;
}


function FinderPattern(posX, posY,  estimatedModuleSize) {
  this.x = posX;
  this.y = posY;
  this.count = 1;
  this.estimatedModuleSize = estimatedModuleSize;
}

Object.defineProperty(FinderPattern.prototype, "X", {
  get: function() {
    return this.x;
  }
});

Object.defineProperty(FinderPattern.prototype, "Y", {
  get: function() {
    return this.y;
  }
});

FinderPattern.prototype.incrementCount = function() {
  this.count++;
};

FinderPattern.prototype.aboutEquals = function(moduleSize, i, j) {
  if (Math.abs(i - this.y) <= moduleSize && Math.abs(j - this.x) <= moduleSize) {
    var moduleSizeDiff = Math.abs(moduleSize - this.estimatedModuleSize);
    return moduleSizeDiff <= 1.0 || moduleSizeDiff / this.estimatedModuleSize <= 1.0;
  }
  return false;
};

function FinderPatternInfo(patternCenters) {
  this.bottomLeft = patternCenters[0];
  this.topLeft = patternCenters[1];
  this.topRight = patternCenters[2];
}

function FinderPatternFinder() {
  this.image = null;
  this.possibleCenters = [];
  this.hasSkipped = false;
  this.crossCheckStateCount = [0, 0, 0, 0, 0];
  this.resultPointCallback = null;
}

Object.defineProperty(FinderPatternFinder.prototype, "CrossCheckStateCount", {
  get: function() {
    this.crossCheckStateCount[0] = 0;
    this.crossCheckStateCount[1] = 0;
    this.crossCheckStateCount[2] = 0;
    this.crossCheckStateCount[3] = 0;
    this.crossCheckStateCount[4] = 0;
    return this.crossCheckStateCount;
  }
});

FinderPatternFinder.prototype.foundPatternCross = function(stateCount) {
  var totalModuleSize = 0;
  for (var i = 0; i < 5; i++) {
    var count = stateCount[i];
    if (count == 0) {
      return false;
    }
    totalModuleSize += count;
  }
  if (totalModuleSize < 7) {
    return false;
  }
  var moduleSize = Math.floor((totalModuleSize << INTEGER_MATH_SHIFT) / 7);
  var maxVariance = Math.floor(moduleSize / 2);
  // Allow less than 50% variance from 1-1-3-1-1 proportions
  return Math.abs(moduleSize - (stateCount[0] << INTEGER_MATH_SHIFT)) < maxVariance && Math.abs(moduleSize - (stateCount[1] << INTEGER_MATH_SHIFT)) < maxVariance && Math.abs(3 * moduleSize - (stateCount[2] << INTEGER_MATH_SHIFT)) < 3 * maxVariance && Math.abs(moduleSize - (stateCount[3] << INTEGER_MATH_SHIFT)) < maxVariance && Math.abs(moduleSize - (stateCount[4] << INTEGER_MATH_SHIFT)) < maxVariance;
};

FinderPatternFinder.prototype.centerFromEnd = function(stateCount,  end) {
  return  (end - stateCount[4] - stateCount[3]) - stateCount[2] / 2.0;
};

FinderPatternFinder.prototype.crossCheckVertical = function(startI,  centerJ,  maxCount,  originalStateCountTotal) {
  var image = this.image;

  var maxI = image.height;
  var stateCount = this.CrossCheckStateCount;

  // Start counting up from center
  var i = startI;
  while (i >= 0 && image.data[centerJ + i * image.width]) {
    stateCount[2]++;
    i--;
  }
  if (i < 0) {
    return NaN;
  }
  while (i >= 0 && !image.data[centerJ + i * image.width] && stateCount[1] <= maxCount) {
    stateCount[1]++;
    i--;
  }
  // If already too many modules in this state or ran off the edge:
  if (i < 0 || stateCount[1] > maxCount) {
    return NaN;
  }
  while (i >= 0 && image.data[centerJ + i * image.width] && stateCount[0] <= maxCount) {
    stateCount[0]++;
    i--;
  }
  if (stateCount[0] > maxCount) {
    return NaN;
  }

  // Now also count down from center
  i = startI + 1;
  while (i < maxI && image.data[centerJ + i * image.width]) {
    stateCount[2]++;
    i++;
  }
  if (i == maxI) {
    return NaN;
  }
  while (i < maxI && !image.data[centerJ + i * image.width] && stateCount[3] < maxCount) {
    stateCount[3]++;
    i++;
  }
  if (i == maxI || stateCount[3] >= maxCount) {
    return NaN;
  }
  while (i < maxI && image.data[centerJ + i * image.width] && stateCount[4] < maxCount) {
    stateCount[4]++;
    i++;
  }
  if (stateCount[4] >= maxCount) {
    return NaN;
  }

  // If we found a finder-pattern-like section, but its size is more than 40% different than
  // the original, assume it's a false positive
  var stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];
  if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {
    return NaN;
  }

  return this.foundPatternCross(stateCount) ? this.centerFromEnd(stateCount, i) : NaN;
};

FinderPatternFinder.prototype.crossCheckHorizontal = function(startJ,  centerI,  maxCount, originalStateCountTotal) {
  var image = this.image;

  var maxJ = image.width;
  var stateCount = this.CrossCheckStateCount;

  var j = startJ;
  while (j >= 0 && image.data[j + centerI * image.width]) {
    stateCount[2]++;
    j--;
  }
  if (j < 0) {
    return NaN;
  }
  while (j >= 0 && !image.data[j + centerI * image.width] && stateCount[1] <= maxCount) {
    stateCount[1]++;
    j--;
  }
  if (j < 0 || stateCount[1] > maxCount) {
    return NaN;
  }
  while (j >= 0 && image.data[j + centerI * image.width] && stateCount[0] <= maxCount) {
    stateCount[0]++;
    j--;
  }
  if (stateCount[0] > maxCount) {
    return NaN;
  }

  j = startJ + 1;
  while (j < maxJ && image.data[j + centerI * image.width]) {
    stateCount[2]++;
    j++;
  }
  if (j == maxJ) {
    return NaN;
  }
  while (j < maxJ && !image.data[j + centerI * image.width] && stateCount[3] < maxCount) {
    stateCount[3]++;
    j++;
  }
  if (j == maxJ || stateCount[3] >= maxCount) {
    return NaN;
  }
  while (j < maxJ && image.data[j + centerI * image.width] && stateCount[4] < maxCount) {
    stateCount[4]++;
    j++;
  }
  if (stateCount[4] >= maxCount) {
    return NaN;
  }

  // If we found a finder-pattern-like section, but its size is significantly different than
  // the original, assume it's a false positive
  var stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];
  if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) {
    return NaN;
  }

  return this.foundPatternCross(stateCount) ? this.centerFromEnd(stateCount, j) : NaN;
};

FinderPatternFinder.prototype.handlePossibleCenter = function(stateCount,  i,  j) {
  var stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];
  var centerJ = this.centerFromEnd(stateCount, j); //float
  var centerI = this.crossCheckVertical(i, Math.floor(centerJ), stateCount[2], stateCountTotal); //float
  if (!isNaN(centerI)) {
    // Re-cross check
    centerJ = this.crossCheckHorizontal(Math.floor(centerJ), Math.floor(centerI), stateCount[2], stateCountTotal);
    if (!isNaN(centerJ)) {
      var estimatedModuleSize =   stateCountTotal / 7.0;
      var found = false;
      var max = this.possibleCenters.length;
      for (var index = 0; index < max; index++) {
        var center = this.possibleCenters[index];
        // Look for about the same center and module size:
        if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {
          center.incrementCount();
          found = true;
          break;
        }
      }
      if (!found) {
        var point = new FinderPattern(centerJ, centerI, estimatedModuleSize);
        this.possibleCenters.push(point);
        if (this.resultPointCallback != null) {
          this.resultPointCallback.foundPossibleResultPoint(point);
        }
      }
      return true;
    }
  }
  return false;
};

FinderPatternFinder.prototype.selectBestPatterns = function() {

  var startSize = this.possibleCenters.length;
  if (startSize < 3) {
    // Couldn't find enough finder patterns
    throw "Couldn't find enough finder patterns:" + startSize + " patterns found";
  }

  // Filter outlier possibilities whose module size is too different
  if (startSize > 3) {
    // But we can only afford to do so if we have at least 4 possibilities to choose from
    var totalModuleSize = 0.0;
    var square = 0.0;
    for (var i = 0; i < startSize; i++) {
      var  centerValue = this.possibleCenters[i].estimatedModuleSize;
      totalModuleSize += centerValue;
      square += (centerValue * centerValue);
    }
    var average = totalModuleSize /  startSize;
    this.possibleCenters.sort(function(center1, center2) {
      var dA = Math.abs(center2.estimatedModuleSize - average);
      var dB = Math.abs(center1.estimatedModuleSize - average);
      if (dA < dB) {
        return (-1);
      } else if (dA == dB) {
        return 0;
      } else {
        return 1;
      }
    });

    var stdDev = Math.sqrt(square / startSize - average * average);
    var limit = Math.max(0.2 * average, stdDev);
    for (var i = this.possibleCenters - 1; i >= 0; i--) {
      var pattern =  this.possibleCenters[i];
      if (Math.abs(pattern.estimatedModuleSize - average) > limit) {
        this.possibleCenters.splice(i, 1);
      }
    }
  }

  if (this.possibleCenters.length > 3) {
    // Throw away all but those first size candidate points we found.
    this.possibleCenters.sort(function(a, b) {
      if (a.count > b.count) return -1;
      if (a.count < b.count) return 1;
      return 0;
    });
  }

  return [this.possibleCenters[0],  this.possibleCenters[1],  this.possibleCenters[2]];
};

FinderPatternFinder.prototype.findRowSkip = function() {
  var max = this.possibleCenters.length;
  if (max <= 1) {
    return 0;
  }
  var firstConfirmedCenter = null;
  for (var i = 0; i < max; i++) {
    var center =  this.possibleCenters[i];
    if (center.count >= CENTER_QUORUM) {
      if (firstConfirmedCenter == null) {
        firstConfirmedCenter = center;
      } else {
        // We have two confirmed centers
        // How far down can we skip before resuming looking for the next
        // pattern? In the worst case, only the difference between the
        // difference in the x / y coordinates of the two centers.
        // This is the case where you find top left last.
        this.hasSkipped = true;
        return Math.floor((Math.abs(firstConfirmedCenter.X - center.X) - Math.abs(firstConfirmedCenter.Y - center.Y)) / 2);
      }
    }
  }
  return 0;
};

FinderPatternFinder.prototype.haveMultiplyConfirmedCenters = function() {
  var confirmedCount = 0;
  var totalModuleSize = 0.0;
  var max = this.possibleCenters.length;
  for (var i = 0; i < max; i++) {
    var pattern =  this.possibleCenters[i];
    if (pattern.count >= CENTER_QUORUM) {
      confirmedCount++;
      totalModuleSize += pattern.estimatedModuleSize;
    }
  }
  if (confirmedCount < 3) {
    return false;
  }
  // OK, we have at least 3 confirmed centers, but, it's possible that one is a "false positive"
  // and that we need to keep looking. We detect this by asking if the estimated module sizes
  // vary too much. We arbitrarily say that when the total deviation from average exceeds
  // 5% of the total module size estimates, it's too much.
  var average = totalModuleSize / max;
  var totalDeviation = 0.0;
  for (var i = 0; i < max; i++) {
    pattern = this.possibleCenters[i];
    totalDeviation += Math.abs(pattern.estimatedModuleSize - average);
  }
  return totalDeviation <= 0.05 * totalModuleSize;
};

FinderPatternFinder.prototype.findFinderPattern = function(image) {
  var tryHarder = false;
  this.image = image;
  var maxI = image.height;
  var maxJ = image.width;
  var iSkip = Math.floor((3 * maxI) / (4 * MAX_MODULES));
  if (iSkip < MIN_SKIP || tryHarder) {
    iSkip = MIN_SKIP;
  }

  var done = false;
  var stateCount = new Array(5);
  for (var i = iSkip - 1; i < maxI && !done; i += iSkip) {
    // Get a row of black/white values
    stateCount[0] = 0;
    stateCount[1] = 0;
    stateCount[2] = 0;
    stateCount[3] = 0;
    stateCount[4] = 0;
    var currentState = 0;
    for (var j = 0; j < maxJ; j++) {
      if (image.data[j + i * image.width]) {
        // Black pixel
        if ((currentState & 1) == 1) {
          // Counting white pixels
          currentState++;
        }
        stateCount[currentState]++;
      } else {
        // White pixel
        if ((currentState & 1) == 0) {
          // Counting black pixels
          if (currentState == 4) {
            // A winner?
            if (this.foundPatternCross(stateCount)) {
              // Yes
              var confirmed = this.handlePossibleCenter(stateCount, i, j);
              if (confirmed) {
                // Start examining every other line. Checking each line turned out to be too
                // expensive and didn't improve performance.
                iSkip = 2;
                if (this.hasSkipped) {
                  done = this.haveMultiplyConfirmedCenters();
                } else {
                  var rowSkip = this.findRowSkip();
                  if (rowSkip > stateCount[2]) {
                    // Skip rows between row of lower confirmed center
                    // and top of presumed third confirmed center
                    // but back up a bit to get a full chance of detecting
                    // it, entire width of center of finder pattern

                    // Skip by rowSkip, but back off by stateCount[2] (size of last center
                    // of pattern we saw) to be conservative, and also back off by iSkip which
                    // is about to be re-added
                    i += rowSkip - stateCount[2] - iSkip;
                    j = maxJ - 1;
                  }
                }
              } else {
                // Advance to next black pixel
                do {
                  j++;
                } while (j < maxJ && !image.data[j + i * image.width]);
                j--; // back up to that last white pixel
              }
              // Clear state to start looking again
              currentState = 0;
              stateCount[0] = 0;
              stateCount[1] = 0;
              stateCount[2] = 0;
              stateCount[3] = 0;
              stateCount[4] = 0;
            } else {
              // No, shift counts back by two
              stateCount[0] = stateCount[2];
              stateCount[1] = stateCount[3];
              stateCount[2] = stateCount[4];
              stateCount[3] = 1;
              stateCount[4] = 0;
              currentState = 3;
            }
          } else {
            stateCount[++currentState]++;
          }
        } else {
          // Counting white pixels
          stateCount[currentState]++;
        }
      }
    }
    if (this.foundPatternCross(stateCount)) {
      var confirmed = this.handlePossibleCenter(stateCount, i, maxJ);
      if (confirmed) {
        iSkip = stateCount[0];
        if (this.hasSkipped) {
          // Found a third one
          done = this.haveMultiplyConfirmedCenters();
        }
      }
    }
  }

  var patternInfo = this.selectBestPatterns();
  orderBestPatterns(patternInfo);

  return new FinderPatternInfo(patternInfo);
};


/***/ }),

/***/ "./node_modules/qrcode-reader/src/formatinf.js":
/*!*****************************************************!*\
  !*** ./node_modules/qrcode-reader/src/formatinf.js ***!
  \*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ FormatInformation)
/* harmony export */ });
/* harmony import */ var _qrcode__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./qrcode */ "./node_modules/qrcode-reader/src/qrcode.js");
/* harmony import */ var _errorlevel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./errorlevel */ "./node_modules/qrcode-reader/src/errorlevel.js");
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/




var FORMAT_INFO_MASK_QR = 0x5412;
var FORMAT_INFO_DECODE_LOOKUP = [
  [0x5412, 0x00],
  [0x5125, 0x01],
  [0x5E7C, 0x02],
  [0x5B4B, 0x03],
  [0x45F9, 0x04],
  [0x40CE, 0x05],
  [0x4F97, 0x06],
  [0x4AA0, 0x07],
  [0x77C4, 0x08],
  [0x72F3, 0x09],
  [0x7DAA, 0x0A],
  [0x789D, 0x0B],
  [0x662F, 0x0C],
  [0x6318, 0x0D],
  [0x6C41, 0x0E],
  [0x6976, 0x0F],
  [0x1689, 0x10],
  [0x13BE, 0x11],
  [0x1CE7, 0x12],
  [0x19D0, 0x13],
  [0x0762, 0x14],
  [0x0255, 0x15],
  [0x0D0C, 0x16],
  [0x083B, 0x17],
  [0x355F, 0x18],
  [0x3068, 0x19],
  [0x3F31, 0x1A],
  [0x3A06, 0x1B],
  [0x24B4, 0x1C],
  [0x2183, 0x1D],
  [0x2EDA, 0x1E],
  [0x2BED, 0x1F],
];
var BITS_SET_IN_HALF_BYTE = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4];


function FormatInformation(formatInfo) {
  this.errorCorrectionLevel = _errorlevel__WEBPACK_IMPORTED_MODULE_1__["default"].forBits((formatInfo >> 3) & 0x03);
  this.dataMask =  (formatInfo & 0x07);
}

FormatInformation.prototype.GetHashCode = function() {
  return (this.errorCorrectionLevel.ordinal() << 3) |  this.dataMask;
};

FormatInformation.prototype.Equals = function(o) {
  var other =  o;
  return this.errorCorrectionLevel == other.errorCorrectionLevel && this.dataMask == other.dataMask;
};

FormatInformation.numBitsDiffering = function(a,  b) {
  a ^= b; // a now has a 1 bit exactly where its bit differs with b's
  // Count bits set quickly with a series of lookups:
  return BITS_SET_IN_HALF_BYTE[a & 0x0F] + BITS_SET_IN_HALF_BYTE[((0,_qrcode__WEBPACK_IMPORTED_MODULE_0__.URShift)(a, 4) & 0x0F)] + BITS_SET_IN_HALF_BYTE[((0,_qrcode__WEBPACK_IMPORTED_MODULE_0__.URShift)(a, 8) & 0x0F)] + BITS_SET_IN_HALF_BYTE[((0,_qrcode__WEBPACK_IMPORTED_MODULE_0__.URShift)(a, 12) & 0x0F)] + BITS_SET_IN_HALF_BYTE[((0,_qrcode__WEBPACK_IMPORTED_MODULE_0__.URShift)(a, 16) & 0x0F)] + BITS_SET_IN_HALF_BYTE[((0,_qrcode__WEBPACK_IMPORTED_MODULE_0__.URShift)(a, 20) & 0x0F)] + BITS_SET_IN_HALF_BYTE[((0,_qrcode__WEBPACK_IMPORTED_MODULE_0__.URShift)(a, 24) & 0x0F)] + BITS_SET_IN_HALF_BYTE[((0,_qrcode__WEBPACK_IMPORTED_MODULE_0__.URShift)(a, 28) & 0x0F)];
};

FormatInformation.decodeFormatInformation = function(maskedFormatInfo) {
  var formatInfo = FormatInformation.doDecodeFormatInformation(maskedFormatInfo);
  if (formatInfo != null) {
    return formatInfo;
  }
  // Should return null, but, some QR codes apparently
  // do not mask this info. Try again by actually masking the pattern
  // first
  return FormatInformation.doDecodeFormatInformation(maskedFormatInfo ^ FORMAT_INFO_MASK_QR);
};
FormatInformation.doDecodeFormatInformation = function(maskedFormatInfo) {
  // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing
  var bestDifference = 0xffffffff;
  var bestFormatInfo = 0;
  for (var i = 0; i < FORMAT_INFO_DECODE_LOOKUP.length; i++) {
    var decodeInfo = FORMAT_INFO_DECODE_LOOKUP[i];
    var targetInfo = decodeInfo[0];
    if (targetInfo == maskedFormatInfo) {
      // Found an exact match
      return new FormatInformation(decodeInfo[1]);
    }
    var bitsDifference = this.numBitsDiffering(maskedFormatInfo, targetInfo);
    if (bitsDifference < bestDifference) {
      bestFormatInfo = decodeInfo[1];
      bestDifference = bitsDifference;
    }
  }
  // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits
  // differing means we found a match
  if (bestDifference <= 3) {
    return new FormatInformation(bestFormatInfo);
  }
  return null;
};




/***/ }),

/***/ "./node_modules/qrcode-reader/src/gf256.js":
/*!*************************************************!*\
  !*** ./node_modules/qrcode-reader/src/gf256.js ***!
  \*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ GF256)
/* harmony export */ });
/* harmony import */ var _gf256poly__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./gf256poly */ "./node_modules/qrcode-reader/src/gf256poly.js");
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/



function GF256(primitive) {
  this.expTable = new Array(256);
  this.logTable = new Array(256);
  var x = 1;
  for (var i = 0; i < 256; i++) {
    this.expTable[i] = x;
    x <<= 1; // x = x * 2; we're assuming the generator alpha is 2
    if (x >= 0x100) {
      x ^= primitive;
    }
  }
  for (var i = 0; i < 255; i++) {
    this.logTable[this.expTable[i]] = i;
  }
  // logTable[0] == 0 but this should never be used
  var at0 = new Array(1); at0[0] = 0;
  this.zero = new _gf256poly__WEBPACK_IMPORTED_MODULE_0__["default"](this, new Array(at0));
  var at1 = new Array(1); at1[0] = 1;
  this.one = new _gf256poly__WEBPACK_IMPORTED_MODULE_0__["default"](this, new Array(at1));
}

Object.defineProperty(GF256.prototype, "Zero", {
  get: function() {
    return this.zero;
  }
});

Object.defineProperty(GF256.prototype, "One", {
  get: function() {
    return this.one;
  }
});

GF256.prototype.buildMonomial = function(degree,  coefficient) {
  if (degree < 0) {
    throw "System.ArgumentException";
  }
  if (coefficient == 0) {
    return this.zero;
  }
  var coefficients = new Array(degree + 1);
  for (var i = 0; i < coefficients.length; i++)coefficients[i] = 0;
  coefficients[0] = coefficient;
  return new _gf256poly__WEBPACK_IMPORTED_MODULE_0__["default"](this, coefficients);
};

GF256.prototype.exp = function(a) {
  return this.expTable[a];
};

GF256.prototype.log = function(a) {
  if (a == 0) {
    throw "System.ArgumentException";
  }
  return this.logTable[a];
};

GF256.prototype.inverse = function(a) {
  if (a == 0) {
    throw "System.ArithmeticException";
  }
  return this.expTable[255 - this.logTable[a]];
};

GF256.prototype.addOrSubtract = function(a,  b) {
  return a ^ b;
};

GF256.prototype.multiply = function(a,  b) {
  if (a == 0 || b == 0) {
    return 0;
  }
  if (a == 1) {
    return b;
  }
  if (b == 1) {
    return a;
  }
  return this.expTable[(this.logTable[a] + this.logTable[b]) % 255];
};

GF256.QR_CODE_FIELD = new GF256(0x011D);
GF256.DATA_MATRIX_FIELD = new GF256(0x012D);


/***/ }),

/***/ "./node_modules/qrcode-reader/src/gf256poly.js":
/*!*****************************************************!*\
  !*** ./node_modules/qrcode-reader/src/gf256poly.js ***!
  \*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ GF256Poly)
/* harmony export */ });
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

function GF256Poly(field,  coefficients) {
  if (coefficients == null || coefficients.length == 0) {
    throw "System.ArgumentException";
  }
  this.field = field;
  var coefficientsLength = coefficients.length;
  if (coefficientsLength > 1 && coefficients[0] == 0) {
    // Leading term must be non-zero for anything except the constant polynomial "0"
    var firstNonZero = 1;
    while (firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0) {
      firstNonZero++;
    }
    if (firstNonZero == coefficientsLength) {
      this.coefficients = field.Zero.coefficients;
    } else {
      this.coefficients = new Array(coefficientsLength - firstNonZero);
      for (var i = 0; i < this.coefficients.length; i++) this.coefficients[i] = 0;
      for (var ci = 0; ci < this.coefficients.length; ci++) this.coefficients[ci] = coefficients[firstNonZero + ci];
    }
  } else {
    this.coefficients = coefficients;
  }
}

Object.defineProperty(GF256Poly.prototype, "Zero", {
  get: function() {
    return this.coefficients[0] == 0;
  }
});

Object.defineProperty(GF256Poly.prototype, "Degree", {
  get: function() {
    return this.coefficients.length - 1;
  }
});

GF256Poly.prototype.getCoefficient = function(degree) {
  return this.coefficients[this.coefficients.length - 1 - degree];
};

GF256Poly.prototype.evaluateAt = function(a) {
  if (a == 0) {
    // Just return the x^0 coefficient
    return this.getCoefficient(0);
  }
  var size = this.coefficients.length;
  if (a == 1) {
    // Just the sum of the coefficients
    var result = 0;
    for (var i = 0; i < size; i++) {
      result = this.field.addOrSubtract(result, this.coefficients[i]);
    }
    return result;
  }
  var result2 = this.coefficients[0];
  for (var i = 1; i < size; i++) {
    result2 = this.field.addOrSubtract(this.field.multiply(a, result2), this.coefficients[i]);
  }
  return result2;
};

GF256Poly.prototype.addOrSubtract = function(other) {
  if (this.field != other.field) {
    throw "GF256Polys do not have same GF256 field";
  }
  if (this.Zero) {
    return other;
  }
  if (other.Zero) {
    return this;
  }

  var smallerCoefficients = this.coefficients;
  var largerCoefficients = other.coefficients;
  if (smallerCoefficients.length > largerCoefficients.length) {
    var temp = smallerCoefficients;
    smallerCoefficients = largerCoefficients;
    largerCoefficients = temp;
  }
  var sumDiff = new Array(largerCoefficients.length);
  var lengthDiff = largerCoefficients.length - smallerCoefficients.length;
  // Copy high-order terms only found in higher-degree polynomial's coefficients
  for (var ci = 0; ci < lengthDiff; ci++)sumDiff[ci] = largerCoefficients[ci];

  for (var i = lengthDiff; i < largerCoefficients.length; i++) {
    sumDiff[i] = this.field.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);
  }

  return new GF256Poly(this.field, sumDiff);
};

GF256Poly.prototype.multiply1 = function(other) {
  if (this.field != other.field) {
    throw "GF256Polys do not have same GF256 field";
  }
  if (this.Zero || other.Zero) {
    return this.field.Zero;
  }
  var aCoefficients = this.coefficients;
  var aLength = aCoefficients.length;
  var bCoefficients = other.coefficients;
  var bLength = bCoefficients.length;
  var product = new Array(aLength + bLength - 1);
  for (var i = 0; i < aLength; i++) {
    var aCoeff = aCoefficients[i];
    for (var j = 0; j < bLength; j++) {
      product[i + j] = this.field.addOrSubtract(product[i + j], this.field.multiply(aCoeff, bCoefficients[j]));
    }
  }
  return new GF256Poly(this.field, product);
};

GF256Poly.prototype.multiply2 = function(scalar) {
  if (scalar == 0) {
    return this.field.Zero;
  }
  if (scalar == 1) {
    return this;
  }
  var size = this.coefficients.length;
  var product = new Array(size);
  for (var i = 0; i < size; i++) {
    product[i] = this.field.multiply(this.coefficients[i], scalar);
  }
  return new GF256Poly(this.field, product);
};

GF256Poly.prototype.multiplyByMonomial = function(degree,  coefficient) {
  if (degree < 0) {
    throw "System.ArgumentException";
  }
  if (coefficient == 0) {
    return this.field.Zero;
  }
  var size = this.coefficients.length;
  var product = new Array(size + degree);
  for (var i = 0; i < product.length; i++)product[i] = 0;
  for (var i = 0; i < size; i++) {
    product[i] = this.field.multiply(this.coefficients[i], coefficient);
  }
  return new GF256Poly(this.field, product);
};

GF256Poly.prototype.divide = function(other) {
  if (this.field != other.field) {
    throw "GF256Polys do not have same GF256 field";
  }
  if (other.Zero) {
    throw "Divide by 0";
  }

  var quotient = this.field.Zero;
  var remainder = this;

  var denominatorLeadingTerm = other.getCoefficient(other.Degree);
  var inverseDenominatorLeadingTerm = this.field.inverse(denominatorLeadingTerm);

  while (remainder.Degree >= other.Degree && !remainder.Zero) {
    var degreeDifference = remainder.Degree - other.Degree;
    var scale = this.field.multiply(remainder.getCoefficient(remainder.Degree), inverseDenominatorLeadingTerm);
    var term = other.multiplyByMonomial(degreeDifference, scale);
    var iterationQuotient = this.field.buildMonomial(degreeDifference, scale);
    quotient = quotient.addOrSubtract(iterationQuotient);
    remainder = remainder.addOrSubtract(term);
  }

  return [quotient, remainder];
};


/***/ }),

/***/ "./node_modules/qrcode-reader/src/grid.js":
/*!************************************************!*\
  !*** ./node_modules/qrcode-reader/src/grid.js ***!
  \************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _bitmat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./bitmat */ "./node_modules/qrcode-reader/src/bitmat.js");
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/



var GridSampler = {};

GridSampler.checkAndNudgePoints = function(image,  points) {
  var width = image.width;
  var height = image.height;
  // Check and nudge points from start until we see some that are OK:
  var nudged = true;
  for (var offset = 0; offset < points.length && nudged; offset += 2) {
    var x = Math.floor(points[offset]);
    var y = Math.floor(points[offset + 1]);
    if (x < -1 || x > width || y < -1 || y > height) {
      throw "Error.checkAndNudgePoints ";
    }
    nudged = false;
    if (x == -1) {
      points[offset] = 0.0;
      nudged = true;
    } else if (x == width) {
      points[offset] = width - 1;
      nudged = true;
    }
    if (y == -1) {
      points[offset + 1] = 0.0;
      nudged = true;
    } else if (y == height) {
      points[offset + 1] = height - 1;
      nudged = true;
    }
  }
  // Check and nudge points from end:
  nudged = true;
  for (var offset = points.length - 2; offset >= 0 && nudged; offset -= 2) {
    var x = Math.floor(points[offset]);
    var y = Math.floor(points[offset + 1]);
    if (x < -1 || x > width || y < -1 || y > height) {
      throw "Error.checkAndNudgePoints ";
    }
    nudged = false;
    if (x == -1) {
      points[offset] = 0.0;
      nudged = true;
    } else if (x == width) {
      points[offset] = width - 1;
      nudged = true;
    }
    if (y == -1) {
      points[offset + 1] = 0.0;
      nudged = true;
    } else if (y == height) {
      points[offset + 1] = height - 1;
      nudged = true;
    }
  }
};



GridSampler.sampleGrid3 = function(image,  dimension,  transform) {
  var bits = new _bitmat__WEBPACK_IMPORTED_MODULE_0__["default"](dimension);
  var points = new Array(dimension << 1);
  for (var y = 0; y < dimension; y++) {
    var max = points.length;
    var iValue =  y + 0.5;
    for (var x = 0; x < max; x += 2) {
      points[x] =  (x >> 1) + 0.5;
      points[x + 1] = iValue;
    }
    transform.transformPoints1(points);
    // Quick check to see if points transformed to something inside the image
    // sufficient to check the endpoints
    GridSampler.checkAndNudgePoints(image, points);
    try {
      for (var x = 0; x < max; x += 2) {
        var bit = image.data[Math.floor(points[x]) + image.width * Math.floor(points[x + 1])];
        if (bit)
          bits.set_Renamed(x >> 1, y);
      }
    } catch (aioobe) {
      // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting
      // transform gets "twisted" such that it maps a straight line of points to a set of points
      // whose endpoints are in bounds, but others are not. There is probably some mathematical
      // way to detect this about the transformation that I don't know yet.
      // This results in an ugly runtime exception despite our clever checks above -- can't have
      // that. We could check each point's coordinates but that feels duplicative. We settle for
      // catching and wrapping ArrayIndexOutOfBoundsException.
      throw "Error.checkAndNudgePoints";
    }
  }
  return bits;
};

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (GridSampler);


/***/ }),

/***/ "./node_modules/qrcode-reader/src/index.js":
/*!*************************************************!*\
  !*** ./node_modules/qrcode-reader/src/index.js ***!
  \*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _qrcode__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./qrcode */ "./node_modules/qrcode-reader/src/qrcode.js");


/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_qrcode__WEBPACK_IMPORTED_MODULE_0__["default"]);


/***/ }),

/***/ "./node_modules/qrcode-reader/src/qrcode.js":
/*!**************************************************!*\
  !*** ./node_modules/qrcode-reader/src/qrcode.js ***!
  \**************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   URShift: () => (/* binding */ URShift),
/* harmony export */   "default": () => (/* binding */ QrCode),
/* harmony export */   qrcode: () => (/* binding */ qrcode)
/* harmony export */ });
/* harmony import */ var _detector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./detector */ "./node_modules/qrcode-reader/src/detector.js");
/* harmony import */ var _decoder__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./decoder */ "./node_modules/qrcode-reader/src/decoder.js");
/*
   Copyright 2011 Lazar Laszlo (lazarsoft@gmail.com, www.lazarsoft.info)

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/




var qrcode = {};
qrcode.sizeOfDataLengthInfo =  [[10, 9, 8, 8], [12, 11, 16, 10], [14, 13, 16, 12]];

function QrCode() {

  this.imagedata = null;
  this.width = 0;
  this.height = 0;
  this.qrCodeSymbol = null;
  this.debug = false;

  this.callback = null;
}


QrCode.prototype.decode = function(src, data) {

  var decode = (function() {

    try {
      this.error = undefined;
      this.result = this.process(this.imagedata);
    } catch (e) {
      this.error = e;
      this.result = undefined;
    }

    if (this.callback != null) {
      this.callback(this.error, this.result);
    }

    return this.result;

  }).bind(this);

  if (src != undefined && src.width != undefined) {
    /* decode from canvas canvas.context.getImageData */
    this.width = src.width;
    this.height = src.height;
    this.imagedata = {"data": data || src.data};
    this.imagedata.width = src.width;
    this.imagedata.height = src.height;

    decode();
  } else {
    if (typeof Image === "undefined") {
      throw new Error("This source format is not supported in your environment, you need to pass an image buffer with width and height (see https://github.com/edi9999/jsqrcode/blob/master/test/qrcode.js)");
    }
    /* decode from URL */

    var image = new Image();
    image.crossOrigin = "Anonymous";

    image.onload = (function() {

      var canvas_qr = document.createElement('canvas');
      var context = canvas_qr.getContext('2d');
      var canvas_out = document.getElementById("out-canvas");

      if (canvas_out != null) {

        var outctx = canvas_out.getContext('2d');
        outctx.clearRect(0, 0, 320, 240);
        outctx.drawImage(image, 0, 0, 320, 240);
      }

      canvas_qr.width = image.width;
      canvas_qr.height = image.height;
      context.drawImage(image, 0, 0);
      this.width = image.width;
      this.height = image.height;

      try {
        this.imagedata = context.getImageData(0, 0, image.width, image.height);
      } catch (e) {
        this.result = "Cross domain image reading not supported in your browser! Save it to your computer then drag and drop the file!";
        if (this.callback != null) return this.callback(null, this.result);
      }

      decode();

    }).bind(this);

    image.src = src;
  }
};

QrCode.prototype.decode_utf8 = function(s) {

  return decodeURIComponent(escape(s));
};

QrCode.prototype.process = function(imageData) {

  var start = new Date().getTime();

  var image = this.grayScaleToBitmap(this.grayscale(imageData));

  var detector = new _detector__WEBPACK_IMPORTED_MODULE_0__["default"](image);

  var qRCodeMatrix = detector.detect();

  /*for (var y = 0; y < qRCodeMatrix.bits.height; y++)
   {
   for (var x = 0; x < qRCodeMatrix.bits.width; x++)
   {
   var point = (x * 4*2) + (y*2 * imageData.width * 4);
   imageData.data[point] = qRCodeMatrix.bits.get_Renamed(x,y)?0:0;
   imageData.data[point+1] = qRCodeMatrix.bits.get_Renamed(x,y)?0:0;
   imageData.data[point+2] = qRCodeMatrix.bits.get_Renamed(x,y)?255:0;
   }
   }*/

  var reader = _decoder__WEBPACK_IMPORTED_MODULE_1__["default"].decode(qRCodeMatrix.bits);
  var data = reader.DataByte;
  var str = "";
  for (var i = 0; i < data.length; i++) {
    for (var j = 0; j < data[i].length; j++)
      str += String.fromCharCode(data[i][j]);
  }

  var end = new Date().getTime();
  var time = end - start;
  if (this.debug) {
    console.log('QR Code processing time (ms): ' + time);
  }

  return {result: this.decode_utf8(str), points: qRCodeMatrix.points};
};

QrCode.prototype.getPixel = function(imageData, x, y) {
  if (imageData.width < x) {
    throw "point error";
  }
  if (imageData.height < y) {
    throw "point error";
  }
  var point = (x * 4) + (y * imageData.width * 4);
  return (imageData.data[point] * 33 + imageData.data[point + 1] * 34 + imageData.data[point + 2] * 33) / 100;
};

QrCode.prototype.binarize = function(th) {
  var ret = new Array(this.width * this.height);
  for (var y = 0; y < this.height; y++) {
    for (var x = 0; x < this.width; x++) {
      var gray = this.getPixel(x, y);

      ret[x + y * this.width] = gray <= th;
    }
  }
  return ret;
};

QrCode.prototype.getMiddleBrightnessPerArea = function(imageData) {
  var numSqrtArea = 4;
  //obtain middle brightness((min + max) / 2) per area
  var areaWidth = Math.floor(imageData.width / numSqrtArea);
  var areaHeight = Math.floor(imageData.height / numSqrtArea);
  var minmax = new Array(numSqrtArea);
  for (var i = 0; i < numSqrtArea; i++) {
    minmax[i] = new Array(numSqrtArea);
    for (var i2 = 0; i2 < numSqrtArea; i2++) {
      minmax[i][i2] = [0, 0];
    }
  }
  for (var ay = 0; ay < numSqrtArea; ay++) {
    for (var ax = 0; ax < numSqrtArea; ax++) {
      minmax[ax][ay][0] = 0xFF;
      for (var dy = 0; dy < areaHeight; dy++) {
        for (var dx = 0; dx < areaWidth; dx++) {
          var target = imageData.data[areaWidth * ax + dx + (areaHeight * ay + dy) * imageData.width];
          if (target < minmax[ax][ay][0])
            minmax[ax][ay][0] = target;
          if (target > minmax[ax][ay][1])
            minmax[ax][ay][1] = target;
        }
      }
    }
  }
  var middle = new Array(numSqrtArea);
  for (var i3 = 0; i3 < numSqrtArea; i3++) {
    middle[i3] = new Array(numSqrtArea);
  }
  for (var ay = 0; ay < numSqrtArea; ay++) {
    for (var ax = 0; ax < numSqrtArea; ax++) {
      middle[ax][ay] = Math.floor((minmax[ax][ay][0] + minmax[ax][ay][1]) / 2);
    }
  }

  return middle;
};

QrCode.prototype.grayScaleToBitmap = function(grayScaleImageData) {
  var middle = this.getMiddleBrightnessPerArea(grayScaleImageData);
  var sqrtNumArea = middle.length;
  var areaWidth = Math.floor(grayScaleImageData.width / sqrtNumArea);
  var areaHeight = Math.floor(grayScaleImageData.height / sqrtNumArea);

  for (var ay = 0; ay < sqrtNumArea; ay++) {
    for (var ax = 0; ax < sqrtNumArea; ax++) {
      for (var dy = 0; dy < areaHeight; dy++) {
        for (var dx = 0; dx < areaWidth; dx++) {
          grayScaleImageData.data[areaWidth * ax + dx + (areaHeight * ay + dy) * grayScaleImageData.width] = (grayScaleImageData.data[areaWidth * ax + dx + (areaHeight * ay + dy) * grayScaleImageData.width] < middle[ax][ay]);
        }
      }
    }
  }
  return grayScaleImageData;
};

QrCode.prototype.grayscale = function(imageData) {
  var ret = new Array(imageData.width * imageData.height);

  for (var y = 0; y < imageData.height; y++) {
    for (var x = 0; x < imageData.width; x++) {
      var gray = this.getPixel(imageData, x, y);

      ret[x + y * imageData.width] = gray;
    }
  }

  return {
    height: imageData.height,
    width: imageData.width,
    data: ret
  };
};

function URShift(number,  bits) {
  if (number >= 0)
    return number >> bits;
  else
    return (number >> bits) + (2 << ~bits);
}


/***/ }),

/***/ "./node_modules/qrcode-reader/src/rsdecoder.js":
/*!*****************************************************!*\
  !*** ./node_modules/qrcode-reader/src/rsdecoder.js ***!
  \*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ ReedSolomonDecoder)
/* harmony export */ });
/* harmony import */ var _gf256__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./gf256 */ "./node_modules/qrcode-reader/src/gf256.js");
/* harmony import */ var _gf256poly__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./gf256poly */ "./node_modules/qrcode-reader/src/gf256poly.js");
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/




function ReedSolomonDecoder(field) {
  this.field = field;
}

ReedSolomonDecoder.prototype.decode = function(received, twoS) {
  var poly = new _gf256poly__WEBPACK_IMPORTED_MODULE_1__["default"](this.field, received);
  var syndromeCoefficients = new Array(twoS);
  for (var i = 0; i < syndromeCoefficients.length; i++)syndromeCoefficients[i] = 0;
  var dataMatrix = false;//this.field.Equals(GF256.DATA_MATRIX_FIELD);
  var noError = true;
  for (var i = 0; i < twoS; i++) {
    // Thanks to sanfordsquires for this fix:
    var _eval = poly.evaluateAt(this.field.exp(dataMatrix ? i + 1 : i));
    syndromeCoefficients[syndromeCoefficients.length - 1 - i] = _eval;
    if (_eval != 0) {
      noError = false;
    }
  }
  if (noError) {
    return;
  }
  var syndrome = new _gf256poly__WEBPACK_IMPORTED_MODULE_1__["default"](this.field, syndromeCoefficients);
  var sigmaOmega = this.runEuclideanAlgorithm(this.field.buildMonomial(twoS, 1), syndrome, twoS);
  var sigma = sigmaOmega[0];
  var omega = sigmaOmega[1];
  var errorLocations = this.findErrorLocations(sigma);
  var errorMagnitudes = this.findErrorMagnitudes(omega, errorLocations, dataMatrix);
  for (var i = 0; i < errorLocations.length; i++) {
    var position = received.length - 1 - this.field.log(errorLocations[i]);
    if (position < 0) {
      throw "ReedSolomonException Bad error location";
    }
    received[position] = _gf256__WEBPACK_IMPORTED_MODULE_0__["default"].prototype.addOrSubtract(received[position], errorMagnitudes[i]);
  }
};

ReedSolomonDecoder.prototype.runEuclideanAlgorithm = function(a,  b,  R) {
  // Assume a's degree is >= b's
  if (a.Degree < b.Degree) {
    var temp = a;
    a = b;
    b = temp;
  }

  var rLast = a;
  var r = b;
  var sLast = this.field.One;
  var s = this.field.Zero;
  var tLast = this.field.Zero;
  var t = this.field.One;

  // Run Euclidean algorithm until r's degree is less than R/2
  while (r.Degree >= Math.floor(R / 2)) {
    var rLastLast = rLast;
    var sLastLast = sLast;
    var tLastLast = tLast;
    rLast = r;
    sLast = s;
    tLast = t;

    // Divide rLastLast by rLast, with quotient in q and remainder in r
    if (rLast.Zero) {
      // Oops, Euclidean algorithm already terminated?
      throw "r_{i-1} was zero";
    }
    r = rLastLast;
    var q = this.field.Zero;
    var denominatorLeadingTerm = rLast.getCoefficient(rLast.Degree);
    var dltInverse = this.field.inverse(denominatorLeadingTerm);
    while (r.Degree >= rLast.Degree && !r.Zero) {
      var degreeDiff = r.Degree - rLast.Degree;
      var scale = this.field.multiply(r.getCoefficient(r.Degree), dltInverse);
      q = q.addOrSubtract(this.field.buildMonomial(degreeDiff, scale));
      r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale));
    }

    s = q.multiply1(sLast).addOrSubtract(sLastLast);
    t = q.multiply1(tLast).addOrSubtract(tLastLast);
  }

  var sigmaTildeAtZero = t.getCoefficient(0);
  if (sigmaTildeAtZero == 0) {
    throw "ReedSolomonException sigmaTilde(0) was zero";
  }

  var inverse = this.field.inverse(sigmaTildeAtZero);
  var sigma = t.multiply2(inverse);
  var omega = r.multiply2(inverse);
  return [sigma, omega];
};

ReedSolomonDecoder.prototype.findErrorLocations = function(errorLocator) {
  // This is a direct application of Chien's search
  var numErrors = errorLocator.Degree;
  if (numErrors == 1) {
    // shortcut
    return new Array(errorLocator.getCoefficient(1));
  }
  var result = new Array(numErrors);
  var e = 0;
  for (var i = 1; i < 256 && e < numErrors; i++) {
    if (errorLocator.evaluateAt(i) == 0) {
      result[e] = this.field.inverse(i);
      e++;
    }
  }
  if (e != numErrors) {
    throw "Error locator degree does not match number of roots";
  }
  return result;
};

ReedSolomonDecoder.prototype.findErrorMagnitudes = function(errorEvaluator, errorLocations, dataMatrix) {
  // This is directly applying Forney's Formula
  var s = errorLocations.length;
  var result = new Array(s);
  for (var i = 0; i < s; i++) {
    var xiInverse = this.field.inverse(errorLocations[i]);
    var denominator = 1;
    for (var j = 0; j < s; j++) {
      if (i != j) {
        denominator = this.field.multiply(denominator, _gf256__WEBPACK_IMPORTED_MODULE_0__["default"].prototype.addOrSubtract(1, this.field.multiply(errorLocations[j], xiInverse)));
      }
    }
    result[i] = this.field.multiply(errorEvaluator.evaluateAt(xiInverse), this.field.inverse(denominator));
    // Thanks to sanfordsquires for this fix:
    if (dataMatrix) {
      result[i] = this.field.multiply(result[i], xiInverse);
    }
  }
  return result;
};


/***/ }),

/***/ "./node_modules/qrcode-reader/src/version.js":
/*!***************************************************!*\
  !*** ./node_modules/qrcode-reader/src/version.js ***!
  \***************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ Version)
/* harmony export */ });
/* harmony import */ var _formatinf__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./formatinf */ "./node_modules/qrcode-reader/src/formatinf.js");
/* harmony import */ var _bitmat__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./bitmat */ "./node_modules/qrcode-reader/src/bitmat.js");
/*
  Ported to JavaScript by Lazar Laszlo 2011

  lazarsoft@gmail.com, www.lazarsoft.info

*/

/*
*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/




function ECB(count,  dataCodewords) {
  this.count = count;
  this.dataCodewords = dataCodewords;
}

function ECBlocks(ecCodewordsPerBlock,  ecBlocks1,  ecBlocks2) {
  this.ecCodewordsPerBlock = ecCodewordsPerBlock;
  if (ecBlocks2)
    this.ecBlocks = [ecBlocks1, ecBlocks2];
  else
    this.ecBlocks = [ecBlocks1];
}

Object.defineProperty(ECBlocks.prototype, "TotalECCodewords", {
  get: function() {
    return  this.ecCodewordsPerBlock * this.NumBlocks;
  }
});

Object.defineProperty(ECBlocks.prototype, "NumBlocks", {
  get: function() {
    var total = 0;
    for (var i = 0; i < this.ecBlocks.length; i++) {
      total += this.ecBlocks[i].length;
    }
    return total;
  }
});

ECBlocks.prototype.getECBlocks = function() {
  return this.ecBlocks;
};

function Version(versionNumber,  alignmentPatternCenters,  ecBlocks1,  ecBlocks2,  ecBlocks3,  ecBlocks4) {
  this.versionNumber = versionNumber;
  this.alignmentPatternCenters = alignmentPatternCenters;
  this.ecBlocks = [ecBlocks1, ecBlocks2, ecBlocks3, ecBlocks4];

  var total = 0;
  var ecCodewords = ecBlocks1.ecCodewordsPerBlock;
  var ecbArray = ecBlocks1.getECBlocks();
  for (var i = 0; i < ecbArray.length; i++) {
    var ecBlock = ecbArray[i];
    total += ecBlock.count * (ecBlock.dataCodewords + ecCodewords);
  }
  this.totalCodewords = total;
}

Object.defineProperty(Version.prototype, "DimensionForVersion", {
  get: function() {
    return  17 + 4 * this.versionNumber;
  }
});

Version.prototype.buildFunctionPattern = function() {
  var dimension = this.DimensionForVersion;
  var bitMatrix = new _bitmat__WEBPACK_IMPORTED_MODULE_1__["default"](dimension);

  // Top left finder pattern + separator + format
  bitMatrix.setRegion(0, 0, 9, 9);
  // Top right finder pattern + separator + format
  bitMatrix.setRegion(dimension - 8, 0, 8, 9);
  // Bottom left finder pattern + separator + format
  bitMatrix.setRegion(0, dimension - 8, 9, 8);

  // Alignment patterns
  var max = this.alignmentPatternCenters.length;
  for (var x = 0; x < max; x++) {
    var i = this.alignmentPatternCenters[x] - 2;
    for (var y = 0; y < max; y++) {
      if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) {
        // No alignment patterns near the three finder paterns
        continue;
      }
      bitMatrix.setRegion(this.alignmentPatternCenters[y] - 2, i, 5, 5);
    }
  }

  // Vertical timing pattern
  bitMatrix.setRegion(6, 9, 1, dimension - 17);
  // Horizontal timing pattern
  bitMatrix.setRegion(9, 6, dimension - 17, 1);

  if (this.versionNumber > 6) {
    // Version info, top right
    bitMatrix.setRegion(dimension - 11, 0, 3, 6);
    // Version info, bottom left
    bitMatrix.setRegion(0, dimension - 11, 6, 3);
  }

  return bitMatrix;
};

Version.prototype.getECBlocksForLevel = function(ecLevel) {
  return this.ecBlocks[ecLevel.ordinal()];
};

Version.VERSION_DECODE_INFO = [
  0x07C94,
  0x085BC,
  0x09A99,
  0x0A4D3,
  0x0BBF6,
  0x0C762,
  0x0D847,
  0x0E60D,
  0x0F928,
  0x10B78,
  0x1145D,
  0x12A17,
  0x13532,
  0x149A6,
  0x15683,
  0x168C9,
  0x177EC,
  0x18EC4,
  0x191E1,
  0x1AFAB,
  0x1B08E,
  0x1CC1A,
  0x1D33F,
  0x1ED75,
  0x1F250,
  0x209D5,
  0x216F0,
  0x228BA,
  0x2379F,
  0x24B0B,
  0x2542E,
  0x26A64,
  0x27541,
  0x28C69
];

Version.VERSIONS = buildVersions();

Version.getVersionForNumber = function(versionNumber) {
  if (versionNumber < 1 || versionNumber > 40) {
    throw "ArgumentException";
  }
  return Version.VERSIONS[versionNumber - 1];
};

Version.getProvisionalVersionForDimension = function(dimension) {
  if (dimension % 4 != 1) {
    throw "Error getProvisionalVersionForDimension";
  }
  try {
    return Version.getVersionForNumber((dimension - 17) >> 2);
  } catch (iae) {
    throw "Error getVersionForNumber";
  }
};

Version.decodeVersionInformation = function(versionBits) {
  var bestDifference = 0xffffffff;
  var bestVersion = 0;
  for (var i = 0; i < Version.VERSION_DECODE_INFO.length; i++) {
    var targetVersion = Version.VERSION_DECODE_INFO[i];
    // Do the version info bits match exactly? done.
    if (targetVersion == versionBits) {
      return this.getVersionForNumber(i + 7);
    }
    // Otherwise see if this is the closest to a real version info bit string
    // we have seen so far
    var bitsDifference = _formatinf__WEBPACK_IMPORTED_MODULE_0__["default"].numBitsDiffering(versionBits, targetVersion);
    if (bitsDifference < bestDifference) {
      bestVersion = i + 7;
      bestDifference = bitsDifference;
    }
  }
  // We can tolerate up to 3 bits of error since no two version info codewords will
  // differ in less than 4 bits.
  if (bestDifference <= 3) {
    return this.getVersionForNumber(bestVersion);
  }
  // If we didn't find a close enough match, fail
  return null;
};

function buildVersions() {
  return [
    new Version(1, [], new ECBlocks(7, new ECB(1, 19)), new ECBlocks(10, new ECB(1, 16)), new ECBlocks(13, new ECB(1, 13)), new ECBlocks(17, new ECB(1, 9))),
    new Version(2, [6, 18], new ECBlocks(10, new ECB(1, 34)), new ECBlocks(16, new ECB(1, 28)), new ECBlocks(22, new ECB(1, 22)), new ECBlocks(28, new ECB(1, 16))),
    new Version(3, [6, 22], new ECBlocks(15, new ECB(1, 55)), new ECBlocks(26, new ECB(1, 44)), new ECBlocks(18, new ECB(2, 17)), new ECBlocks(22, new ECB(2, 13))),
    new Version(4, [6, 26], new ECBlocks(20, new ECB(1, 80)), new ECBlocks(18, new ECB(2, 32)), new ECBlocks(26, new ECB(2, 24)), new ECBlocks(16, new ECB(4, 9))),
    new Version(5, [6, 30], new ECBlocks(26, new ECB(1, 108)), new ECBlocks(24, new ECB(2, 43)), new ECBlocks(18, new ECB(2, 15), new ECB(2, 16)), new ECBlocks(22, new ECB(2, 11), new ECB(2, 12))),
    new Version(6, [6, 34], new ECBlocks(18, new ECB(2, 68)), new ECBlocks(16, new ECB(4, 27)), new ECBlocks(24, new ECB(4, 19)), new ECBlocks(28, new ECB(4, 15))),
    new Version(7, [6, 22, 38], new ECBlocks(20, new ECB(2, 78)), new ECBlocks(18, new ECB(4, 31)), new ECBlocks(18, new ECB(2, 14), new ECB(4, 15)), new ECBlocks(26, new ECB(4, 13), new ECB(1, 14))),
    new Version(8, [6, 24, 42], new ECBlocks(24, new ECB(2, 97)), new ECBlocks(22, new ECB(2, 38), new ECB(2, 39)), new ECBlocks(22, new ECB(4, 18), new ECB(2, 19)), new ECBlocks(26, new ECB(4, 14), new ECB(2, 15))),
    new Version(9, [6, 26, 46], new ECBlocks(30, new ECB(2, 116)), new ECBlocks(22, new ECB(3, 36), new ECB(2, 37)), new ECBlocks(20, new ECB(4, 16), new ECB(4, 17)), new ECBlocks(24, new ECB(4, 12), new ECB(4, 13))),
    new Version(10, [6, 28, 50], new ECBlocks(18, new ECB(2, 68), new ECB(2, 69)), new ECBlocks(26, new ECB(4, 43), new ECB(1, 44)), new ECBlocks(24, new ECB(6, 19), new ECB(2, 20)), new ECBlocks(28, new ECB(6, 15), new ECB(2, 16))),
    new Version(11, [6, 30, 54], new ECBlocks(20, new ECB(4, 81)), new ECBlocks(30, new ECB(1, 50), new ECB(4, 51)), new ECBlocks(28, new ECB(4, 22), new ECB(4, 23)), new ECBlocks(24, new ECB(3, 12), new ECB(8, 13))),
    new Version(12, [6, 32, 58], new ECBlocks(24, new ECB(2, 92), new ECB(2, 93)), new ECBlocks(22, new ECB(6, 36), new ECB(2, 37)), new ECBlocks(26, new ECB(4, 20), new ECB(6, 21)), new ECBlocks(28, new ECB(7, 14), new ECB(4, 15))),
    new Version(13, [6, 34, 62], new ECBlocks(26, new ECB(4, 107)), new ECBlocks(22, new ECB(8, 37), new ECB(1, 38)), new ECBlocks(24, new ECB(8, 20), new ECB(4, 21)), new ECBlocks(22, new ECB(12, 11), new ECB(4, 12))),
    new Version(14, [6, 26, 46, 66], new ECBlocks(30, new ECB(3, 115), new ECB(1, 116)), new ECBlocks(24, new ECB(4, 40), new ECB(5, 41)), new ECBlocks(20, new ECB(11, 16), new ECB(5, 17)), new ECBlocks(24, new ECB(11, 12), new ECB(5, 13))),
    new Version(15, [6, 26, 48, 70], new ECBlocks(22, new ECB(5, 87), new ECB(1, 88)), new ECBlocks(24, new ECB(5, 41), new ECB(5, 42)), new ECBlocks(30, new ECB(5, 24), new ECB(7, 25)), new ECBlocks(24, new ECB(11, 12), new ECB(7, 13))),
    new Version(16, [6, 26, 50, 74], new ECBlocks(24, new ECB(5, 98), new ECB(1, 99)), new ECBlocks(28, new ECB(7, 45), new ECB(3, 46)), new ECBlocks(24, new ECB(15, 19), new ECB(2, 20)), new ECBlocks(30, new ECB(3, 15), new ECB(13, 16))),
    new Version(17, [6, 30, 54, 78], new ECBlocks(28, new ECB(1, 107), new ECB(5, 108)), new ECBlocks(28, new ECB(10, 46), new ECB(1, 47)), new ECBlocks(28, new ECB(1, 22), new ECB(15, 23)), new ECBlocks(28, new ECB(2, 14), new ECB(17, 15))),
    new Version(18, [6, 30, 56, 82], new ECBlocks(30, new ECB(5, 120), new ECB(1, 121)), new ECBlocks(26, new ECB(9, 43), new ECB(4, 44)), new ECBlocks(28, new ECB(17, 22), new ECB(1, 23)), new ECBlocks(28, new ECB(2, 14), new ECB(19, 15))),
    new Version(19, [6, 30, 58, 86], new ECBlocks(28, new ECB(3, 113), new ECB(4, 114)), new ECBlocks(26, new ECB(3, 44), new ECB(11, 45)), new ECBlocks(26, new ECB(17, 21), new ECB(4, 22)), new ECBlocks(26, new ECB(9, 13), new ECB(16, 14))),
    new Version(20, [6, 34, 62, 90], new ECBlocks(28, new ECB(3, 107), new ECB(5, 108)), new ECBlocks(26, new ECB(3, 41), new ECB(13, 42)), new ECBlocks(30, new ECB(15, 24), new ECB(5, 25)), new ECBlocks(28, new ECB(15, 15), new ECB(10, 16))),
    new Version(21, [6, 28, 50, 72, 94], new ECBlocks(28, new ECB(4, 116), new ECB(4, 117)), new ECBlocks(26, new ECB(17, 42)), new ECBlocks(28, new ECB(17, 22), new ECB(6, 23)), new ECBlocks(30, new ECB(19, 16), new ECB(6, 17))),
    new Version(22, [6, 26, 50, 74, 98], new ECBlocks(28, new ECB(2, 111), new ECB(7, 112)), new ECBlocks(28, new ECB(17, 46)), new ECBlocks(30, new ECB(7, 24), new ECB(16, 25)), new ECBlocks(24, new ECB(34, 13))),
    new Version(23, [6, 30, 54, 74, 102], new ECBlocks(30, new ECB(4, 121), new ECB(5, 122)), new ECBlocks(28, new ECB(4, 47), new ECB(14, 48)), new ECBlocks(30, new ECB(11, 24), new ECB(14, 25)), new ECBlocks(30, new ECB(16, 15), new ECB(14, 16))),
    new Version(24, [6, 28, 54, 80, 106], new ECBlocks(30, new ECB(6, 117), new ECB(4, 118)), new ECBlocks(28, new ECB(6, 45), new ECB(14, 46)), new ECBlocks(30, new ECB(11, 24), new ECB(16, 25)), new ECBlocks(30, new ECB(30, 16), new ECB(2, 17))),
    new Version(25, [6, 32, 58, 84, 110], new ECBlocks(26, new ECB(8, 106), new ECB(4, 107)), new ECBlocks(28, new ECB(8, 47), new ECB(13, 48)), new ECBlocks(30, new ECB(7, 24), new ECB(22, 25)), new ECBlocks(30, new ECB(22, 15), new ECB(13, 16))),
    new Version(26, [6, 30, 58, 86, 114], new ECBlocks(28, new ECB(10, 114), new ECB(2, 115)), new ECBlocks(28, new ECB(19, 46), new ECB(4, 47)), new ECBlocks(28, new ECB(28, 22), new ECB(6, 23)), new ECBlocks(30, new ECB(33, 16), new ECB(4, 17))),
    new Version(27, [6, 34, 62, 90, 118], new ECBlocks(30, new ECB(8, 122), new ECB(4, 123)), new ECBlocks(28, new ECB(22, 45), new ECB(3, 46)), new ECBlocks(30, new ECB(8, 23), new ECB(26, 24)), new ECBlocks(30, new ECB(12, 15),     new ECB(28, 16))),
    new Version(28, [6, 26, 50, 74, 98, 122], new ECBlocks(30, new ECB(3, 117), new ECB(10, 118)), new ECBlocks(28, new ECB(3, 45), new ECB(23, 46)), new ECBlocks(30, new ECB(4, 24), new ECB(31, 25)), new ECBlocks(30, new ECB(11, 15), new ECB(31, 16))),
    new Version(29, [6, 30, 54, 78, 102, 126], new ECBlocks(30, new ECB(7, 116), new ECB(7, 117)), new ECBlocks(28, new ECB(21, 45), new ECB(7, 46)), new ECBlocks(30, new ECB(1, 23), new ECB(37, 24)), new ECBlocks(30, new ECB(19, 15), new ECB(26, 16))),
    new Version(30, [6, 26, 52, 78, 104, 130], new ECBlocks(30, new ECB(5, 115), new ECB(10, 116)), new ECBlocks(28, new ECB(19, 47), new ECB(10, 48)), new ECBlocks(30, new ECB(15, 24), new ECB(25, 25)), new ECBlocks(30, new ECB(23, 15), new ECB(25, 16))),
    new Version(31, [6, 30, 56, 82, 108, 134], new ECBlocks(30, new ECB(13, 115), new ECB(3, 116)), new ECBlocks(28, new ECB(2, 46), new ECB(29, 47)), new ECBlocks(30, new ECB(42, 24), new ECB(1, 25)), new ECBlocks(30, new ECB(23, 15), new ECB(28, 16))),
    new Version(32, [6, 34, 60, 86, 112, 138], new ECBlocks(30, new ECB(17, 115)), new ECBlocks(28, new ECB(10, 46), new ECB(23, 47)), new ECBlocks(30, new ECB(10, 24), new ECB(35, 25)), new ECBlocks(30, new ECB(19, 15), new ECB(35, 16))),
    new Version(33, [6, 30, 58, 86, 114, 142], new ECBlocks(30, new ECB(17, 115), new ECB(1, 116)), new ECBlocks(28, new ECB(14, 46), new ECB(21, 47)), new ECBlocks(30, new ECB(29, 24), new ECB(19, 25)), new ECBlocks(30, new ECB(11, 15), new ECB(46, 16))),
    new Version(34, [6, 34, 62, 90, 118, 146], new ECBlocks(30, new ECB(13, 115), new ECB(6, 116)), new ECBlocks(28, new ECB(14, 46), new ECB(23, 47)), new ECBlocks(30, new ECB(44, 24), new ECB(7, 25)), new ECBlocks(30, new ECB(59, 16), new ECB(1, 17))),
    new Version(35, [6, 30, 54, 78, 102, 126, 150], new ECBlocks(30, new ECB(12, 121), new ECB(7, 122)), new ECBlocks(28, new ECB(12, 47), new ECB(26, 48)), new ECBlocks(30, new ECB(39, 24), new ECB(14, 25)), new ECBlocks(30, new ECB(22, 15), new ECB(41, 16))),
    new Version(36, [6, 24, 50, 76, 102, 128, 154], new ECBlocks(30, new ECB(6, 121), new ECB(14, 122)), new ECBlocks(28, new ECB(6, 47), new ECB(34, 48)), new ECBlocks(30, new ECB(46, 24), new ECB(10, 25)), new ECBlocks(30, new ECB(2, 15), new ECB(64, 16))),
    new Version(37, [6, 28, 54, 80, 106, 132, 158], new ECBlocks(30, new ECB(17, 122), new ECB(4, 123)), new ECBlocks(28, new ECB(29, 46), new ECB(14, 47)), new ECBlocks(30, new ECB(49, 24), new ECB(10, 25)), new ECBlocks(30, new ECB(24, 15), new ECB(46, 16))),
    new Version(38, [6, 32, 58, 84, 110, 136, 162], new ECBlocks(30, new ECB(4, 122), new ECB(18, 123)), new ECBlocks(28, new ECB(13, 46), new ECB(32, 47)), new ECBlocks(30, new ECB(48, 24), new ECB(14, 25)), new ECBlocks(30, new ECB(42, 15), new ECB(32, 16))),
    new Version(39, [6, 26, 54, 82, 110, 138, 166], new ECBlocks(30, new ECB(20, 117), new ECB(4, 118)), new ECBlocks(28, new ECB(40, 47), new ECB(7, 48)), new ECBlocks(30, new ECB(43, 24), new ECB(22, 25)), new ECBlocks(30, new ECB(10, 15), new ECB(67, 16))),
    new Version(40, [6, 30, 58, 86, 114, 142, 170], new ECBlocks(30, new ECB(19, 118), new ECB(6, 119)), new ECBlocks(28, new ECB(18, 47), new ECB(31, 48)), new ECBlocks(30, new ECB(34, 24), new ECB(34, 25)), new ECBlocks(30, new ECB(20, 15), new ECB(61, 16))),
  ];
}


/***/ }),

/***/ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import.vue?vue&type=script&lang=ts":
/*!*************************************************************************************************************************************************************************!*\
  !*** ./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import.vue?vue&type=script&lang=ts ***!
  \*************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.runtime.esm.js");
/* harmony import */ var _Import_FileImport_vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Import/FileImport.vue */ "./src/components/Import/FileImport.vue");
/* harmony import */ var _Import_QrImport_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Import/QrImport.vue */ "./src/components/Import/QrImport.vue");
/* harmony import */ var _Import_TextImport_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Import/TextImport.vue */ "./src/components/Import/TextImport.vue");




/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (vue__WEBPACK_IMPORTED_MODULE_3__["default"].extend({
    data: function () {
        const query = location.search ? location.search.substr(1) : "";
        const importType = ["FileImport", "QrImport", "TextImport"].includes(query)
            ? query
            : "FileImport";
        return {
            importType,
            shouldShowPassphrase: shouldShowPassphrase(this.$entries),
        };
    },
    components: {
        FileImport: _Import_FileImport_vue__WEBPACK_IMPORTED_MODULE_0__["default"],
        QrImport: _Import_QrImport_vue__WEBPACK_IMPORTED_MODULE_1__["default"],
        TextImport: _Import_TextImport_vue__WEBPACK_IMPORTED_MODULE_2__["default"],
    },
    mounted() {
        chrome.runtime.onMessage.addListener((event) => {
            if (event.action === "stopImport") {
                this.shouldShowPassphrase = true;
            }
            // https://stackoverflow.com/a/56483156
            return true;
        });
    },
}));
function shouldShowPassphrase(entries) {
    for (const entry of entries) {
        if (!entry.secret) {
            return true;
        }
    }
    return false;
}


/***/ }),

/***/ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/FileImport.vue?vue&type=script&lang=ts":
/*!************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/FileImport.vue?vue&type=script&lang=ts ***!
  \************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! crypto-js */ "./node_modules/crypto-js/index.js");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.runtime.esm.js");
/* harmony import */ var _import__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../import */ "./src/import.ts");
/* harmony import */ var _models_storage__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../models/storage */ "./src/models/storage.ts");
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};




/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (vue__WEBPACK_IMPORTED_MODULE_3__["default"].extend({
    data: function () {
        return {
            getFilePassphrase: false,
            readFilePassphrase: false,
            importFilePassphrase: "",
        };
    },
    methods: {
        importFile(event, closeWindow) {
            const target = event.target;
            if (!target || !target.files) {
                return;
            }
            if (target.files[0]) {
                const reader = new FileReader();
                let decryptedFileData = {};
                reader.onload = () => __awaiter(this, void 0, void 0, function* () {
                    let importData = {};
                    let failedCount = 0;
                    let succeededCount = 0;
                    const fileContent = reader.result;
                    // Check if file contains OTP auth URLs instead of JSON
                    if (fileContent.trim().startsWith("otpauth://")) {
                        const result = yield (0,_import__WEBPACK_IMPORTED_MODULE_1__.getEntryDataFromOTPAuthPerLine)(fileContent);
                        importData = result.exportData;
                        failedCount = result.failedCount;
                        succeededCount = result.succeededCount;
                    }
                    else {
                        try {
                            importData = JSON.parse(fileContent);
                            succeededCount = Object.keys(importData).filter((key) => ["key", "enc", "hash"].indexOf(key) === -1).length;
                        }
                        catch (e) {
                            // If JSON parsing fails, try OTP auth format
                            const result = yield (0,_import__WEBPACK_IMPORTED_MODULE_1__.getEntryDataFromOTPAuthPerLine)(fileContent);
                            importData = result.exportData;
                            failedCount = result.failedCount;
                            succeededCount = result.succeededCount;
                        }
                    }
                    let key = null;
                    if (importData.hasOwnProperty("key")) {
                        if (importData.key) {
                            key = importData.key;
                        }
                        delete importData.key;
                    }
                    else if (importData.enc && importData.hash) {
                        key = { enc: importData.enc };
                        delete importData.hash;
                        delete importData.enc;
                    }
                    for (const hash in importData) {
                        const possibleEntry = importData[hash];
                        if (possibleEntry.dataType === "Key") {
                            // don't try to import keys as an OTPEntry
                            continue;
                        }
                        if (possibleEntry.keyId || possibleEntry.encrypted) {
                            try {
                                const oldPassphrase = yield this.getOldPassphrase();
                                if (key) {
                                    // v2 encryption
                                    decryptedFileData = yield (0,_import__WEBPACK_IMPORTED_MODULE_1__.decryptBackupData)(importData, crypto_js__WEBPACK_IMPORTED_MODULE_0__.AES.decrypt(key.enc, oldPassphrase).toString());
                                }
                                else {
                                    // v3 and v1 encryption
                                    decryptedFileData = yield (0,_import__WEBPACK_IMPORTED_MODULE_1__.decryptBackupData)(importData, oldPassphrase);
                                }
                                break;
                            }
                            catch (_a) {
                                break;
                            }
                        }
                        else {
                            decryptedFileData[hash] = possibleEntry;
                        }
                    }
                    if (Object.keys(decryptedFileData).length) {
                        yield _models_storage__WEBPACK_IMPORTED_MODULE_2__.EntryStorage.import(this.$encryption, decryptedFileData);
                        if (failedCount === 0) {
                            alert(this.i18n.updateSuccess);
                        }
                        else if (succeededCount) {
                            alert(this.i18n.migration_partly_fail);
                        }
                        else {
                            alert(this.i18n.migration_fail);
                        }
                        if (closeWindow) {
                            window.close();
                        }
                    }
                    else {
                        alert(this.i18n.migration_fail);
                        this.getFilePassphrase = false;
                        this.importFilePassphrase = "";
                    }
                });
                reader.readAsText(target.files[0], "utf8");
            }
            else {
                alert(this.i18n.migration_fail);
                if (closeWindow) {
                    window.close();
                }
            }
            return;
        },
        getOldPassphrase() {
            return __awaiter(this, void 0, void 0, function* () {
                this.getFilePassphrase = true;
                while (true) {
                    if (this.readFilePassphrase) {
                        if (this.importFilePassphrase) {
                            this.readFilePassphrase = false;
                            break;
                        }
                        else {
                            this.readFilePassphrase = false;
                        }
                    }
                    yield new Promise((resolve) => setTimeout(resolve, 250));
                }
                return this.importFilePassphrase;
            });
        },
    },
}));


/***/ }),

/***/ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/QrImport.vue?vue&type=script&lang=ts":
/*!**********************************************************************************************************************************************************************************!*\
  !*** ./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/QrImport.vue?vue&type=script&lang=ts ***!
  \**********************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.runtime.esm.js");
/* harmony import */ var qrcode_reader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! qrcode-reader */ "./node_modules/qrcode-reader/src/index.js");
/* harmony import */ var jsqr__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! jsqr */ "./node_modules/jsqr/dist/jsQR.js");
/* harmony import */ var jsqr__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(jsqr__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _import__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../import */ "./src/import.ts");
/* harmony import */ var _models_storage__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../models/storage */ "./src/models/storage.ts");
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};

// @ts-ignore




/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (vue__WEBPACK_IMPORTED_MODULE_4__["default"].extend({
    methods: {
        importQr(event, closeWindow) {
            return __awaiter(this, void 0, void 0, function* () {
                const target = event.target;
                if (!target || !target.files) {
                    return;
                }
                if (target.files.length) {
                    const otpUrlList = [];
                    let hasFailedResults = false;
                    for (let fileIndex = 0; fileIndex < target.files.length; fileIndex++) {
                        const file = target.files[fileIndex];
                        const otpUrl = yield getOtpUrlFromQrFile(file);
                        if (otpUrl !== null) {
                            otpUrlList.push(otpUrl);
                        }
                        else {
                            hasFailedResults = true;
                        }
                    }
                    const result = yield (0,_import__WEBPACK_IMPORTED_MODULE_2__.getEntryDataFromOTPAuthPerLine)(otpUrlList.join("\n"));
                    let importData = result.exportData;
                    const { failedCount, succeededCount } = result;
                    let decryptedFileData = importData;
                    if (Object.keys(decryptedFileData).length) {
                        yield _models_storage__WEBPACK_IMPORTED_MODULE_3__.EntryStorage.import(this.$encryption, decryptedFileData);
                        if (hasFailedResults) {
                            alert(this.i18n.import_backup_qr_partly_failed);
                        }
                        else if (failedCount && succeededCount) {
                            alert(this.i18n.migration_partly_fail);
                        }
                        else if (succeededCount) {
                            alert(this.i18n.updateSuccess);
                        }
                        else {
                            alert(this.i18n.migration_fail);
                        }
                        if (closeWindow) {
                            window.close();
                        }
                    }
                    else {
                        alert(this.i18n.errorqr);
                        if (closeWindow) {
                            window.close();
                        }
                    }
                }
                else {
                    alert(this.i18n.updateFailure);
                    if (closeWindow) {
                        window.alert(this.i18n.updateFailure);
                        window.close();
                    }
                }
                return;
            });
        },
    },
}));
function getOtpUrlFromQrFile(file) {
    return __awaiter(this, void 0, void 0, function* () {
        return new Promise((resolve) => {
            const reader = new FileReader();
            reader.onload = () => {
                const imageUrl = reader.result;
                const qrReader = new qrcode_reader__WEBPACK_IMPORTED_MODULE_0__["default"]();
                qrReader.callback = (error, text) => {
                    if (error) {
                        console.error(error);
                        const image = document.createElement("img");
                        image.onload = () => {
                            const canvas = document.createElement("canvas");
                            const ctx = canvas.getContext("2d");
                            canvas.width = image.width;
                            canvas.height = image.height;
                            ctx.drawImage(image, 0, 0);
                            const qrImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                            const jsQrCode = jsqr__WEBPACK_IMPORTED_MODULE_1___default()(qrImageData.data, canvas.width, canvas.height);
                            if (jsQrCode && jsQrCode.data) {
                                if (jsQrCode.data.indexOf("otpauth://") !== 0 &&
                                    jsQrCode.data.indexOf("otpauth-migration://") !== 0) {
                                    return resolve(null);
                                }
                                return resolve(jsQrCode.data);
                            }
                            else {
                                return resolve(null);
                            }
                        };
                        image.src = imageUrl;
                    }
                    else {
                        if (text.result.indexOf("otpauth://") !== 0 &&
                            text.result.indexOf("otpauth-migration://") !== 0) {
                            return resolve(null);
                        }
                        return resolve(text.result);
                    }
                };
                qrReader.decode(imageUrl);
            };
            reader.readAsDataURL(file);
        });
    });
}


/***/ }),

/***/ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/TextImport.vue?vue&type=script&lang=ts":
/*!************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/TextImport.vue?vue&type=script&lang=ts ***!
  \************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! crypto-js */ "./node_modules/crypto-js/index.js");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.runtime.esm.js");
/* harmony import */ var _import__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../import */ "./src/import.ts");
/* harmony import */ var _models_storage__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../models/storage */ "./src/models/storage.ts");
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};




/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (vue__WEBPACK_IMPORTED_MODULE_3__["default"].extend({
    data: function () {
        return {
            importCode: "",
            importEncrypted: false,
            importPassphrase: "",
        };
    },
    methods: {
        importBackupCode() {
            return __awaiter(this, void 0, void 0, function* () {
                let exportData = {};
                let failedCount = 0;
                let succeededCount = 0;
                try {
                    exportData = JSON.parse(this.importCode);
                }
                catch (error) {
                    console.warn(error);
                    // Maybe one-otpauth-per line text
                    const result = yield (0,_import__WEBPACK_IMPORTED_MODULE_1__.getEntryDataFromOTPAuthPerLine)(this.importCode);
                    exportData = result.exportData;
                    failedCount = result.failedCount;
                    succeededCount = result.succeededCount;
                }
                let key = null;
                if (exportData.hasOwnProperty("key")) {
                    if (exportData.key) {
                        key = exportData.key;
                    }
                    delete exportData.key;
                }
                try {
                    const passphrase = this.importEncrypted && this.importPassphrase
                        ? this.importPassphrase
                        : null;
                    let decryptedbackupData = {};
                    if (key && passphrase) {
                        decryptedbackupData = yield (0,_import__WEBPACK_IMPORTED_MODULE_1__.decryptBackupData)(exportData, crypto_js__WEBPACK_IMPORTED_MODULE_0__.AES.decrypt(key.enc, passphrase).toString());
                    }
                    else {
                        decryptedbackupData = yield (0,_import__WEBPACK_IMPORTED_MODULE_1__.decryptBackupData)(exportData, passphrase);
                    }
                    if (Object.keys(decryptedbackupData).length) {
                        yield _models_storage__WEBPACK_IMPORTED_MODULE_2__.EntryStorage.import(this.$encryption, decryptedbackupData);
                        if (failedCount === 0) {
                            alert(this.i18n.updateSuccess);
                        }
                        else if (succeededCount) {
                            alert(this.i18n.import_backup_qr_partly_failed);
                        }
                        else {
                            alert(this.i18n.updateFailure);
                        }
                        window.close();
                    }
                    else {
                        alert(this.i18n.updateFailure);
                    }
                    return;
                }
                catch (error) {
                    throw error;
                }
            });
        },
    },
}));


/***/ }),

/***/ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ButtonInput.vue?vue&type=script&lang=ts":
/*!*************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ButtonInput.vue?vue&type=script&lang=ts ***!
  \*************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.runtime.esm.js");

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (vue__WEBPACK_IMPORTED_MODULE_0__["default"].extend({
    props: ["type"],
}));


/***/ }),

/***/ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ButtonLink.vue?vue&type=script&lang=ts":
/*!************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ButtonLink.vue?vue&type=script&lang=ts ***!
  \************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.runtime.esm.js");

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (vue__WEBPACK_IMPORTED_MODULE_0__["default"].extend({
    props: ["type", "href", "download"],
}));


/***/ }),

/***/ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/FileInput.vue?vue&type=script&lang=ts":
/*!***********************************************************************************************************************************************************************************!*\
  !*** ./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/FileInput.vue?vue&type=script&lang=ts ***!
  \***********************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.runtime.esm.js");

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (vue__WEBPACK_IMPORTED_MODULE_0__["default"].extend({
    props: ["label", "multiple", "accept"],
}));


/***/ }),

/***/ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/SelectInput.vue?vue&type=script&lang=ts":
/*!*************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/SelectInput.vue?vue&type=script&lang=ts ***!
  \*************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.runtime.esm.js");

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (vue__WEBPACK_IMPORTED_MODULE_0__["default"].extend({
    props: ["label", "value", "disabled"],
}));


/***/ }),

/***/ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/TextInput.vue?vue&type=script&lang=ts":
/*!***********************************************************************************************************************************************************************************!*\
  !*** ./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/TextInput.vue?vue&type=script&lang=ts ***!
  \***********************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.runtime.esm.js");

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (vue__WEBPACK_IMPORTED_MODULE_0__["default"].extend({
    props: ["label", "value", "type", "autofocus"],
    mounted() {
        if (!this.$props.autofocus) {
            return;
        }
        const textInput = this.$refs.textInput;
        if (textInput instanceof HTMLInputElement) {
            textInput.focus();
        }
    },
}));


/***/ }),

/***/ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ToggleInput.vue?vue&type=script&lang=ts":
/*!*************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ToggleInput.vue?vue&type=script&lang=ts ***!
  \*************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.runtime.esm.js");

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (vue__WEBPACK_IMPORTED_MODULE_0__["default"].extend({
    props: {
        label: String,
        checked: Boolean,
    },
    model: {
        prop: "checked",
        event: "change",
    },
}));


/***/ }),

/***/ "./src/components/common/index.ts":
/*!****************************************!*\
  !*** ./src/components/common/index.ts ***!
  \****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _ButtonInput_vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ButtonInput.vue */ "./src/components/common/ButtonInput.vue");
/* harmony import */ var _ButtonLink_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ButtonLink.vue */ "./src/components/common/ButtonLink.vue");
/* harmony import */ var _TextInput_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TextInput.vue */ "./src/components/common/TextInput.vue");
/* harmony import */ var _SelectInput_vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./SelectInput.vue */ "./src/components/common/SelectInput.vue");
/* harmony import */ var _ToggleInput_vue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ToggleInput.vue */ "./src/components/common/ToggleInput.vue");
/* harmony import */ var _FileInput_vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./FileInput.vue */ "./src/components/common/FileInput.vue");






/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ([
    { name: "a-button", component: _ButtonInput_vue__WEBPACK_IMPORTED_MODULE_0__["default"] },
    { name: "a-button-link", component: _ButtonLink_vue__WEBPACK_IMPORTED_MODULE_1__["default"] },
    { name: "a-text-input", component: _TextInput_vue__WEBPACK_IMPORTED_MODULE_2__["default"] },
    { name: "a-select-input", component: _SelectInput_vue__WEBPACK_IMPORTED_MODULE_3__["default"] },
    { name: "a-toggle-input", component: _ToggleInput_vue__WEBPACK_IMPORTED_MODULE_4__["default"] },
    { name: "a-file-input", component: _FileInput_vue__WEBPACK_IMPORTED_MODULE_5__["default"] },
]);


/***/ }),

/***/ "./src/import.ts":
/*!***********************!*\
  !*** ./src/import.ts ***!
  \***********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   decryptBackupData: () => (/* binding */ decryptBackupData),
/* harmony export */   getEntryDataFromOTPAuthPerLine: () => (/* binding */ getEntryDataFromOTPAuthPerLine)
/* harmony export */ });
/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.runtime.esm.js");
/* harmony import */ var _components_Import_vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./components/Import.vue */ "./src/components/Import.vue");
/* harmony import */ var _components_common_index__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./components/common/index */ "./src/components/common/index.ts");
/* harmony import */ var _store_i18n__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./store/i18n */ "./src/store/i18n.ts");
/* harmony import */ var _models_encryption__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./models/encryption */ "./src/models/encryption.ts");
/* harmony import */ var _models_storage__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./models/storage */ "./src/models/storage.ts");
/* harmony import */ var _models_migration__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./models/migration */ "./src/models/migration.ts");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! crypto-js */ "./node_modules/crypto-js/index.js");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(crypto_js__WEBPACK_IMPORTED_MODULE_6__);
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};








function init() {
    return __awaiter(this, void 0, void 0, function* () {
        // i18n
        vue__WEBPACK_IMPORTED_MODULE_7__["default"].prototype.i18n = yield (0,_store_i18n__WEBPACK_IMPORTED_MODULE_2__.loadI18nMessages)();
        // Load common components globally
        for (const component of _components_common_index__WEBPACK_IMPORTED_MODULE_1__["default"]) {
            vue__WEBPACK_IMPORTED_MODULE_7__["default"].component(component.name, component.component);
        }
        // Load entries to global
        const cachedSecrets = yield getCachedSecrets();
        const encryption = new _models_encryption__WEBPACK_IMPORTED_MODULE_3__.Encryption(cachedSecrets.cachedPassphrase, cachedSecrets.cachedKeyId);
        const entries = yield _models_storage__WEBPACK_IMPORTED_MODULE_4__.EntryStorage.get();
        if (encryption.getEncryptionStatus()) {
            for (const entry of entries) {
                yield entry.applyEncryption(encryption);
            }
        }
        vue__WEBPACK_IMPORTED_MODULE_7__["default"].prototype.$entries = entries;
        vue__WEBPACK_IMPORTED_MODULE_7__["default"].prototype.$encryption = encryption;
        const instance = new vue__WEBPACK_IMPORTED_MODULE_7__["default"]({
            render: (h) => h(_components_Import_vue__WEBPACK_IMPORTED_MODULE_0__["default"]),
        }).$mount("#import");
        // Set title
        try {
            document.title = instance.i18n.extName;
        }
        catch (e) {
            console.error(e);
        }
    });
}
init();
function getCachedSecrets() {
    return __awaiter(this, void 0, void 0, function* () {
        const { cachedPassphrase, cachedKeyId } = yield chrome.storage.session.get();
        return { cachedPassphrase, cachedKeyId };
    });
}
function decryptBackupData(backupData, passphrase) {
    return __awaiter(this, void 0, void 0, function* () {
        const decryptedBackupData = {};
        const keys = new Map();
        for (const hash in backupData) {
            const unknownStorageItem = backupData[hash];
            if (typeof unknownStorageItem !== "object" ||
                unknownStorageItem.dataType === "Key") {
                continue;
            }
            let storageItem;
            if (unknownStorageItem.dataType === "EncOTPStorage") {
                if (!passphrase) {
                    continue;
                }
                if (!keys.has(unknownStorageItem.keyId)) {
                    keys.set(unknownStorageItem.keyId, yield findAndUnlockKey(backupData, unknownStorageItem.keyId, passphrase));
                }
                const decryptKey = keys.get(unknownStorageItem.keyId);
                if (!decryptKey) {
                    // wrong password for key
                    continue;
                }
                storageItem = Object.assign(Object.assign(Object.assign({}, unknownStorageItem), JSON.parse(crypto_js__WEBPACK_IMPORTED_MODULE_6__.AES.decrypt(unknownStorageItem.data, decryptKey).toString(crypto_js__WEBPACK_IMPORTED_MODULE_6__.enc.Utf8))), { encrypted: false });
            }
            else {
                storageItem = unknownStorageItem;
            }
            if (!storageItem.secret) {
                continue;
            }
            if (storageItem.encrypted && !passphrase) {
                continue;
            }
            if (storageItem.encrypted && passphrase) {
                try {
                    storageItem.secret = crypto_js__WEBPACK_IMPORTED_MODULE_6__.AES.decrypt(storageItem.secret, passphrase).toString(crypto_js__WEBPACK_IMPORTED_MODULE_6__.enc.Utf8);
                    storageItem.encrypted = false;
                }
                catch (error) {
                    continue;
                }
            }
            // storageItem.secret may be empty after decrypt with wrong
            // passphrase
            if (!storageItem.secret) {
                continue;
            }
            decryptedBackupData[hash] = storageItem;
        }
        return decryptedBackupData;
    });
}
function findAndUnlockKey(importData, keyId, password) {
    return __awaiter(this, void 0, void 0, function* () {
        if (!(keyId in importData)) {
            return null;
        }
        const key = importData[keyId];
        if (key.dataType !== "Key" || key.id !== keyId) {
            return null;
        }
        const rawHash = yield new Promise((resolve) => {
            const iframe = document.getElementById("argon-sandbox");
            const message = {
                action: "hash",
                value: password,
                salt: key.salt,
            };
            if (iframe) {
                window.addEventListener("message", (response) => {
                    resolve(response.data.response);
                });
                // @ts-expect-error bad typings
                iframe.contentWindow.postMessage(message, "*");
            }
        });
        // https://passlib.readthedocs.io/en/stable/lib/passlib.hash.argon2.html#format-algorithm
        const possibleHash = rawHash.split("$")[5];
        if (!possibleHash) {
            throw new Error("argon2 did not return a hash!");
        }
        // verify user password by comparing their password hash with the
        // hash of their password's hash
        const isCorrectPassword = yield new Promise((resolve) => {
            const iframe = document.getElementById("argon-sandbox");
            const message = {
                action: "verify",
                value: possibleHash,
                hash: key.hash,
            };
            if (iframe) {
                window.addEventListener("message", (response) => {
                    resolve(response.data.response);
                });
                // @ts-expect-error bad typings
                iframe.contentWindow.postMessage(message, "*");
            }
        });
        if (!isCorrectPassword) {
            return null;
        }
        return possibleHash;
    });
}
function getEntryDataFromOTPAuthPerLine(importCode) {
    return __awaiter(this, void 0, void 0, function* () {
        const lines = importCode.split("\n");
        const exportData = {};
        let failedCount = 0;
        let succeededCount = 0;
        for (let item of lines) {
            item = item.trim();
            if (item.startsWith("otpauth-migration:")) {
                const migrationData = (0,_models_migration__WEBPACK_IMPORTED_MODULE_5__.getOTPAuthPerLineFromOPTAuthMigration)(item);
                for (const line of migrationData) {
                    lines.push(line);
                }
                continue;
            }
            if (!item.startsWith("otpauth:")) {
                continue;
            }
            let uri = item.split("otpauth://")[1];
            let type = uri.substr(0, 4).toLowerCase();
            uri = uri.substr(5);
            let label = uri.split("?")[0];
            const parameterPart = uri.split("?")[1];
            if (!parameterPart) {
                failedCount++;
                continue;
            }
            else {
                let secret = "";
                let account;
                let issuer;
                let algorithm;
                let period;
                let digits;
                try {
                    label = decodeURIComponent(label);
                }
                catch (error) {
                    console.error(error);
                }
                if (label.indexOf(":") !== -1) {
                    issuer = label.split(":")[0];
                    account = label.split(":")[1];
                }
                else {
                    account = label;
                }
                const parameters = parameterPart.split("&");
                parameters.forEach((item) => {
                    const parameter = item.split("=");
                    if (parameter[0].toLowerCase() === "secret") {
                        secret = parameter[1];
                    }
                    else if (parameter[0].toLowerCase() === "issuer") {
                        try {
                            issuer = decodeURIComponent(parameter[1]);
                        }
                        catch (_a) {
                            issuer = parameter[1];
                        }
                        issuer = issuer.replace(/\+/g, " ");
                    } /* else if (parameter[0].toLowerCase() === "counter") {
                      let counter = Number(parameter[1]);
                      counter = isNaN(counter) || counter < 0 ? 0 : counter;
                    } */
                    else if (parameter[0].toLowerCase() === "period") {
                        period = Number(parameter[1]);
                        period =
                            isNaN(period) || period < 0 || period > 60 || 60 % period !== 0
                                ? undefined
                                : period;
                    }
                    else if (parameter[0].toLowerCase() === "digits") {
                        digits = Number(parameter[1]);
                        digits = isNaN(digits) ? 6 : digits;
                    }
                    else if (parameter[0].toLowerCase() === "algorithm") {
                        algorithm = parameter[1];
                    }
                });
                if (!secret) {
                    failedCount++;
                    continue;
                }
                else if (!/^[0-9a-f]+$/i.test(secret) &&
                    !/^[2-7a-z]+=*$/i.test(secret)) {
                    failedCount++;
                    continue;
                }
                else {
                    const hash = crypto.randomUUID();
                    if (!/^[2-7a-z]+=*$/i.test(secret) &&
                        /^[0-9a-f]+$/i.test(secret) &&
                        type === "totp") {
                        type = "hex";
                    }
                    else if (!/^[2-7a-z]+=*$/i.test(secret) &&
                        /^[0-9a-f]+$/i.test(secret) &&
                        type === "hotp") {
                        type = "hhex";
                    }
                    exportData[hash] = {
                        account,
                        hash,
                        issuer,
                        secret,
                        type,
                        encrypted: false,
                        index: 0,
                        counter: 0,
                        pinned: false,
                    };
                    if (period) {
                        exportData[hash].period = period;
                    }
                    if (digits) {
                        exportData[hash].digits = digits;
                    }
                    if (algorithm) {
                        exportData[hash].algorithm = algorithm;
                    }
                    succeededCount++;
                }
            }
        }
        return { exportData, failedCount, succeededCount };
    });
}


/***/ }),

/***/ "./src/models/encryption.ts":
/*!**********************************!*\
  !*** ./src/models/encryption.ts ***!
  \**********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   Encryption: () => (/* binding */ Encryption)
/* harmony export */ });
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! crypto-js */ "./node_modules/crypto-js/index.js");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto_js__WEBPACK_IMPORTED_MODULE_0__);

class Encryption {
    constructor(hash, keyId) {
        this.password = hash;
        this.keyId = keyId;
    }
    getEncryptedString(data) {
        if (!this.password) {
            return data;
        }
        else {
            return crypto_js__WEBPACK_IMPORTED_MODULE_0__.AES.encrypt(data, this.password).toString();
        }
    }
    decryptSecretString(secret) {
        try {
            const decryptedSecret = crypto_js__WEBPACK_IMPORTED_MODULE_0__.AES.decrypt(secret, this.password).toString(crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Utf8);
            if (!decryptedSecret) {
                return null;
            }
            if (decryptedSecret.length < 8) {
                return null;
            }
            if (!/^[a-z2-7]+=*$/i.test(decryptedSecret) &&
                !/^[0-9a-f]+$/i.test(decryptedSecret) &&
                !/^blz-/.test(decryptedSecret) &&
                !/^bliz-/.test(decryptedSecret) &&
                !/^stm-/.test(decryptedSecret)) {
                return null;
            }
            return decryptedSecret;
        }
        catch (error) {
            return null;
        }
    }
    decryptEncSecret(entry) {
        try {
            if (!entry.encData) {
                return null;
            }
            const decryptedData = crypto_js__WEBPACK_IMPORTED_MODULE_0__.AES.decrypt(entry.encData, this.password).toString(crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Utf8);
            if (!decryptedData) {
                return null;
            }
            return JSON.parse(decryptedData);
        }
        catch (error) {
            return null;
        }
    }
    getEncryptionStatus() {
        return this.password ? true : false;
    }
    updateEncryptionPassword(password) {
        this.password = password;
    }
    setEncryptionKeyId(id) {
        this.keyId = id;
    }
    getEncryptionKeyId() {
        return this.keyId;
    }
}


/***/ }),

/***/ "./src/models/key-utilities.ts":
/*!*************************************!*\
  !*** ./src/models/key-utilities.ts ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   KeyUtilities: () => (/* binding */ KeyUtilities)
/* harmony export */ });
/* harmony import */ var _otp__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./otp */ "./src/models/otp.ts");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! crypto-js */ "./node_modules/crypto-js/index.js");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(crypto_js__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var node_gost_crypto__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! node-gost-crypto */ "./node_modules/node-gost-crypto/index.js");
/* harmony import */ var node_gost_crypto__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(node_gost_crypto__WEBPACK_IMPORTED_MODULE_2__);



// Originally based on the JavaScript implementation as provided by Russell
// Sayers on his Tin Isles blog:
// http://blog.tinisles.com/2011/10/google-authenticator-one-time-password-algorithm-in-javascript/
// Rewrite with TypeScript by Sneezry https://github.com/Sneezry
class KeyUtilities {
    static dec2hex(s) {
        return (s < 15.5 ? "0" : "") + Math.round(s).toString(16);
    }
    static hex2dec(s) {
        return Number(`0x${s}`);
    }
    static hex2str(hex) {
        let str = "";
        for (let i = 0; i < hex.length; i += 2) {
            str += String.fromCharCode(this.hex2dec(hex.substr(i, 2)));
        }
        return str;
    }
    static leftpad(str, len, pad) {
        if (len + 1 >= str.length) {
            str = new Array(len + 1 - str.length).join(pad) + str;
        }
        return str;
    }
    static base32tohex(base32) {
        const base32chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
        let bits = "";
        let hex = "";
        let padding = 0;
        for (let i = 0; i < base32.length; i++) {
            if (base32.charAt(i) === "=") {
                bits += "00000";
                padding++;
            }
            else {
                const val = base32chars.indexOf(base32.charAt(i).toUpperCase());
                bits += this.leftpad(val.toString(2), 5, "0");
            }
        }
        for (let i = 0; i + 4 <= bits.length; i += 4) {
            const chunk = bits.substr(i, 4);
            hex = hex + Number(`0b${chunk}`).toString(16);
        }
        // if (hex.length % 2 && hex[hex.length - 1] === '0') {
        //   hex = hex.substr(0, hex.length - 1);
        // }
        switch (padding) {
            case 0:
                break;
            case 6:
                hex = hex.substr(0, hex.length - 8);
                break;
            case 4:
                hex = hex.substr(0, hex.length - 6);
                break;
            case 3:
                hex = hex.substr(0, hex.length - 4);
                break;
            case 1:
                hex = hex.substr(0, hex.length - 2);
                break;
            default:
                throw new Error("Invalid Base32 string");
        }
        return hex;
    }
    static base26(num) {
        const chars = "23456789BCDFGHJKMNPQRTVWXY";
        let output = "";
        const len = 5;
        for (let i = 0; i < len; i++) {
            output += chars[num % chars.length];
            num = Math.floor(num / chars.length);
        }
        if (output.length < len) {
            output = new Array(len - output.length + 1).join(chars[0]) + output;
        }
        return output;
    }
    static cryptoJsWordArrayToUint8Array(wordArray) {
        const l = wordArray.sigBytes;
        const words = wordArray.words;
        const result = new Uint8Array(l);
        let i = 0 /*dst*/, j = 0; /*src*/
        while (i < l) {
            // here i is a multiple of 4
            const w = words[j++];
            result[i++] = (w & 0xff000000) >>> 24;
            if (i === l)
                break;
            result[i++] = (w & 0x00ff0000) >>> 16;
            if (i === l)
                break;
            result[i++] = (w & 0x0000ff00) >>> 8;
            if (i === l)
                break;
            result[i++] = w & 0x000000ff;
        }
        return result;
    }
    static generate(type, secret, counter, period, len, algorithm, clockOffset) {
        secret = secret.replace(/\s/g, "");
        if (!len) {
            len = 6;
        }
        let b26 = false;
        let key;
        switch (type) {
            case _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.totp:
            case _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.hotp:
                key = this.base32tohex(secret);
                break;
            case _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.hex:
            case _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.hhex:
                key = secret;
                break;
            case _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.battle:
                key = this.base32tohex(secret);
                len = 8;
                break;
            case _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.steam:
                key = this.base32tohex(secret);
                len = 10;
                b26 = true;
                break;
            default:
                key = this.base32tohex(secret);
        }
        if (!key) {
            throw new Error("Invalid secret key");
        }
        if (type !== _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.hotp && type !== _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.hhex) {
            let epoch = Math.round(new Date().getTime() / 1000.0);
            if (clockOffset) {
                epoch = epoch + Number(clockOffset);
            }
            counter = Math.floor(epoch / period);
        }
        const time = this.leftpad(this.dec2hex(counter), 16, "0");
        if (key.length % 2 === 1) {
            if (key.substr(-1) === "0") {
                key = key.substr(0, key.length - 1);
            }
            else {
                key += "0";
            }
        }
        let alg;
        let gostCipher;
        let hmacObj;
        switch (algorithm) {
            case _otp__WEBPACK_IMPORTED_MODULE_0__.OTPAlgorithm.SHA256:
                hmacObj = crypto_js__WEBPACK_IMPORTED_MODULE_1__.HmacSHA256(crypto_js__WEBPACK_IMPORTED_MODULE_1__.enc.Hex.parse(time), crypto_js__WEBPACK_IMPORTED_MODULE_1__.enc.Hex.parse(key));
                break;
            case _otp__WEBPACK_IMPORTED_MODULE_0__.OTPAlgorithm.SHA512:
                hmacObj = crypto_js__WEBPACK_IMPORTED_MODULE_1__.HmacSHA512(crypto_js__WEBPACK_IMPORTED_MODULE_1__.enc.Hex.parse(time), crypto_js__WEBPACK_IMPORTED_MODULE_1__.enc.Hex.parse(key));
                break;
            case _otp__WEBPACK_IMPORTED_MODULE_0__.OTPAlgorithm.GOST3411_2012_256:
            case _otp__WEBPACK_IMPORTED_MODULE_0__.OTPAlgorithm.GOST3411_2012_512:
                alg = {
                    mode: "HMAC",
                    name: "GOST R 34.11",
                    version: 2012,
                    length: _otp__WEBPACK_IMPORTED_MODULE_0__.OTPUtil.getOTPAlgorithmSpec(algorithm).length,
                };
                gostCipher = node_gost_crypto__WEBPACK_IMPORTED_MODULE_2__.gostEngine.getGostDigest(alg);
                hmacObj = crypto_js__WEBPACK_IMPORTED_MODULE_1__.lib.WordArray.create(gostCipher.sign(this.cryptoJsWordArrayToUint8Array(crypto_js__WEBPACK_IMPORTED_MODULE_1__.enc.Hex.parse(key)), this.cryptoJsWordArrayToUint8Array(crypto_js__WEBPACK_IMPORTED_MODULE_1__.enc.Hex.parse(time))));
                break;
            default:
                hmacObj = crypto_js__WEBPACK_IMPORTED_MODULE_1__.HmacSHA1(crypto_js__WEBPACK_IMPORTED_MODULE_1__.enc.Hex.parse(time), crypto_js__WEBPACK_IMPORTED_MODULE_1__.enc.Hex.parse(key));
                break;
        }
        const hmac = crypto_js__WEBPACK_IMPORTED_MODULE_1__.enc.Hex.stringify(hmacObj);
        const offset = this.hex2dec(hmac.substring(hmac.length - 1));
        let otp = (this.hex2dec(hmac.substr(offset * 2, 8)) & this.hex2dec("7fffffff")) +
            "";
        if (b26) {
            return this.base26(Number(otp));
        }
        if (otp.length < len) {
            otp = new Array(len - otp.length + 1).join("0") + otp;
        }
        return otp.substr(otp.length - len, len).toString();
    }
}


/***/ }),

/***/ "./src/models/migration.ts":
/*!*********************************!*\
  !*** ./src/models/migration.ts ***!
  \*********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   getOTPAuthPerLineFromOPTAuthMigration: () => (/* binding */ getOTPAuthPerLineFromOPTAuthMigration)
/* harmony export */ });
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! crypto-js */ "./node_modules/crypto-js/index.js");
/* harmony import */ var crypto_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto_js__WEBPACK_IMPORTED_MODULE_0__);

function byteArray2Base32(bytes) {
    const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
    const len = bytes.length;
    let result = "";
    let high = 0, low = 0, sh = 0, hasDataInLow = false;
    for (let i = 0; i < len; i += 5) {
        hasDataInLow = true;
        high = 0xf8 & bytes[i];
        result += chars.charAt(high >> 3);
        low = 0x07 & bytes[i];
        sh = 2;
        if (i + 1 < len) {
            high = 0xc0 & bytes[i + 1];
            result += chars.charAt((low << 2) + (high >> 6));
            result += chars.charAt((0x3e & bytes[i + 1]) >> 1);
            low = bytes[i + 1] & 0x01;
            sh = 4;
        }
        if (i + 2 < len) {
            high = 0xf0 & bytes[i + 2];
            result += chars.charAt((low << 4) + (high >> 4));
            low = 0x0f & bytes[i + 2];
            sh = 1;
        }
        if (i + 3 < len) {
            high = 0x80 & bytes[i + 3];
            result += chars.charAt((low << 1) + (high >> 7));
            result += chars.charAt((0x7c & bytes[i + 3]) >> 2);
            low = 0x03 & bytes[i + 3];
            sh = 3;
        }
        if (i + 4 < len) {
            hasDataInLow = false;
            high = 0xe0 & bytes[i + 4];
            result += chars.charAt((low << 3) + (high >> 5));
            result += chars.charAt(0x1f & bytes[i + 4]);
            low = 0;
            sh = 0;
        }
    }
    if (hasDataInLow) {
        result += chars.charAt(low << sh);
    }
    const padlen = 8 - (result.length % 8);
    return result + (padlen < 8 ? Array(padlen + 1).join("=") : "");
}
function wordArrayToByteArray(wordArray) {
    const byteArray = [];
    for (let i = 0; i < wordArray.words.length; ++i) {
        const word = wordArray.words[i];
        for (let j = 3; j >= 0; --j) {
            byteArray.push((word >> (8 * j)) & 0xff);
        }
    }
    byteArray.length = wordArray.sigBytes;
    return byteArray;
}
function byteArray2String(bytes) {
    return String.fromCharCode.apply(null, bytes);
}
function subBytesArray(bytes, start, length) {
    const subBytes = [];
    for (let i = 0; i < length; i++) {
        subBytes.push(bytes[start + i]);
    }
    return subBytes;
}
function getOTPAuthPerLineFromOPTAuthMigration(migrationUri) {
    if (!migrationUri.startsWith("otpauth-migration:")) {
        return [];
    }
    const base64Data = decodeURIComponent(migrationUri.split("data=")[1]);
    const wordArrayData = crypto_js__WEBPACK_IMPORTED_MODULE_0__.enc.Base64.parse(base64Data);
    const byteData = wordArrayToByteArray(wordArrayData);
    const lines = [];
    let offset = 0;
    while (offset < byteData.length) {
        if (byteData[offset] !== 10) {
            break;
        }
        const lineLength = byteData[offset + 1];
        const secretStart = offset + 4;
        const secretLength = byteData[offset + 3];
        const secretBytes = subBytesArray(byteData, secretStart, secretLength);
        const secret = byteArray2Base32(secretBytes);
        const accountStart = secretStart + secretLength + 2;
        const accountLength = byteData[secretStart + secretLength + 1];
        const accountBytes = subBytesArray(byteData, accountStart, accountLength);
        const account = byteArray2String(accountBytes);
        const isserStart = accountStart + accountLength + 2;
        const isserLength = byteData[accountStart + accountLength + 1];
        const issuerBytes = subBytesArray(byteData, isserStart, isserLength);
        const issuer = byteArray2String(issuerBytes);
        const algorithm = ["SHA1", "SHA1", "SHA256", "SHA512", "MD5"][byteData[isserStart + isserLength + 1]];
        const digits = [6, 6, 8][byteData[isserStart + isserLength + 3]];
        const type = ["totp", "hotp", "totp"][byteData[isserStart + isserLength + 5]];
        let line = `otpauth://${type}/${account}?secret=${secret}&issuer=${issuer}&algorithm=${algorithm}&digits=${digits}`;
        if (type === "hotp") {
            let counter = 1;
            if (isserStart + isserLength + 7 <= lineLength) {
                counter = byteData[isserStart + isserLength + 7];
            }
            line += `&counter=${counter}`;
        }
        lines.push(line);
        offset += lineLength + 2;
    }
    return lines;
}


/***/ }),

/***/ "./src/models/otp.ts":
/*!***************************!*\
  !*** ./src/models/otp.ts ***!
  \***************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   CodeState: () => (/* binding */ CodeState),
/* harmony export */   DataType: () => (/* binding */ DataType),
/* harmony export */   OTPAlgorithm: () => (/* binding */ OTPAlgorithm),
/* harmony export */   OTPEntry: () => (/* binding */ OTPEntry),
/* harmony export */   OTPType: () => (/* binding */ OTPType),
/* harmony export */   OTPUtil: () => (/* binding */ OTPUtil)
/* harmony export */ });
/* harmony import */ var _key_utilities__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./key-utilities */ "./src/models/key-utilities.ts");
/* harmony import */ var _settings__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./settings */ "./src/models/settings.ts");
/* harmony import */ var _storage__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./storage */ "./src/models/storage.ts");
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};



var OTPType;
(function (OTPType) {
    OTPType[OTPType["totp"] = 1] = "totp";
    OTPType[OTPType["hotp"] = 2] = "hotp";
    OTPType[OTPType["battle"] = 3] = "battle";
    OTPType[OTPType["steam"] = 4] = "steam";
    OTPType[OTPType["hex"] = 5] = "hex";
    OTPType[OTPType["hhex"] = 6] = "hhex";
})(OTPType || (OTPType = {}));
var CodeState;
(function (CodeState) {
    CodeState["Invalid"] = "-1";
    CodeState["Encrypted"] = "-2";
})(CodeState || (CodeState = {}));
var OTPAlgorithm;
(function (OTPAlgorithm) {
    OTPAlgorithm[OTPAlgorithm["SHA1"] = 1] = "SHA1";
    OTPAlgorithm[OTPAlgorithm["SHA256"] = 2] = "SHA256";
    OTPAlgorithm[OTPAlgorithm["SHA512"] = 3] = "SHA512";
    OTPAlgorithm[OTPAlgorithm["GOST3411_2012_256"] = 4] = "GOST3411_2012_256";
    OTPAlgorithm[OTPAlgorithm["GOST3411_2012_512"] = 5] = "GOST3411_2012_512";
})(OTPAlgorithm || (OTPAlgorithm = {}));
var DataType;
(function (DataType) {
    DataType["OTPStorage"] = "OTPStorage";
    DataType["EncOTPStorage"] = "EncOTPStorage";
    DataType["Key"] = "Key";
})(DataType || (DataType = {}));
class OTPUtil {
    static getOTPAlgorithmSpec(otpAlgorithm) {
        switch (otpAlgorithm) {
            case OTPAlgorithm.GOST3411_2012_256:
                return { length: 256 };
            case OTPAlgorithm.GOST3411_2012_512:
                return { length: 512 };
            default:
                return { length: 0 };
        }
    }
}
class OTPEntry {
    constructor(entry, encryption) {
        this.code = "&bull;&bull;&bull;&bull;&bull;&bull;";
        this.encryption = encryption;
        this.index = entry.index;
        if ("keyId" in entry) {
            this.encData = entry.encData;
            this.secret = null;
            this.hash = entry.hash;
            this.keyId = entry.keyId;
            // defaults
            this.type = OTPType.totp;
            this.issuer = "";
            this.account = "";
            this.counter = 0;
            this.period = 30;
            this.digits = 6;
            this.algorithm = OTPAlgorithm.SHA1;
            this.pinned = false;
            return;
        }
        else if (entry.encrypted) {
            // v2 encryption backwards compat logic
            this.secret = null;
            this.encSecret = entry.secret;
        }
        else {
            this.secret = entry.secret;
        }
        this.type = entry.type;
        if (entry.issuer) {
            this.issuer = entry.issuer;
        }
        else {
            this.issuer = "";
        }
        if (entry.account) {
            this.account = entry.account;
        }
        else {
            this.account = "";
        }
        if (entry.hash) {
            this.hash = entry.hash;
        }
        else {
            this.hash = crypto.randomUUID();
        }
        if (entry.counter) {
            this.counter = entry.counter;
        }
        else {
            this.counter = 0;
        }
        if (entry.digits) {
            this.digits = entry.digits;
        }
        else {
            this.digits = 6;
        }
        if (entry.algorithm) {
            this.algorithm = entry.algorithm;
        }
        else {
            this.algorithm = OTPAlgorithm.SHA1;
        }
        if (entry.pinned) {
            this.pinned = entry.pinned;
        }
        else {
            this.pinned = false;
        }
        if (this.type === OTPType.totp && entry.period) {
            this.period = entry.period;
        }
        else {
            this.period = 30;
        }
        if (this.type !== OTPType.hotp && this.type !== OTPType.hhex) {
            this.generate();
        }
    }
    create() {
        return __awaiter(this, void 0, void 0, function* () {
            yield _storage__WEBPACK_IMPORTED_MODULE_2__.EntryStorage.add(this);
            return;
        });
    }
    update() {
        return __awaiter(this, void 0, void 0, function* () {
            yield _storage__WEBPACK_IMPORTED_MODULE_2__.EntryStorage.update(this);
            return;
        });
    }
    changeEncryption(encryption) {
        if (!this.secret) {
            return;
        }
        this.encryption = encryption;
        return;
    }
    applyEncryption(encryption) {
        if (!encryption || !encryption.getEncryptionStatus()) {
            return;
        }
        if (this.encSecret) {
            // v2 encryption
            this.secret = encryption.decryptSecretString(this.encSecret);
            if (this.secret) {
                this.encSecret = "";
            }
            return;
        }
        // check if its a rawotpstorage
        const decryptedData = encryption.decryptEncSecret(this);
        if (decryptedData === null) {
            return;
        }
        if ((decryptedData === null || decryptedData === void 0 ? void 0 : decryptedData.dataType) !== "OTPStorage") {
            console.warn("Decrypt successful, but malformed encData!", this.hash);
        }
        if (decryptedData.hash !== this.hash) {
            console.warn("Decrypt successful, but hash mismatch!", this.hash, decryptedData.hash);
        }
        this.account = decryptedData.account || "";
        // @ts-expect-error need a better way to do this
        this.algorithm = OTPAlgorithm[decryptedData.algorithm] || OTPAlgorithm.SHA1;
        this.counter = decryptedData.counter || 0;
        this.digits = decryptedData.digits || 6;
        this.issuer = decryptedData.issuer || "";
        this.period = decryptedData.period || 30;
        this.pinned = decryptedData.pinned || false;
        this.secret = decryptedData.secret;
        // @ts-expect-error need a better way to do this
        this.type = OTPType[decryptedData.type] || OTPType.totp;
        if (this.type !== OTPType.hotp && this.type !== OTPType.hhex) {
            this.generate();
        }
        this.encryption = encryption;
        this.encData = "";
    }
    delete() {
        return __awaiter(this, void 0, void 0, function* () {
            yield _storage__WEBPACK_IMPORTED_MODULE_2__.EntryStorage.delete(this);
            return;
        });
    }
    next() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.type !== OTPType.hotp && this.type !== OTPType.hhex) {
                return;
            }
            this.generate();
            if (this.secret !== null) {
                this.counter++;
                yield this.update();
            }
            return;
        });
    }
    genUUID() {
        this.hash = crypto.randomUUID();
    }
    generate() {
        const offset = _settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.items ? _settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.items.offset : 0;
        if (!_settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.items) {
            // browser storage is async, so we need to wait for it to load
            // and re-generate the code
            // don't change the code to async, it will break the mutation
            // for Accounts store to export data
            _settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.updateItems().then(() => {
                this.generate();
            });
        }
        if (!this.secret && !this.encData) {
            this.code = CodeState.Invalid;
        }
        else if (!this.secret) {
            this.code = CodeState.Encrypted;
        }
        else {
            try {
                this.code = _key_utilities__WEBPACK_IMPORTED_MODULE_0__.KeyUtilities.generate(this.type, this.secret, this.counter, this.period, this.digits, this.algorithm, offset);
            }
            catch (error) {
                this.code = CodeState.Invalid;
                console.warn("Invalid secret.", error);
            }
        }
    }
}


/***/ }),

/***/ "./src/models/settings.ts":
/*!********************************!*\
  !*** ./src/models/settings.ts ***!
  \********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   StorageLocation: () => (/* binding */ StorageLocation),
/* harmony export */   UserSettings: () => (/* binding */ UserSettings)
/* harmony export */ });
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var StorageLocation;
(function (StorageLocation) {
    StorageLocation["Sync"] = "sync";
    StorageLocation["Local"] = "local";
})(StorageLocation || (StorageLocation = {}));
// Maybe we can have a better way to define this
const LocalUserSettingsDataKeys = [
    "driveEncrypted",
    "driveFolder",
    "driveRefreshToken",
    "driveRevoked",
    "driveToken",
    "dropboxEncrypted",
    "dropboxRevoked",
    "dropboxToken",
    "lastRemindingBackupTime",
    "offset",
    "oneDriveBusiness",
    "oneDriveEncrypted",
    "oneDriveRevoked",
    "oneDriveRefreshToken",
    "oneDriveToken",
    "storageLocation",
];
class UserSettings {
    static updateItems() {
        return __awaiter(this, void 0, void 0, function* () {
            UserSettings.items = yield UserSettings.getAllItems();
        });
    }
    static convertFromLocalStorage(data, location) {
        return __awaiter(this, void 0, void 0, function* () {
            const settings = {};
            for (const key in data) {
                if (isBooleanOption(key)) {
                    settings[key] = data[key] === "true";
                }
                else if (isNumberOption(key)) {
                    settings[key] = Number(data[key]);
                }
                else if (isJSONOption(key)) {
                    settings[key] = JSON.parse(data[key]);
                }
                else {
                    settings[key] = data[key];
                }
            }
            settings.storageLocation = location;
            UserSettings.items = settings;
            yield UserSettings.commitItems();
        });
    }
    static commitItems() {
        return __awaiter(this, void 0, void 0, function* () {
            const storageLocation = UserSettings.items.storageLocation || StorageLocation.Local;
            if (storageLocation === StorageLocation.Local) {
                yield chrome.storage[storageLocation].set({
                    // JSON.parse(JSON.stringify()) strips functions (e.g. getItem, setItem, ...) which may have been added to the object.
                    // Without this, a crash may occur as chrome.storage throws an error when trying to serialize a function.
                    UserSettings: JSON.parse(JSON.stringify(UserSettings.items)),
                });
            }
            else {
                const { syncableSettings, localSettings } = UserSettings.splitSettings(UserSettings.items);
                yield Promise.all([
                    chrome.storage[StorageLocation.Local].set({
                        UserSettings: JSON.parse(JSON.stringify(localSettings)),
                    }),
                    chrome.storage[StorageLocation.Sync].set({
                        UserSettings: JSON.parse(JSON.stringify(syncableSettings)),
                    }),
                ]);
            }
            yield UserSettings.updateItems();
        });
    }
    static removeItem(key) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const localSettings = yield UserSettings.getStorageData(StorageLocation.Local);
            const storageLocation = localSettings.storageLocation || StorageLocation.Local;
            const location = LocalUserSettingsDataKeys.includes(key)
                ? StorageLocation.Local
                : storageLocation;
            const storageData = ((_a = (yield chrome.storage[location].get("UserSettings"))) === null || _a === void 0 ? void 0 : _a.UserSettings) || {};
            delete storageData[key];
            UserSettings.items = storageData;
            yield UserSettings.commitItems();
        });
    }
    static getStorageData(location) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const storageData = ((_a = (yield chrome.storage[location].get("UserSettings"))) === null || _a === void 0 ? void 0 : _a.UserSettings) || {};
            return storageData;
        });
    }
    static splitSettings(storageData) {
        const syncableSettings = Object.assign({}, storageData);
        const localSettings = Object.assign({}, storageData);
        let key;
        for (key in storageData) {
            if (LocalUserSettingsDataKeys.includes(key)) {
                delete syncableSettings[key];
            }
            else {
                delete localSettings[key];
            }
        }
        return {
            syncableSettings,
            localSettings,
        };
    }
    static getAllItems() {
        return __awaiter(this, void 0, void 0, function* () {
            const localSettings = yield UserSettings.getStorageData(StorageLocation.Local);
            const storageLocation = localSettings.storageLocation || StorageLocation.Local;
            if (storageLocation === StorageLocation.Local) {
                return localSettings;
            }
            const syncableSettings = yield UserSettings.getStorageData(StorageLocation.Sync);
            return Object.assign(Object.assign({}, syncableSettings), localSettings);
        });
    }
}
UserSettings.items = {};

function isBooleanOption(key) {
    return [
        "autofill",
        "driveEncrypted",
        "driveRevoked",
        "dropboxEncrypted",
        "dropboxRevoked",
        "enableContextMenu",
        "oneDriveBusiness",
        "oneDriveEncrypted",
        "oneDriveRevoked",
        "smartFilter",
    ].includes(key);
}
function isNumberOption(key) {
    return ["autolock", "lastRemindingBackupTime", "offset", "zoom"].includes(key);
}
function isJSONOption(key) {
    return ["advisorIgnoreList"].includes(key);
}


/***/ }),

/***/ "./src/models/storage.ts":
/*!*******************************!*\
  !*** ./src/models/storage.ts ***!
  \*******************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   BrowserStorage: () => (/* binding */ BrowserStorage),
/* harmony export */   EntryStorage: () => (/* binding */ EntryStorage),
/* harmony export */   ManagedStorage: () => (/* binding */ ManagedStorage),
/* harmony export */   isOldKey: () => (/* binding */ isOldKey)
/* harmony export */ });
/* harmony import */ var _otp__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./otp */ "./src/models/otp.ts");
/* harmony import */ var _settings__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./settings */ "./src/models/settings.ts");
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};



class BrowserStorage {
    static getStorageLocation() {
        return __awaiter(this, void 0, void 0, function* () {
            yield _settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.updateItems();
            const managedLocation = yield ManagedStorage.get("storageArea");
            if (managedLocation === _settings__WEBPACK_IMPORTED_MODULE_1__.StorageLocation.Sync ||
                managedLocation === _settings__WEBPACK_IMPORTED_MODULE_1__.StorageLocation.Local) {
                return new Promise((resolve) => {
                    if (_settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.items.storageLocation !== managedLocation) {
                        _settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.items.storageLocation = managedLocation;
                        _settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.commitItems();
                    }
                    resolve(managedLocation);
                    return;
                });
            }
            else if (_settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.items.storageLocation !== _settings__WEBPACK_IMPORTED_MODULE_1__.StorageLocation.Sync &&
                _settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.items.storageLocation !== _settings__WEBPACK_IMPORTED_MODULE_1__.StorageLocation.Local) {
                return new Promise((resolve, reject) => {
                    let amountSync;
                    let amountLocal;
                    chrome.storage.local.get((local) => {
                        amountLocal = Object.keys(local).length;
                        if (local.LocalStorage) {
                            amountLocal--;
                        }
                        try {
                            chrome.storage.sync.get((sync) => {
                                amountSync = Object.keys(sync).length;
                                // If storage location can't be found try to auto-detect storage
                                // location
                                if (amountLocal > amountSync && amountSync === 0) {
                                    _settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.items.storageLocation = _settings__WEBPACK_IMPORTED_MODULE_1__.StorageLocation.Local;
                                }
                                else if (amountLocal < amountSync && amountLocal === 0) {
                                    _settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.items.storageLocation = _settings__WEBPACK_IMPORTED_MODULE_1__.StorageLocation.Sync;
                                }
                                else {
                                    // Use default
                                    _settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.items.storageLocation = _settings__WEBPACK_IMPORTED_MODULE_1__.StorageLocation.Sync;
                                }
                                _settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.commitItems();
                                resolve(_settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.items.storageLocation);
                                return;
                            });
                        }
                        catch (error) {
                            reject(error);
                            return;
                        }
                    });
                });
            }
            else {
                return new Promise((resolve) => {
                    resolve(_settings__WEBPACK_IMPORTED_MODULE_1__.UserSettings.items.storageLocation || _settings__WEBPACK_IMPORTED_MODULE_1__.StorageLocation.Sync);
                    return;
                });
            }
        });
    }
    // TODO: promise this
    static get() {
        return __awaiter(this, void 0, void 0, function* () {
            const storageLocation = yield this.getStorageLocation();
            const removeOtherData = function (items) {
                delete items.key;
                delete items.LocalStorage;
                for (const itemId in items) {
                    const item = items[itemId];
                    if (item !== null &&
                        typeof item === "object" &&
                        "dataType" in item &&
                        item.dataType === "Key") {
                        delete items[itemId];
                    }
                }
            };
            let items = {};
            if (storageLocation === "local") {
                items = yield chrome.storage.local.get();
            }
            else if (storageLocation === "sync") {
                items = yield chrome.storage.sync.get();
            }
            removeOtherData(items);
            return items;
        });
    }
    static getKeys() {
        return __awaiter(this, void 0, void 0, function* () {
            const storageLocation = yield this.getStorageLocation();
            const data = (yield chrome.storage[storageLocation].get());
            // Return old key first, so we know to run a migration
            if (data && typeof data === "object" && "key" in data) {
                if (isOldKey(data.key)) {
                    return data.key;
                }
                else {
                    console.error("'key' is malformed!");
                }
            }
            const keys = [];
            if (data && typeof data === "object") {
                for (const record in data) {
                    const key = data[record];
                    if (isKey(key)) {
                        keys.push(key);
                    }
                }
            }
            return keys;
        });
    }
    static set(data) {
        return __awaiter(this, void 0, void 0, function* () {
            const storageLocation = yield this.getStorageLocation();
            if (storageLocation === _settings__WEBPACK_IMPORTED_MODULE_1__.StorageLocation.Local) {
                yield chrome.storage.local.set(data);
            }
            else if (storageLocation === _settings__WEBPACK_IMPORTED_MODULE_1__.StorageLocation.Sync) {
                yield chrome.storage.sync.set(data);
            }
            return;
        });
    }
    static remove(data) {
        return __awaiter(this, void 0, void 0, function* () {
            const storageLocation = yield this.getStorageLocation();
            if (storageLocation === "local") {
                yield chrome.storage.local.remove(data);
            }
            else if (storageLocation === "sync") {
                yield chrome.storage.sync.remove(data);
            }
            return;
        });
    }
    // Use for Chrome only.
    // https://github.com/Authenticator-Extension/Authenticator/issues/412
    static clearLogs() {
        return __awaiter(this, void 0, void 0, function* () {
            const storageLocation = yield this.getStorageLocation();
            if (storageLocation === "local") {
                const data = yield chrome.storage.local.get();
                yield chrome.storage.local.clear();
                yield chrome.storage.local.set(data);
            }
            else if (storageLocation === "sync") {
                const data = yield chrome.storage.sync.get();
                yield chrome.storage.sync.clear();
                yield chrome.storage.sync.set(data);
            }
        });
    }
}
function isOldKey(key) {
    return Boolean(key &&
        typeof key === "object" &&
        "enc" in key &&
        "hash" in key &&
        key.enc &&
        key.hash &&
        typeof key.enc === "string" &&
        typeof key.hash === "string");
}
function isKey(key) {
    return Boolean(key &&
        typeof key === "object" &&
        "dataType" in key &&
        "id" in key &&
        "salt" in key &&
        key.dataType === "Key" &&
        key.id &&
        key.salt &&
        typeof key.id === "string" &&
        typeof key.salt === "string");
}
class EntryStorage {
    static getOTPStorageFromEntry(entry, unencrypted) {
        var _a, _b, _c;
        let secret;
        if (!entry.secret && entry.encData && entry.keyId) {
            return {
                dataType: _otp__WEBPACK_IMPORTED_MODULE_0__.DataType.EncOTPStorage,
                keyId: entry.keyId,
                data: entry.encData,
                index: entry.index,
            };
        }
        else if (entry.secret) {
            secret = entry.secret;
        }
        else {
            secret = "";
            console.warn("Invalid entry", entry);
        }
        let encrypted = ((_a = entry.encryption) === null || _a === void 0 ? void 0 : _a.getEncryptionStatus()) || false;
        if (unencrypted && entry.secret) {
            secret = entry.secret;
            encrypted = false;
        }
        const storageItem = {
            encrypted,
            hash: entry.hash,
            index: entry.index,
            type: _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType[entry.type],
            secret,
        };
        if (entry.pinned) {
            storageItem.pinned = true;
        }
        if (entry.type === _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.hotp || entry.type === _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.hhex) {
            storageItem.counter = entry.counter;
        }
        if (entry.period && entry.period !== 30) {
            storageItem.period = entry.period;
        }
        if (entry.issuer) {
            storageItem.issuer = entry.issuer;
        }
        if (entry.account) {
            storageItem.account = entry.account;
        }
        if (entry.digits && entry.digits !== 6) {
            storageItem.digits = entry.digits;
        }
        if (entry.algorithm && entry.algorithm !== _otp__WEBPACK_IMPORTED_MODULE_0__.OTPAlgorithm.SHA1) {
            storageItem.algorithm = _otp__WEBPACK_IMPORTED_MODULE_0__.OTPAlgorithm[entry.algorithm];
        }
        if ((_b = entry.encryption) === null || _b === void 0 ? void 0 : _b.getEncryptionKeyId()) {
            storageItem.keyId = entry.encryption.getEncryptionKeyId();
        }
        storageItem.dataType = _otp__WEBPACK_IMPORTED_MODULE_0__.DataType.OTPStorage;
        if (!unencrypted &&
            encrypted &&
            ((_c = entry.encryption) === null || _c === void 0 ? void 0 : _c.getEncryptionStatus()) &&
            entry.encryption.getEncryptionKeyId()) {
            const encData = entry.encryption.getEncryptedString(JSON.stringify(storageItem));
            return {
                dataType: _otp__WEBPACK_IMPORTED_MODULE_0__.DataType.EncOTPStorage,
                data: encData,
                keyId: entry.encryption.getEncryptionKeyId(),
                index: entry.index,
            };
        }
        else if (encrypted) {
            console.error("Could not encrypt malformed entry: ", entry);
        }
        return storageItem;
    }
    static ensureUniqueIndex(data) {
        const tempEntryArray = [];
        for (const hash of Object.keys(data)) {
            if (hash === "UserSettings" ||
                data[hash].dataType === "Key" ||
                !this.isValidEntry(data, hash)) {
                continue;
            }
            tempEntryArray.push([hash, data[hash]]);
        }
        tempEntryArray.sort((a, b) => {
            return a[1].index - b[1].index;
        });
        let i = 0;
        const newData = tempEntryArray.reduce((previous, entry) => {
            const mergedData = Object.assign(Object.assign({}, previous), { [entry[0]]: Object.assign(Object.assign({}, entry[1]), { index: i }) });
            i += 1;
            return mergedData;
        }, {});
        return newData;
    }
    static isOTPStorage(entry) {
        if (typeof entry !== "object") {
            return false;
        }
        if (!entry || !("secret" in entry || "data" in entry)) {
            return false;
        }
        return true;
    }
    static isValidEntry(_data, hash) {
        if (typeof _data[hash] !== "object") {
            console.log('Key "' + hash + '" is not an object');
            return false;
        }
        else {
            if (!this.isOTPStorage(_data[hash])) {
                console.log('Key "' + hash + '" is not OTPStorage');
                return false;
            }
            return true;
        }
    }
    static hasEncryptionKey() {
        return __awaiter(this, void 0, void 0, function* () {
            const keys = yield BrowserStorage.getKeys();
            if (isOldKey(keys)) {
                return true;
            }
            else {
                return keys.length !== 0;
            }
        });
    }
    static getExport(data, encrypted) {
        try {
            const exportData = {};
            for (const entry of data) {
                // Skip unable-decrypted data
                if (entry.code === _otp__WEBPACK_IMPORTED_MODULE_0__.CodeState.Encrypted || !entry.secret) {
                    continue;
                }
                exportData[entry.hash] = this.getOTPStorageFromEntry(entry, !encrypted);
            }
            return exportData;
        }
        catch (error) {
            return error;
        }
    }
    static backupGetExport(encryption, encrypted) {
        return __awaiter(this, void 0, void 0, function* () {
            const _data = yield BrowserStorage.get();
            for (const hash of Object.keys(_data)) {
                if (hash === "UserSettings" ||
                    _data[hash].dataType === "Key" ||
                    !this.isValidEntry(_data, hash)) {
                    delete _data[hash];
                    continue;
                }
                const entry = _data[hash];
                // TODO: fix this
                if (entry.dataType === "EncOTPStorage") {
                    continue;
                }
                // remove unnecessary fields
                if (!(entry.type === _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType[_otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.hotp]) &&
                    !(entry.type === _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType[_otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.hhex])) {
                    delete entry.counter;
                }
                if (entry.period === 30) {
                    delete entry.period;
                }
                if (!entry.issuer) {
                    delete entry.issuer;
                }
                if (!entry.account) {
                    delete entry.account;
                }
                if (entry.digits === 6) {
                    delete entry.digits;
                }
                if (entry.algorithm === _otp__WEBPACK_IMPORTED_MODULE_0__.OTPAlgorithm[_otp__WEBPACK_IMPORTED_MODULE_0__.OTPAlgorithm.SHA1]) {
                    delete entry.algorithm;
                }
                delete entry.pinned;
                if (!encrypted) {
                    // decrypt the data to export
                    if (entry.encrypted) {
                        const decryptedSecret = encryption.decryptSecretString(entry.secret);
                        if (decryptedSecret !== entry.secret && decryptedSecret !== null) {
                            entry.secret = decryptedSecret;
                            entry.encrypted = false;
                        }
                    }
                    // we need correct hash
                    if (hash !== entry.hash) {
                        _data[entry.hash] = entry;
                        delete _data[hash];
                    }
                }
            }
            if (encryption.getEncryptionStatus()) {
                const keys = yield BrowserStorage.getKeys();
                if (isOldKey(keys)) {
                    Object.assign(_data, { key: keys });
                }
                else {
                    for (const key of keys) {
                        Object.assign(_data, { [key.id]: key });
                    }
                }
            }
            return _data;
        });
    }
    static import(encryption, data) {
        return __awaiter(this, void 0, void 0, function* () {
            let _data = yield BrowserStorage.get();
            for (const hash of Object.keys(data)) {
                // never trust data import from user
                // data must be decrypted before calling this method
                if (!data[hash].secret || data[hash].encrypted) {
                    // TODO: we need give a failed warning
                    continue;
                }
                const rawAlgorithm = data[hash].algorithm;
                const entryData = {
                    type: parseInt(data[hash].type) || _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType[_otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.totp],
                    index: data[hash].index || 0,
                    issuer: data[hash].issuer || "",
                    account: data[hash].account || "",
                    encrypted: false,
                    secret: data[hash].secret,
                    counter: data[hash].counter || 0,
                    period: data[hash].period || 30,
                    digits: data[hash].digits || 6,
                    algorithm: rawAlgorithm
                        ? parseInt(rawAlgorithm)
                        : _otp__WEBPACK_IMPORTED_MODULE_0__.OTPAlgorithm.SHA1,
                    pinned: data[hash].pinned || false,
                    hash: data[hash].hash || hash,
                };
                if (isNaN(entryData.period) || entryData.period <= 0) {
                    entryData.period = 30;
                }
                // If invalid digits, then use default.
                if (entryData.digits > 10 || entryData.digits < 1) {
                    entryData.digits = 6;
                }
                // If invalid algorithm, then use default
                if (!_otp__WEBPACK_IMPORTED_MODULE_0__.OTPAlgorithm[entryData.algorithm]) {
                    entryData.algorithm = _otp__WEBPACK_IMPORTED_MODULE_0__.OTPAlgorithm.SHA1;
                }
                if (/^(blz-|bliz-)/.test(entryData.secret)) {
                    const secretMatches = entryData.secret.match(/^(blz-|bliz-)(.*)/);
                    if (secretMatches && secretMatches.length >= 3) {
                        entryData.secret = secretMatches[2];
                        entryData.type = _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.battle;
                    }
                }
                if (/^stm-/.test(entryData.secret)) {
                    const secretMatches = entryData.secret.match(/^stm-(.*)/);
                    if (secretMatches && secretMatches.length >= 2) {
                        entryData.secret = secretMatches[1];
                        entryData.type = _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.steam;
                    }
                }
                if (!/^[a-z2-7]+=*$/i.test(entryData.secret) &&
                    /^[0-9a-f]+$/i.test(entryData.secret) &&
                    entryData.type === _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.totp) {
                    entryData.type = _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.hex;
                }
                if (!/^[a-z2-7]+=*$/i.test(entryData.secret) &&
                    /^[0-9a-f]+$/i.test(entryData.secret) &&
                    entryData.type === _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.hotp) {
                    entryData.type = _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.hhex;
                }
                // not a valid / old hash
                if (!/^[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}$/.test(hash)) {
                    entryData.hash = crypto.randomUUID();
                    delete data[hash];
                }
                const entry = new _otp__WEBPACK_IMPORTED_MODULE_0__.OTPEntry(entryData, encryption);
                _data[entryData.hash] = this.getOTPStorageFromEntry(entry);
            }
            _data = this.ensureUniqueIndex(_data);
            yield BrowserStorage.set(_data);
        });
    }
    static add(entry) {
        return __awaiter(this, void 0, void 0, function* () {
            yield BrowserStorage.set({
                [entry.hash]: this.getOTPStorageFromEntry(entry),
            });
        });
    }
    static update(entry) {
        return __awaiter(this, void 0, void 0, function* () {
            let _data = yield BrowserStorage.get();
            if (!Object.prototype.hasOwnProperty.call(_data, entry.hash)) {
                throw new Error("Entry to change does not exist.");
            }
            const storageItem = this.getOTPStorageFromEntry(entry);
            _data[entry.hash] = storageItem;
            _data = this.ensureUniqueIndex(_data);
            yield BrowserStorage.set(_data);
        });
    }
    static set(entries) {
        return __awaiter(this, void 0, void 0, function* () {
            let _data = yield BrowserStorage.get();
            entries.forEach((entry) => {
                const storageItem = this.getOTPStorageFromEntry(entry);
                _data[entry.hash] = storageItem;
            });
            _data = this.ensureUniqueIndex(_data);
            yield BrowserStorage.set(_data);
        });
    }
    static get() {
        return __awaiter(this, void 0, void 0, function* () {
            const _data = yield BrowserStorage.get();
            const data = [];
            for (const hash of Object.keys(_data)) {
                if (hash === "UserSettings" ||
                    _data[hash].dataType === "Key" ||
                    !this.isValidEntry(_data, hash)) {
                    continue;
                }
                const entryData = _data[hash];
                if (entryData.dataType === "EncOTPStorage") {
                    data.push(new _otp__WEBPACK_IMPORTED_MODULE_0__.OTPEntry({
                        encrypted: true,
                        encData: entryData.data,
                        keyId: entryData.keyId,
                        hash,
                        index: entryData.index,
                    }));
                    continue;
                }
                if (!entryData.hash) {
                    entryData.hash = hash;
                }
                if (!entryData.type) {
                    entryData.type = _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType[_otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.totp];
                }
                let type;
                switch (entryData.type) {
                    case "totp":
                    case "hotp":
                    case "battle":
                    case "steam":
                    case "hex":
                    case "hhex":
                        type = _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType[entryData.type];
                        break;
                    default:
                        // we need correct the type here
                        // and save it
                        type = _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.totp;
                        entryData.type = _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType[_otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.totp];
                }
                let period;
                if (entryData.type === _otp__WEBPACK_IMPORTED_MODULE_0__.OTPType[_otp__WEBPACK_IMPORTED_MODULE_0__.OTPType.totp] &&
                    entryData.period &&
                    entryData.period > 0) {
                    period = entryData.period;
                }
                const entry = new _otp__WEBPACK_IMPORTED_MODULE_0__.OTPEntry({
                    account: entryData.account,
                    encrypted: entryData.encrypted,
                    hash: entryData.hash,
                    index: entryData.index,
                    issuer: entryData.issuer,
                    secret: entryData.secret,
                    type,
                    counter: entryData.counter,
                    period,
                    digits: entryData.digits ? Number(entryData.digits) : undefined,
                    // @ts-expect-error - it's fine if this ends up undefined
                    algorithm: _otp__WEBPACK_IMPORTED_MODULE_0__.OTPAlgorithm[entryData.algorithm],
                    pinned: entryData.pinned,
                });
                data.push(entry);
            }
            data.sort((a, b) => {
                return a.index - b.index;
            });
            return data;
        });
    }
    static remove(hash) {
        return __awaiter(this, void 0, void 0, function* () {
            yield BrowserStorage.remove(hash);
        });
    }
    static delete(entry) {
        return __awaiter(this, void 0, void 0, function* () {
            let _data = yield BrowserStorage.get();
            if (Object.prototype.hasOwnProperty.call(_data, entry.hash)) {
                delete _data[entry.hash];
            }
            _data = this.ensureUniqueIndex(_data);
            yield BrowserStorage.remove(entry.hash);
            yield BrowserStorage.set(_data);
        });
    }
}
class ManagedStorage {
    static get(key, defaultValue) {
        const managedStoragePromise = new Promise((resolve) => {
            if (chrome.storage.managed) {
                chrome.storage.managed.get((data) => {
                    if (chrome.runtime.lastError) {
                        return resolve(defaultValue);
                    }
                    if (data) {
                        if (data[key]) {
                            return resolve(data[key]);
                        }
                    }
                    return resolve(defaultValue);
                });
            }
            else {
                // no available in Safari
                resolve(defaultValue);
            }
        });
        const timeoutPromise = new Promise((resolve) => {
            setTimeout(() => resolve(defaultValue), 10);
        });
        return Promise.race([managedStoragePromise, timeoutPromise]);
    }
}


/***/ }),

/***/ "./src/store/i18n.ts":
/*!***************************!*\
  !*** ./src/store/i18n.ts ***!
  \***************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   loadI18nMessages: () => (/* binding */ loadI18nMessages)
/* harmony export */ });
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
function loadI18nMessages() {
    return __awaiter(this, void 0, void 0, function* () {
        return new Promise((resolve, reject) => {
            try {
                const xhr = new XMLHttpRequest();
                xhr.overrideMimeType("application/json");
                xhr.onreadystatechange = () => {
                    if (xhr.readyState === 4) {
                        const i18nMessage = JSON.parse(xhr.responseText);
                        const i18nData = {};
                        for (const key of Object.keys(i18nMessage)) {
                            i18nData[key] = chrome.i18n.getMessage(key);
                        }
                        return resolve(i18nData);
                    }
                    return;
                };
                xhr.open("GET", chrome.runtime.getURL("/_locales/en/messages.json"));
                xhr.send();
            }
            catch (error) {
                if (typeof error === "string" || error === undefined) {
                    return reject(Error(error));
                }
                else if (error instanceof Error) {
                    return reject(error);
                }
                else {
                    return reject(Error(String(error)));
                }
            }
        });
    });
}


/***/ }),

/***/ "./src/components/Import.vue":
/*!***********************************!*\
  !*** ./src/components/Import.vue ***!
  \***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _Import_vue_vue_type_template_id_6aabbf55__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Import.vue?vue&type=template&id=6aabbf55 */ "./src/components/Import.vue?vue&type=template&id=6aabbf55");
/* harmony import */ var _Import_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Import.vue?vue&type=script&lang=ts */ "./src/components/Import.vue?vue&type=script&lang=ts");
/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js");





/* normalize component */
;
var component = (0,_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])(
  _Import_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__["default"],
  _Import_vue_vue_type_template_id_6aabbf55__WEBPACK_IMPORTED_MODULE_0__.render,
  _Import_vue_vue_type_template_id_6aabbf55__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns,
  false,
  null,
  null,
  null
  
)

/* hot reload */
if (false) { var api; }
component.options.__file = "src/components/Import.vue"
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (component.exports);

/***/ }),

/***/ "./src/components/Import/FileImport.vue":
/*!**********************************************!*\
  !*** ./src/components/Import/FileImport.vue ***!
  \**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _FileImport_vue_vue_type_template_id_bf1068ea__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./FileImport.vue?vue&type=template&id=bf1068ea */ "./src/components/Import/FileImport.vue?vue&type=template&id=bf1068ea");
/* harmony import */ var _FileImport_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./FileImport.vue?vue&type=script&lang=ts */ "./src/components/Import/FileImport.vue?vue&type=script&lang=ts");
/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js");





/* normalize component */
;
var component = (0,_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])(
  _FileImport_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__["default"],
  _FileImport_vue_vue_type_template_id_bf1068ea__WEBPACK_IMPORTED_MODULE_0__.render,
  _FileImport_vue_vue_type_template_id_bf1068ea__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns,
  false,
  null,
  null,
  null
  
)

/* hot reload */
if (false) { var api; }
component.options.__file = "src/components/Import/FileImport.vue"
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (component.exports);

/***/ }),

/***/ "./src/components/Import/QrImport.vue":
/*!********************************************!*\
  !*** ./src/components/Import/QrImport.vue ***!
  \********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _QrImport_vue_vue_type_template_id_15cc8320__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./QrImport.vue?vue&type=template&id=15cc8320 */ "./src/components/Import/QrImport.vue?vue&type=template&id=15cc8320");
/* harmony import */ var _QrImport_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./QrImport.vue?vue&type=script&lang=ts */ "./src/components/Import/QrImport.vue?vue&type=script&lang=ts");
/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js");





/* normalize component */
;
var component = (0,_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])(
  _QrImport_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__["default"],
  _QrImport_vue_vue_type_template_id_15cc8320__WEBPACK_IMPORTED_MODULE_0__.render,
  _QrImport_vue_vue_type_template_id_15cc8320__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns,
  false,
  null,
  null,
  null
  
)

/* hot reload */
if (false) { var api; }
component.options.__file = "src/components/Import/QrImport.vue"
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (component.exports);

/***/ }),

/***/ "./src/components/Import/TextImport.vue":
/*!**********************************************!*\
  !*** ./src/components/Import/TextImport.vue ***!
  \**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _TextImport_vue_vue_type_template_id_5646f1fc__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./TextImport.vue?vue&type=template&id=5646f1fc */ "./src/components/Import/TextImport.vue?vue&type=template&id=5646f1fc");
/* harmony import */ var _TextImport_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TextImport.vue?vue&type=script&lang=ts */ "./src/components/Import/TextImport.vue?vue&type=script&lang=ts");
/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js");





/* normalize component */
;
var component = (0,_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])(
  _TextImport_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__["default"],
  _TextImport_vue_vue_type_template_id_5646f1fc__WEBPACK_IMPORTED_MODULE_0__.render,
  _TextImport_vue_vue_type_template_id_5646f1fc__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns,
  false,
  null,
  null,
  null
  
)

/* hot reload */
if (false) { var api; }
component.options.__file = "src/components/Import/TextImport.vue"
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (component.exports);

/***/ }),

/***/ "./src/components/common/ButtonInput.vue":
/*!***********************************************!*\
  !*** ./src/components/common/ButtonInput.vue ***!
  \***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _ButtonInput_vue_vue_type_template_id_6f661184__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ButtonInput.vue?vue&type=template&id=6f661184 */ "./src/components/common/ButtonInput.vue?vue&type=template&id=6f661184");
/* harmony import */ var _ButtonInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ButtonInput.vue?vue&type=script&lang=ts */ "./src/components/common/ButtonInput.vue?vue&type=script&lang=ts");
/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js");





/* normalize component */
;
var component = (0,_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])(
  _ButtonInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__["default"],
  _ButtonInput_vue_vue_type_template_id_6f661184__WEBPACK_IMPORTED_MODULE_0__.render,
  _ButtonInput_vue_vue_type_template_id_6f661184__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns,
  false,
  null,
  null,
  null
  
)

/* hot reload */
if (false) { var api; }
component.options.__file = "src/components/common/ButtonInput.vue"
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (component.exports);

/***/ }),

/***/ "./src/components/common/ButtonLink.vue":
/*!**********************************************!*\
  !*** ./src/components/common/ButtonLink.vue ***!
  \**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _ButtonLink_vue_vue_type_template_id_1e22cd30__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ButtonLink.vue?vue&type=template&id=1e22cd30 */ "./src/components/common/ButtonLink.vue?vue&type=template&id=1e22cd30");
/* harmony import */ var _ButtonLink_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ButtonLink.vue?vue&type=script&lang=ts */ "./src/components/common/ButtonLink.vue?vue&type=script&lang=ts");
/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js");





/* normalize component */
;
var component = (0,_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])(
  _ButtonLink_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__["default"],
  _ButtonLink_vue_vue_type_template_id_1e22cd30__WEBPACK_IMPORTED_MODULE_0__.render,
  _ButtonLink_vue_vue_type_template_id_1e22cd30__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns,
  false,
  null,
  null,
  null
  
)

/* hot reload */
if (false) { var api; }
component.options.__file = "src/components/common/ButtonLink.vue"
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (component.exports);

/***/ }),

/***/ "./src/components/common/FileInput.vue":
/*!*********************************************!*\
  !*** ./src/components/common/FileInput.vue ***!
  \*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _FileInput_vue_vue_type_template_id_1b28190c__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./FileInput.vue?vue&type=template&id=1b28190c */ "./src/components/common/FileInput.vue?vue&type=template&id=1b28190c");
/* harmony import */ var _FileInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./FileInput.vue?vue&type=script&lang=ts */ "./src/components/common/FileInput.vue?vue&type=script&lang=ts");
/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js");





/* normalize component */
;
var component = (0,_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])(
  _FileInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__["default"],
  _FileInput_vue_vue_type_template_id_1b28190c__WEBPACK_IMPORTED_MODULE_0__.render,
  _FileInput_vue_vue_type_template_id_1b28190c__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns,
  false,
  null,
  null,
  null
  
)

/* hot reload */
if (false) { var api; }
component.options.__file = "src/components/common/FileInput.vue"
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (component.exports);

/***/ }),

/***/ "./src/components/common/SelectInput.vue":
/*!***********************************************!*\
  !*** ./src/components/common/SelectInput.vue ***!
  \***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _SelectInput_vue_vue_type_template_id_209ae6fa__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./SelectInput.vue?vue&type=template&id=209ae6fa */ "./src/components/common/SelectInput.vue?vue&type=template&id=209ae6fa");
/* harmony import */ var _SelectInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./SelectInput.vue?vue&type=script&lang=ts */ "./src/components/common/SelectInput.vue?vue&type=script&lang=ts");
/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js");





/* normalize component */
;
var component = (0,_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])(
  _SelectInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__["default"],
  _SelectInput_vue_vue_type_template_id_209ae6fa__WEBPACK_IMPORTED_MODULE_0__.render,
  _SelectInput_vue_vue_type_template_id_209ae6fa__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns,
  false,
  null,
  null,
  null
  
)

/* hot reload */
if (false) { var api; }
component.options.__file = "src/components/common/SelectInput.vue"
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (component.exports);

/***/ }),

/***/ "./src/components/common/TextInput.vue":
/*!*********************************************!*\
  !*** ./src/components/common/TextInput.vue ***!
  \*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _TextInput_vue_vue_type_template_id_29d5bae9__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./TextInput.vue?vue&type=template&id=29d5bae9 */ "./src/components/common/TextInput.vue?vue&type=template&id=29d5bae9");
/* harmony import */ var _TextInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TextInput.vue?vue&type=script&lang=ts */ "./src/components/common/TextInput.vue?vue&type=script&lang=ts");
/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js");





/* normalize component */
;
var component = (0,_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])(
  _TextInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__["default"],
  _TextInput_vue_vue_type_template_id_29d5bae9__WEBPACK_IMPORTED_MODULE_0__.render,
  _TextInput_vue_vue_type_template_id_29d5bae9__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns,
  false,
  null,
  null,
  null
  
)

/* hot reload */
if (false) { var api; }
component.options.__file = "src/components/common/TextInput.vue"
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (component.exports);

/***/ }),

/***/ "./src/components/common/ToggleInput.vue":
/*!***********************************************!*\
  !*** ./src/components/common/ToggleInput.vue ***!
  \***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _ToggleInput_vue_vue_type_template_id_c09df8bc__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ToggleInput.vue?vue&type=template&id=c09df8bc */ "./src/components/common/ToggleInput.vue?vue&type=template&id=c09df8bc");
/* harmony import */ var _ToggleInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ToggleInput.vue?vue&type=script&lang=ts */ "./src/components/common/ToggleInput.vue?vue&type=script&lang=ts");
/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js");





/* normalize component */
;
var component = (0,_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])(
  _ToggleInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_1__["default"],
  _ToggleInput_vue_vue_type_template_id_c09df8bc__WEBPACK_IMPORTED_MODULE_0__.render,
  _ToggleInput_vue_vue_type_template_id_c09df8bc__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns,
  false,
  null,
  null,
  null
  
)

/* hot reload */
if (false) { var api; }
component.options.__file = "src/components/common/ToggleInput.vue"
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (component.exports);

/***/ }),

/***/ "./src/components/Import.vue?vue&type=script&lang=ts":
/*!***********************************************************!*\
  !*** ./src/components/Import.vue?vue&type=script&lang=ts ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_Import_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/ts-loader/index.js??clonedRuleSet-2!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Import.vue?vue&type=script&lang=ts */ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import.vue?vue&type=script&lang=ts");
 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_Import_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__["default"]); 

/***/ }),

/***/ "./src/components/Import/FileImport.vue?vue&type=script&lang=ts":
/*!**********************************************************************!*\
  !*** ./src/components/Import/FileImport.vue?vue&type=script&lang=ts ***!
  \**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_FileImport_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/ts-loader/index.js??clonedRuleSet-2!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FileImport.vue?vue&type=script&lang=ts */ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/FileImport.vue?vue&type=script&lang=ts");
 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_FileImport_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__["default"]); 

/***/ }),

/***/ "./src/components/Import/QrImport.vue?vue&type=script&lang=ts":
/*!********************************************************************!*\
  !*** ./src/components/Import/QrImport.vue?vue&type=script&lang=ts ***!
  \********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_QrImport_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/ts-loader/index.js??clonedRuleSet-2!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./QrImport.vue?vue&type=script&lang=ts */ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/QrImport.vue?vue&type=script&lang=ts");
 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_QrImport_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__["default"]); 

/***/ }),

/***/ "./src/components/Import/TextImport.vue?vue&type=script&lang=ts":
/*!**********************************************************************!*\
  !*** ./src/components/Import/TextImport.vue?vue&type=script&lang=ts ***!
  \**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_TextImport_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/ts-loader/index.js??clonedRuleSet-2!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./TextImport.vue?vue&type=script&lang=ts */ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/TextImport.vue?vue&type=script&lang=ts");
 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_TextImport_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__["default"]); 

/***/ }),

/***/ "./src/components/common/ButtonInput.vue?vue&type=script&lang=ts":
/*!***********************************************************************!*\
  !*** ./src/components/common/ButtonInput.vue?vue&type=script&lang=ts ***!
  \***********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ButtonInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/ts-loader/index.js??clonedRuleSet-2!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./ButtonInput.vue?vue&type=script&lang=ts */ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ButtonInput.vue?vue&type=script&lang=ts");
 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ButtonInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__["default"]); 

/***/ }),

/***/ "./src/components/common/ButtonLink.vue?vue&type=script&lang=ts":
/*!**********************************************************************!*\
  !*** ./src/components/common/ButtonLink.vue?vue&type=script&lang=ts ***!
  \**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ButtonLink_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/ts-loader/index.js??clonedRuleSet-2!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./ButtonLink.vue?vue&type=script&lang=ts */ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ButtonLink.vue?vue&type=script&lang=ts");
 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ButtonLink_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__["default"]); 

/***/ }),

/***/ "./src/components/common/FileInput.vue?vue&type=script&lang=ts":
/*!*********************************************************************!*\
  !*** ./src/components/common/FileInput.vue?vue&type=script&lang=ts ***!
  \*********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_FileInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/ts-loader/index.js??clonedRuleSet-2!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FileInput.vue?vue&type=script&lang=ts */ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/FileInput.vue?vue&type=script&lang=ts");
 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_FileInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__["default"]); 

/***/ }),

/***/ "./src/components/common/SelectInput.vue?vue&type=script&lang=ts":
/*!***********************************************************************!*\
  !*** ./src/components/common/SelectInput.vue?vue&type=script&lang=ts ***!
  \***********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_SelectInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/ts-loader/index.js??clonedRuleSet-2!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./SelectInput.vue?vue&type=script&lang=ts */ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/SelectInput.vue?vue&type=script&lang=ts");
 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_SelectInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__["default"]); 

/***/ }),

/***/ "./src/components/common/TextInput.vue?vue&type=script&lang=ts":
/*!*********************************************************************!*\
  !*** ./src/components/common/TextInput.vue?vue&type=script&lang=ts ***!
  \*********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_TextInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/ts-loader/index.js??clonedRuleSet-2!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./TextInput.vue?vue&type=script&lang=ts */ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/TextInput.vue?vue&type=script&lang=ts");
 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_TextInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__["default"]); 

/***/ }),

/***/ "./src/components/common/ToggleInput.vue?vue&type=script&lang=ts":
/*!***********************************************************************!*\
  !*** ./src/components/common/ToggleInput.vue?vue&type=script&lang=ts ***!
  \***********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ToggleInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/ts-loader/index.js??clonedRuleSet-2!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./ToggleInput.vue?vue&type=script&lang=ts */ "./node_modules/ts-loader/index.js??clonedRuleSet-2!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ToggleInput.vue?vue&type=script&lang=ts");
 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_ts_loader_index_js_clonedRuleSet_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ToggleInput_vue_vue_type_script_lang_ts__WEBPACK_IMPORTED_MODULE_0__["default"]); 

/***/ }),

/***/ "./src/components/Import.vue?vue&type=template&id=6aabbf55":
/*!*****************************************************************!*\
  !*** ./src/components/Import.vue?vue&type=template&id=6aabbf55 ***!
  \*****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_Import_vue_vue_type_template_id_6aabbf55__WEBPACK_IMPORTED_MODULE_0__.render),
/* harmony export */   staticRenderFns: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_Import_vue_vue_type_template_id_6aabbf55__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns)
/* harmony export */ });
/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_Import_vue_vue_type_template_id_6aabbf55__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Import.vue?vue&type=template&id=6aabbf55 */ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import.vue?vue&type=template&id=6aabbf55");


/***/ }),

/***/ "./src/components/Import/FileImport.vue?vue&type=template&id=bf1068ea":
/*!****************************************************************************!*\
  !*** ./src/components/Import/FileImport.vue?vue&type=template&id=bf1068ea ***!
  \****************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_FileImport_vue_vue_type_template_id_bf1068ea__WEBPACK_IMPORTED_MODULE_0__.render),
/* harmony export */   staticRenderFns: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_FileImport_vue_vue_type_template_id_bf1068ea__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns)
/* harmony export */ });
/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_FileImport_vue_vue_type_template_id_bf1068ea__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FileImport.vue?vue&type=template&id=bf1068ea */ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/FileImport.vue?vue&type=template&id=bf1068ea");


/***/ }),

/***/ "./src/components/Import/QrImport.vue?vue&type=template&id=15cc8320":
/*!**************************************************************************!*\
  !*** ./src/components/Import/QrImport.vue?vue&type=template&id=15cc8320 ***!
  \**************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_QrImport_vue_vue_type_template_id_15cc8320__WEBPACK_IMPORTED_MODULE_0__.render),
/* harmony export */   staticRenderFns: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_QrImport_vue_vue_type_template_id_15cc8320__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns)
/* harmony export */ });
/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_QrImport_vue_vue_type_template_id_15cc8320__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./QrImport.vue?vue&type=template&id=15cc8320 */ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/QrImport.vue?vue&type=template&id=15cc8320");


/***/ }),

/***/ "./src/components/Import/TextImport.vue?vue&type=template&id=5646f1fc":
/*!****************************************************************************!*\
  !*** ./src/components/Import/TextImport.vue?vue&type=template&id=5646f1fc ***!
  \****************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_TextImport_vue_vue_type_template_id_5646f1fc__WEBPACK_IMPORTED_MODULE_0__.render),
/* harmony export */   staticRenderFns: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_TextImport_vue_vue_type_template_id_5646f1fc__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns)
/* harmony export */ });
/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_TextImport_vue_vue_type_template_id_5646f1fc__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./TextImport.vue?vue&type=template&id=5646f1fc */ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/TextImport.vue?vue&type=template&id=5646f1fc");


/***/ }),

/***/ "./src/components/common/ButtonInput.vue?vue&type=template&id=6f661184":
/*!*****************************************************************************!*\
  !*** ./src/components/common/ButtonInput.vue?vue&type=template&id=6f661184 ***!
  \*****************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ButtonInput_vue_vue_type_template_id_6f661184__WEBPACK_IMPORTED_MODULE_0__.render),
/* harmony export */   staticRenderFns: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ButtonInput_vue_vue_type_template_id_6f661184__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns)
/* harmony export */ });
/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ButtonInput_vue_vue_type_template_id_6f661184__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./ButtonInput.vue?vue&type=template&id=6f661184 */ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ButtonInput.vue?vue&type=template&id=6f661184");


/***/ }),

/***/ "./src/components/common/ButtonLink.vue?vue&type=template&id=1e22cd30":
/*!****************************************************************************!*\
  !*** ./src/components/common/ButtonLink.vue?vue&type=template&id=1e22cd30 ***!
  \****************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ButtonLink_vue_vue_type_template_id_1e22cd30__WEBPACK_IMPORTED_MODULE_0__.render),
/* harmony export */   staticRenderFns: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ButtonLink_vue_vue_type_template_id_1e22cd30__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns)
/* harmony export */ });
/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ButtonLink_vue_vue_type_template_id_1e22cd30__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./ButtonLink.vue?vue&type=template&id=1e22cd30 */ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ButtonLink.vue?vue&type=template&id=1e22cd30");


/***/ }),

/***/ "./src/components/common/FileInput.vue?vue&type=template&id=1b28190c":
/*!***************************************************************************!*\
  !*** ./src/components/common/FileInput.vue?vue&type=template&id=1b28190c ***!
  \***************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_FileInput_vue_vue_type_template_id_1b28190c__WEBPACK_IMPORTED_MODULE_0__.render),
/* harmony export */   staticRenderFns: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_FileInput_vue_vue_type_template_id_1b28190c__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns)
/* harmony export */ });
/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_FileInput_vue_vue_type_template_id_1b28190c__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FileInput.vue?vue&type=template&id=1b28190c */ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/FileInput.vue?vue&type=template&id=1b28190c");


/***/ }),

/***/ "./src/components/common/SelectInput.vue?vue&type=template&id=209ae6fa":
/*!*****************************************************************************!*\
  !*** ./src/components/common/SelectInput.vue?vue&type=template&id=209ae6fa ***!
  \*****************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_SelectInput_vue_vue_type_template_id_209ae6fa__WEBPACK_IMPORTED_MODULE_0__.render),
/* harmony export */   staticRenderFns: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_SelectInput_vue_vue_type_template_id_209ae6fa__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns)
/* harmony export */ });
/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_SelectInput_vue_vue_type_template_id_209ae6fa__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./SelectInput.vue?vue&type=template&id=209ae6fa */ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/SelectInput.vue?vue&type=template&id=209ae6fa");


/***/ }),

/***/ "./src/components/common/TextInput.vue?vue&type=template&id=29d5bae9":
/*!***************************************************************************!*\
  !*** ./src/components/common/TextInput.vue?vue&type=template&id=29d5bae9 ***!
  \***************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_TextInput_vue_vue_type_template_id_29d5bae9__WEBPACK_IMPORTED_MODULE_0__.render),
/* harmony export */   staticRenderFns: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_TextInput_vue_vue_type_template_id_29d5bae9__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns)
/* harmony export */ });
/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_TextInput_vue_vue_type_template_id_29d5bae9__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./TextInput.vue?vue&type=template&id=29d5bae9 */ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/TextInput.vue?vue&type=template&id=29d5bae9");


/***/ }),

/***/ "./src/components/common/ToggleInput.vue?vue&type=template&id=c09df8bc":
/*!*****************************************************************************!*\
  !*** ./src/components/common/ToggleInput.vue?vue&type=template&id=c09df8bc ***!
  \*****************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ToggleInput_vue_vue_type_template_id_c09df8bc__WEBPACK_IMPORTED_MODULE_0__.render),
/* harmony export */   staticRenderFns: () => (/* reexport safe */ _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ToggleInput_vue_vue_type_template_id_c09df8bc__WEBPACK_IMPORTED_MODULE_0__.staticRenderFns)
/* harmony export */ });
/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_lib_index_js_vue_loader_options_ToggleInput_vue_vue_type_template_id_c09df8bc__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./ToggleInput.vue?vue&type=template&id=c09df8bc */ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ToggleInput.vue?vue&type=template&id=c09df8bc");


/***/ }),

/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import.vue?vue&type=template&id=6aabbf55":
/*!*********************************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import.vue?vue&type=template&id=6aabbf55 ***!
  \*********************************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* binding */ render),
/* harmony export */   staticRenderFns: () => (/* binding */ staticRenderFns)
/* harmony export */ });
var render = function render() {
  var _vm = this,
    _c = _vm._self._c,
    _setup = _vm._self._setupProxy
  return _c("div", { staticClass: "theme-normal", attrs: { id: "import" } }, [
    !_vm.shouldShowPassphrase
      ? _c(
          "div",
          [
            _c("div", { staticClass: "import_tab" }, [
              _c("input", {
                directives: [
                  {
                    name: "model",
                    rawName: "v-model",
                    value: _vm.importType,
                    expression: "importType",
                  },
                ],
                attrs: {
                  type: "radio",
                  id: "import_file_radio",
                  value: "FileImport",
                },
                domProps: { checked: _vm._q(_vm.importType, "FileImport") },
                on: {
                  change: function ($event) {
                    _vm.importType = "FileImport"
                  },
                },
              }),
              _vm._v(" "),
              _c("label", { attrs: { for: "import_file_radio" } }, [
                _vm._v(_vm._s(_vm.i18n.import_backup_file)),
              ]),
              _vm._v(" "),
              _c("input", {
                directives: [
                  {
                    name: "model",
                    rawName: "v-model",
                    value: _vm.importType,
                    expression: "importType",
                  },
                ],
                attrs: {
                  type: "radio",
                  id: "import_qr_radio",
                  value: "QrImport",
                },
                domProps: { checked: _vm._q(_vm.importType, "QrImport") },
                on: {
                  change: function ($event) {
                    _vm.importType = "QrImport"
                  },
                },
              }),
              _vm._v(" "),
              _c("label", { attrs: { for: "import_qr_radio" } }, [
                _vm._v(_vm._s(_vm.i18n.import_backup_qr)),
              ]),
              _vm._v(" "),
              _c("input", {
                directives: [
                  {
                    name: "model",
                    rawName: "v-model",
                    value: _vm.importType,
                    expression: "importType",
                  },
                ],
                attrs: {
                  type: "radio",
                  id: "import_code_radio",
                  value: "TextImport",
                },
                domProps: { checked: _vm._q(_vm.importType, "TextImport") },
                on: {
                  change: function ($event) {
                    _vm.importType = "TextImport"
                  },
                },
              }),
              _vm._v(" "),
              _c("label", { attrs: { for: "import_code_radio" } }, [
                _vm._v(_vm._s(_vm.i18n.import_backup_code)),
              ]),
            ]),
            _vm._v(" "),
            _c("div", [
              _c("p", { attrs: { id: "import_info" } }, [
                _vm._v(
                  "\n        " +
                    _vm._s(_vm.i18n.otp_backup_inform) +
                    "\n        "
                ),
                _c(
                  "a",
                  {
                    attrs: {
                      href:
                        "https://kausa.tech/posts/panduan-docfast-toolkit-chrome-extension",
                      target: "_blank",
                    },
                  },
                  [_vm._v(_vm._s(_vm.i18n.otp_backup_learn))]
                ),
              ]),
            ]),
            _vm._v(" "),
            _c(_vm.importType, { tag: "component" }),
          ],
          1
        )
      : _vm._e(),
    _vm._v(" "),
    _vm.shouldShowPassphrase
      ? _c("div", { staticClass: "error_password" }, [
          _vm._v("\n    " + _vm._s(_vm.i18n.import_error_password) + "\n  "),
        ])
      : _vm._e(),
  ])
}
var staticRenderFns = []
render._withStripped = true



/***/ }),

/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/FileImport.vue?vue&type=template&id=bf1068ea":
/*!********************************************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/FileImport.vue?vue&type=template&id=bf1068ea ***!
  \********************************************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* binding */ render),
/* harmony export */   staticRenderFns: () => (/* binding */ staticRenderFns)
/* harmony export */ });
var render = function render() {
  var _vm = this,
    _c = _vm._self._c,
    _setup = _vm._self._setupProxy
  return _c(
    "div",
    [
      !_vm.getFilePassphrase
        ? _c("a-file-input", {
            attrs: {
              "button-type": "file",
              accept: "application/json, text/plain",
              label: _vm.i18n.import_backup_file,
            },
            on: {
              change: function ($event) {
                return _vm.importFile($event, true)
              },
            },
          })
        : _c(
            "div",
            { staticClass: "import_file_passphrase" },
            [
              _c("p", { staticClass: "error_password" }, [
                _vm._v(_vm._s(_vm.i18n.passphrase_info)),
              ]),
              _vm._v(" "),
              _c("a-text-input", {
                attrs: { label: _vm.i18n.phrase, type: "password" },
                on: {
                  enter: function ($event) {
                    _vm.readFilePassphrase = true
                  },
                },
                model: {
                  value: _vm.importFilePassphrase,
                  callback: function ($$v) {
                    _vm.importFilePassphrase = $$v
                  },
                  expression: "importFilePassphrase",
                },
              }),
              _vm._v(" "),
              _c(
                "a-button",
                {
                  on: {
                    click: function ($event) {
                      _vm.readFilePassphrase = true
                    },
                  },
                },
                [_vm._v(_vm._s(_vm.i18n.ok))]
              ),
            ],
            1
          ),
    ],
    1
  )
}
var staticRenderFns = []
render._withStripped = true



/***/ }),

/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/QrImport.vue?vue&type=template&id=15cc8320":
/*!******************************************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/QrImport.vue?vue&type=template&id=15cc8320 ***!
  \******************************************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* binding */ render),
/* harmony export */   staticRenderFns: () => (/* binding */ staticRenderFns)
/* harmony export */ });
var render = function render() {
  var _vm = this,
    _c = _vm._self._c,
    _setup = _vm._self._setupProxy
  return _c(
    "div",
    [
      _c("p", { staticStyle: { margin: "10px 20px 20px 20px" } }, [
        _vm._v(
          "\n    " + _vm._s(_vm.i18n.import_backup_qr_in_batches) + "\n  "
        ),
      ]),
      _vm._v(" "),
      _c("a-file-input", {
        attrs: {
          "button-type": "file",
          accept: "image/*",
          multiple: "true",
          label: _vm.i18n.import_backup_qr,
        },
        on: {
          change: function ($event) {
            return _vm.importQr($event, true)
          },
        },
      }),
    ],
    1
  )
}
var staticRenderFns = []
render._withStripped = true



/***/ }),

/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/TextImport.vue?vue&type=template&id=5646f1fc":
/*!********************************************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/Import/TextImport.vue?vue&type=template&id=5646f1fc ***!
  \********************************************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* binding */ render),
/* harmony export */   staticRenderFns: () => (/* binding */ staticRenderFns)
/* harmony export */ });
var render = function render() {
  var _vm = this,
    _c = _vm._self._c,
    _setup = _vm._self._setupProxy
  return _c(
    "div",
    [
      _c("div", { staticClass: "import_code" }, [
        _c("textarea", {
          directives: [
            {
              name: "model",
              rawName: "v-model",
              value: _vm.importCode,
              expression: "importCode",
            },
          ],
          attrs: {
            spellcheck: "false",
            placeholder:
              "otpauth://totp/...\notpauth://totp/...\notpauth://hotp/...\n...",
          },
          domProps: { value: _vm.importCode },
          on: {
            input: function ($event) {
              if ($event.target.composing) return
              _vm.importCode = $event.target.value
            },
          },
        }),
      ]),
      _vm._v(" "),
      _c("div", { staticClass: "import_encrypted" }, [
        _c("input", {
          directives: [
            {
              name: "model",
              rawName: "v-model",
              value: _vm.importEncrypted,
              expression: "importEncrypted",
            },
          ],
          attrs: { type: "checkbox", id: "encryptedCode" },
          domProps: {
            checked: Array.isArray(_vm.importEncrypted)
              ? _vm._i(_vm.importEncrypted, null) > -1
              : _vm.importEncrypted,
          },
          on: {
            change: function ($event) {
              var $$a = _vm.importEncrypted,
                $$el = $event.target,
                $$c = $$el.checked ? true : false
              if (Array.isArray($$a)) {
                var $$v = null,
                  $$i = _vm._i($$a, $$v)
                if ($$el.checked) {
                  $$i < 0 && (_vm.importEncrypted = $$a.concat([$$v]))
                } else {
                  $$i > -1 &&
                    (_vm.importEncrypted = $$a
                      .slice(0, $$i)
                      .concat($$a.slice($$i + 1)))
                }
              } else {
                _vm.importEncrypted = $$c
              }
            },
          },
        }),
        _vm._v(" "),
        _c("label", { attrs: { for: "encryptedCode" } }, [
          _vm._v(_vm._s(_vm.i18n.encrypted)),
        ]),
      ]),
      _vm._v(" "),
      _c("a-text-input", {
        directives: [
          {
            name: "show",
            rawName: "v-show",
            value: _vm.importEncrypted,
            expression: "importEncrypted",
          },
        ],
        attrs: { label: _vm.i18n.phrase, type: "password" },
        model: {
          value: _vm.importPassphrase,
          callback: function ($$v) {
            _vm.importPassphrase = $$v
          },
          expression: "importPassphrase",
        },
      }),
      _vm._v(" "),
      _c(
        "a-button",
        {
          on: {
            click: function ($event) {
              return _vm.importBackupCode()
            },
          },
        },
        [_vm._v("\n      " + _vm._s(_vm.i18n.import_backup_code) + "\n    ")]
      ),
    ],
    1
  )
}
var staticRenderFns = []
render._withStripped = true



/***/ }),

/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ButtonInput.vue?vue&type=template&id=6f661184":
/*!*********************************************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ButtonInput.vue?vue&type=template&id=6f661184 ***!
  \*********************************************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* binding */ render),
/* harmony export */   staticRenderFns: () => (/* binding */ staticRenderFns)
/* harmony export */ });
var render = function render() {
  var _vm = this,
    _c = _vm._self._c,
    _setup = _vm._self._setupProxy
  return _c(
    "button",
    _vm._g(
      { class: { "button-small": _vm.type === "small", button: !_vm.type } },
      _vm.$listeners
    ),
    [_vm._t("default")],
    2
  )
}
var staticRenderFns = []
render._withStripped = true



/***/ }),

/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ButtonLink.vue?vue&type=template&id=1e22cd30":
/*!********************************************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ButtonLink.vue?vue&type=template&id=1e22cd30 ***!
  \********************************************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* binding */ render),
/* harmony export */   staticRenderFns: () => (/* binding */ staticRenderFns)
/* harmony export */ });
var render = function render() {
  var _vm = this,
    _c = _vm._self._c,
    _setup = _vm._self._setupProxy
  return _c(
    "a",
    {
      class: { "button-small": _vm.type === "small", button: !_vm.type },
      attrs: { href: _vm.href, download: _vm.download, target: "_blank" },
    },
    [_vm._t("default")],
    2
  )
}
var staticRenderFns = []
render._withStripped = true



/***/ }),

/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/FileInput.vue?vue&type=template&id=1b28190c":
/*!*******************************************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/FileInput.vue?vue&type=template&id=1b28190c ***!
  \*******************************************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* binding */ render),
/* harmony export */   staticRenderFns: () => (/* binding */ staticRenderFns)
/* harmony export */ });
var render = function render() {
  var _vm = this,
    _c = _vm._self._c,
    _setup = _vm._self._setupProxy
  return _c("div", { staticClass: "import_file" }, [
    _c("label", { attrs: { for: "import_file" } }, [_vm._v(_vm._s(_vm.label))]),
    _vm._v(" "),
    _c(
      "input",
      _vm._g(
        {
          attrs: {
            id: "import_file",
            type: "file",
            accept: _vm.accept,
            multiple: _vm.multiple,
          },
        },
        _vm.$listeners
      )
    ),
  ])
}
var staticRenderFns = []
render._withStripped = true



/***/ }),

/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/SelectInput.vue?vue&type=template&id=209ae6fa":
/*!*********************************************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/SelectInput.vue?vue&type=template&id=209ae6fa ***!
  \*********************************************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* binding */ render),
/* harmony export */   staticRenderFns: () => (/* binding */ staticRenderFns)
/* harmony export */ });
var render = function render() {
  var _vm = this,
    _c = _vm._self._c,
    _setup = _vm._self._setupProxy
  return _c("div", { staticClass: "control-group" }, [
    _c(
      "label",
      { staticClass: "combo-label", staticStyle: { margin: "20px 10px" } },
      [_vm._v(_vm._s(_vm.label))]
    ),
    _vm._v(" "),
    _c(
      "select",
      {
        staticStyle: { margin: "20px 10px" },
        attrs: { disabled: _vm.disabled },
        domProps: { value: _vm.value },
        on: {
          input: function ($event) {
            return _vm.$emit("input", $event.target.value)
          },
          change: function ($event) {
            return _vm.$emit("change")
          },
        },
      },
      [_vm._t("default")],
      2
    ),
  ])
}
var staticRenderFns = []
render._withStripped = true



/***/ }),

/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/TextInput.vue?vue&type=template&id=29d5bae9":
/*!*******************************************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/TextInput.vue?vue&type=template&id=29d5bae9 ***!
  \*******************************************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* binding */ render),
/* harmony export */   staticRenderFns: () => (/* binding */ staticRenderFns)
/* harmony export */ });
var render = function render() {
  var _vm = this,
    _c = _vm._self._c,
    _setup = _vm._self._setupProxy
  return _c("div", [
    _c("label", [_vm._v(_vm._s(_vm.label))]),
    _vm._v(" "),
    _c("input", {
      ref: "textInput",
      staticClass: "input",
      attrs: { type: _vm.type ? _vm.type : "text" },
      domProps: { value: _vm.value },
      on: {
        input: function ($event) {
          return _vm.$emit("input", $event.target.value)
        },
        keyup: function ($event) {
          if (
            !$event.type.indexOf("key") &&
            _vm._k($event.keyCode, "enter", 13, $event.key, "Enter")
          )
            return null
          return _vm.$emit("enter")
        },
      },
    }),
  ])
}
var staticRenderFns = []
render._withStripped = true



/***/ }),

/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ToggleInput.vue?vue&type=template&id=c09df8bc":
/*!*********************************************************************************************************************************************************************************************************************!*\
  !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/lib/index.js??vue-loader-options!./src/components/common/ToggleInput.vue?vue&type=template&id=c09df8bc ***!
  \*********************************************************************************************************************************************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   render: () => (/* binding */ render),
/* harmony export */   staticRenderFns: () => (/* binding */ staticRenderFns)
/* harmony export */ });
var render = function render() {
  var _vm = this,
    _c = _vm._self._c,
    _setup = _vm._self._setupProxy
  return _c("div", { staticClass: "control-group" }, [
    _c("label", { staticClass: "combo-label" }, [_vm._v(_vm._s(_vm.label))]),
    _vm._v(" "),
    _c("input", {
      staticClass: "checkbox",
      attrs: { type: "checkbox" },
      domProps: { checked: _vm.checked },
      on: {
        change: function ($event) {
          return _vm.$emit("change", $event.target.checked)
        },
      },
    }),
  ])
}
var staticRenderFns = []
render._withStripped = true



/***/ }),

/***/ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js":
/*!********************************************************************!*\
  !*** ./node_modules/vue-loader/lib/runtime/componentNormalizer.js ***!
  \********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (/* binding */ normalizeComponent)
/* harmony export */ });
/* globals __VUE_SSR_CONTEXT__ */

// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).
// This module is a runtime utility for cleaner component module output and will
// be included in the final webpack user bundle.

function normalizeComponent(
  scriptExports,
  render,
  staticRenderFns,
  functionalTemplate,
  injectStyles,
  scopeId,
  moduleIdentifier /* server only */,
  shadowMode /* vue-cli only */
) {
  // Vue.extend constructor export interop
  var options =
    typeof scriptExports === 'function' ? scriptExports.options : scriptExports

  // render functions
  if (render) {
    options.render = render
    options.staticRenderFns = staticRenderFns
    options._compiled = true
  }

  // functional template
  if (functionalTemplate) {
    options.functional = true
  }

  // scopedId
  if (scopeId) {
    options._scopeId = 'data-v-' + scopeId
  }

  var hook
  if (moduleIdentifier) {
    // server build
    hook = function (context) {
      // 2.3 injection
      context =
        context || // cached call
        (this.$vnode && this.$vnode.ssrContext) || // stateful
        (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional
      // 2.2 with runInNewContext: true
      if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
        context = __VUE_SSR_CONTEXT__
      }
      // inject component styles
      if (injectStyles) {
        injectStyles.call(this, context)
      }
      // register component module identifier for async chunk inferrence
      if (context && context._registeredComponents) {
        context._registeredComponents.add(moduleIdentifier)
      }
    }
    // used by ssr in case component is cached and beforeCreate
    // never gets called
    options._ssrRegister = hook
  } else if (injectStyles) {
    hook = shadowMode
      ? function () {
          injectStyles.call(
            this,
            (options.functional ? this.parent : this).$root.$options.shadowRoot
          )
        }
      : injectStyles
  }

  if (hook) {
    if (options.functional) {
      // for template-only hot-reload because in that case the render fn doesn't
      // go through the normalizer
      options._injectStyles = hook
      // register for functional component in vue file
      var originalRender = options.render
      options.render = function renderWithStyleInjection(h, context) {
        hook.call(context)
        return originalRender(h, context)
      }
    } else {
      // inject component registration as beforeCreate hook
      var existing = options.beforeCreate
      options.beforeCreate = existing ? [].concat(existing, hook) : [hook]
    }
  }

  return {
    exports: scriptExports,
    options: options
  }
}


/***/ }),

/***/ "./node_modules/vue/dist/vue.runtime.esm.js":
/*!**************************************************!*\
  !*** ./node_modules/vue/dist/vue.runtime.esm.js ***!
  \**************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   EffectScope: () => (/* binding */ EffectScope),
/* harmony export */   computed: () => (/* binding */ computed),
/* harmony export */   customRef: () => (/* binding */ customRef),
/* harmony export */   "default": () => (/* binding */ Vue),
/* harmony export */   defineAsyncComponent: () => (/* binding */ defineAsyncComponent),
/* harmony export */   defineComponent: () => (/* binding */ defineComponent),
/* harmony export */   del: () => (/* binding */ del),
/* harmony export */   effectScope: () => (/* binding */ effectScope),
/* harmony export */   getCurrentInstance: () => (/* binding */ getCurrentInstance),
/* harmony export */   getCurrentScope: () => (/* binding */ getCurrentScope),
/* harmony export */   h: () => (/* binding */ h),
/* harmony export */   inject: () => (/* binding */ inject),
/* harmony export */   isProxy: () => (/* binding */ isProxy),
/* harmony export */   isReactive: () => (/* binding */ isReactive),
/* harmony export */   isReadonly: () => (/* binding */ isReadonly),
/* harmony export */   isRef: () => (/* binding */ isRef),
/* harmony export */   isShallow: () => (/* binding */ isShallow),
/* harmony export */   markRaw: () => (/* binding */ markRaw),
/* harmony export */   mergeDefaults: () => (/* binding */ mergeDefaults),
/* harmony export */   nextTick: () => (/* binding */ nextTick),
/* harmony export */   onActivated: () => (/* binding */ onActivated),
/* harmony export */   onBeforeMount: () => (/* binding */ onBeforeMount),
/* harmony export */   onBeforeUnmount: () => (/* binding */ onBeforeUnmount),
/* harmony export */   onBeforeUpdate: () => (/* binding */ onBeforeUpdate),
/* harmony export */   onDeactivated: () => (/* binding */ onDeactivated),
/* harmony export */   onErrorCaptured: () => (/* binding */ onErrorCaptured),
/* harmony export */   onMounted: () => (/* binding */ onMounted),
/* harmony export */   onRenderTracked: () => (/* binding */ onRenderTracked),
/* harmony export */   onRenderTriggered: () => (/* binding */ onRenderTriggered),
/* harmony export */   onScopeDispose: () => (/* binding */ onScopeDispose),
/* harmony export */   onServerPrefetch: () => (/* binding */ onServerPrefetch),
/* harmony export */   onUnmounted: () => (/* binding */ onUnmounted),
/* harmony export */   onUpdated: () => (/* binding */ onUpdated),
/* harmony export */   provide: () => (/* binding */ provide),
/* harmony export */   proxyRefs: () => (/* binding */ proxyRefs),
/* harmony export */   reactive: () => (/* binding */ reactive),
/* harmony export */   readonly: () => (/* binding */ readonly),
/* harmony export */   ref: () => (/* binding */ ref$1),
/* harmony export */   set: () => (/* binding */ set),
/* harmony export */   shallowReactive: () => (/* binding */ shallowReactive),
/* harmony export */   shallowReadonly: () => (/* binding */ shallowReadonly),
/* harmony export */   shallowRef: () => (/* binding */ shallowRef),
/* harmony export */   toRaw: () => (/* binding */ toRaw),
/* harmony export */   toRef: () => (/* binding */ toRef),
/* harmony export */   toRefs: () => (/* binding */ toRefs),
/* harmony export */   triggerRef: () => (/* binding */ triggerRef),
/* harmony export */   unref: () => (/* binding */ unref),
/* harmony export */   useAttrs: () => (/* binding */ useAttrs),
/* harmony export */   useCssModule: () => (/* binding */ useCssModule),
/* harmony export */   useCssVars: () => (/* binding */ useCssVars),
/* harmony export */   useListeners: () => (/* binding */ useListeners),
/* harmony export */   useSlots: () => (/* binding */ useSlots),
/* harmony export */   version: () => (/* binding */ version),
/* harmony export */   watch: () => (/* binding */ watch),
/* harmony export */   watchEffect: () => (/* binding */ watchEffect),
/* harmony export */   watchPostEffect: () => (/* binding */ watchPostEffect),
/* harmony export */   watchSyncEffect: () => (/* binding */ watchSyncEffect)
/* harmony export */ });
/*!
 * Vue.js v2.7.16
 * (c) 2014-2023 Evan You
 * Released under the MIT License.
 */
var emptyObject = Object.freeze({});
var isArray = Array.isArray;
// These helpers produce better VM code in JS engines due to their
// explicitness and function inlining.
function isUndef(v) {
    return v === undefined || v === null;
}
function isDef(v) {
    return v !== undefined && v !== null;
}
function isTrue(v) {
    return v === true;
}
function isFalse(v) {
    return v === false;
}
/**
 * Check if value is primitive.
 */
function isPrimitive(value) {
    return (typeof value === 'string' ||
        typeof value === 'number' ||
        // $flow-disable-line
        typeof value === 'symbol' ||
        typeof value === 'boolean');
}
function isFunction(value) {
    return typeof value === 'function';
}
/**
 * Quick object check - this is primarily used to tell
 * objects from primitive values when we know the value
 * is a JSON-compliant type.
 */
function isObject(obj) {
    return obj !== null && typeof obj === 'object';
}
/**
 * Get the raw type string of a value, e.g., [object Object].
 */
var _toString = Object.prototype.toString;
function toRawType(value) {
    return _toString.call(value).slice(8, -1);
}
/**
 * Strict object type check. Only returns true
 * for plain JavaScript objects.
 */
function isPlainObject(obj) {
    return _toString.call(obj) === '[object Object]';
}
function isRegExp(v) {
    return _toString.call(v) === '[object RegExp]';
}
/**
 * Check if val is a valid array index.
 */
function isValidArrayIndex(val) {
    var n = parseFloat(String(val));
    return n >= 0 && Math.floor(n) === n && isFinite(val);
}
function isPromise(val) {
    return (isDef(val) &&
        typeof val.then === 'function' &&
        typeof val.catch === 'function');
}
/**
 * Convert a value to a string that is actually rendered.
 */
function toString(val) {
    return val == null
        ? ''
        : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)
            ? JSON.stringify(val, replacer, 2)
            : String(val);
}
function replacer(_key, val) {
    // avoid circular deps from v3
    if (val && val.__v_isRef) {
        return val.value;
    }
    return val;
}
/**
 * Convert an input value to a number for persistence.
 * If the conversion fails, return original string.
 */
function toNumber(val) {
    var n = parseFloat(val);
    return isNaN(n) ? val : n;
}
/**
 * Make a map and return a function for checking if a key
 * is in that map.
 */
function makeMap(str, expectsLowerCase) {
    var map = Object.create(null);
    var list = str.split(',');
    for (var i = 0; i < list.length; i++) {
        map[list[i]] = true;
    }
    return expectsLowerCase ? function (val) { return map[val.toLowerCase()]; } : function (val) { return map[val]; };
}
/**
 * Check if a tag is a built-in tag.
 */
var isBuiltInTag = makeMap('slot,component', true);
/**
 * Check if an attribute is a reserved attribute.
 */
var isReservedAttribute = makeMap('key,ref,slot,slot-scope,is');
/**
 * Remove an item from an array.
 */
function remove$2(arr, item) {
    var len = arr.length;
    if (len) {
        // fast path for the only / last item
        if (item === arr[len - 1]) {
            arr.length = len - 1;
            return;
        }
        var index = arr.indexOf(item);
        if (index > -1) {
            return arr.splice(index, 1);
        }
    }
}
/**
 * Check whether an object has the property.
 */
var hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn(obj, key) {
    return hasOwnProperty.call(obj, key);
}
/**
 * Create a cached version of a pure function.
 */
function cached(fn) {
    var cache = Object.create(null);
    return function cachedFn(str) {
        var hit = cache[str];
        return hit || (cache[str] = fn(str));
    };
}
/**
 * Camelize a hyphen-delimited string.
 */
var camelizeRE = /-(\w)/g;
var camelize = cached(function (str) {
    return str.replace(camelizeRE, function (_, c) { return (c ? c.toUpperCase() : ''); });
});
/**
 * Capitalize a string.
 */
var capitalize = cached(function (str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
});
/**
 * Hyphenate a camelCase string.
 */
var hyphenateRE = /\B([A-Z])/g;
var hyphenate = cached(function (str) {
    return str.replace(hyphenateRE, '-$1').toLowerCase();
});
/**
 * Simple bind polyfill for environments that do not support it,
 * e.g., PhantomJS 1.x. Technically, we don't need this anymore
 * since native bind is now performant enough in most browsers.
 * But removing it would mean breaking code that was able to run in
 * PhantomJS 1.x, so this must be kept for backward compatibility.
 */
/* istanbul ignore next */
function polyfillBind(fn, ctx) {
    function boundFn(a) {
        var l = arguments.length;
        return l
            ? l > 1
                ? fn.apply(ctx, arguments)
                : fn.call(ctx, a)
            : fn.call(ctx);
    }
    boundFn._length = fn.length;
    return boundFn;
}
function nativeBind(fn, ctx) {
    return fn.bind(ctx);
}
// @ts-expect-error bind cannot be `undefined`
var bind = Function.prototype.bind ? nativeBind : polyfillBind;
/**
 * Convert an Array-like object to a real Array.
 */
function toArray(list, start) {
    start = start || 0;
    var i = list.length - start;
    var ret = new Array(i);
    while (i--) {
        ret[i] = list[i + start];
    }
    return ret;
}
/**
 * Mix properties into target object.
 */
function extend(to, _from) {
    for (var key in _from) {
        to[key] = _from[key];
    }
    return to;
}
/**
 * Merge an Array of Objects into a single Object.
 */
function toObject(arr) {
    var res = {};
    for (var i = 0; i < arr.length; i++) {
        if (arr[i]) {
            extend(res, arr[i]);
        }
    }
    return res;
}
/* eslint-disable no-unused-vars */
/**
 * Perform no operation.
 * Stubbing args to make Flow happy without leaving useless transpiled code
 * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/).
 */
function noop(a, b, c) { }
/**
 * Always return false.
 */
var no = function (a, b, c) { return false; };
/* eslint-enable no-unused-vars */
/**
 * Return the same value.
 */
var identity = function (_) { return _; };
/**
 * Check if two values are loosely equal - that is,
 * if they are plain objects, do they have the same shape?
 */
function looseEqual(a, b) {
    if (a === b)
        return true;
    var isObjectA = isObject(a);
    var isObjectB = isObject(b);
    if (isObjectA && isObjectB) {
        try {
            var isArrayA = Array.isArray(a);
            var isArrayB = Array.isArray(b);
            if (isArrayA && isArrayB) {
                return (a.length === b.length &&
                    a.every(function (e, i) {
                        return looseEqual(e, b[i]);
                    }));
            }
            else if (a instanceof Date && b instanceof Date) {
                return a.getTime() === b.getTime();
            }
            else if (!isArrayA && !isArrayB) {
                var keysA = Object.keys(a);
                var keysB = Object.keys(b);
                return (keysA.length === keysB.length &&
                    keysA.every(function (key) {
                        return looseEqual(a[key], b[key]);
                    }));
            }
            else {
                /* istanbul ignore next */
                return false;
            }
        }
        catch (e) {
            /* istanbul ignore next */
            return false;
        }
    }
    else if (!isObjectA && !isObjectB) {
        return String(a) === String(b);
    }
    else {
        return false;
    }
}
/**
 * Return the first index at which a loosely equal value can be
 * found in the array (if value is a plain object, the array must
 * contain an object of the same shape), or -1 if it is not present.
 */
function looseIndexOf(arr, val) {
    for (var i = 0; i < arr.length; i++) {
        if (looseEqual(arr[i], val))
            return i;
    }
    return -1;
}
/**
 * Ensure a function is called only once.
 */
function once(fn) {
    var called = false;
    return function () {
        if (!called) {
            called = true;
            fn.apply(this, arguments);
        }
    };
}
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#polyfill
function hasChanged(x, y) {
    if (x === y) {
        return x === 0 && 1 / x !== 1 / y;
    }
    else {
        return x === x || y === y;
    }
}

var SSR_ATTR = 'data-server-rendered';
var ASSET_TYPES = ['component', 'directive', 'filter'];
var LIFECYCLE_HOOKS = [
    'beforeCreate',
    'created',
    'beforeMount',
    'mounted',
    'beforeUpdate',
    'updated',
    'beforeDestroy',
    'destroyed',
    'activated',
    'deactivated',
    'errorCaptured',
    'serverPrefetch',
    'renderTracked',
    'renderTriggered'
];

var config = {
    /**
     * Option merge strategies (used in core/util/options)
     */
    // $flow-disable-line
    optionMergeStrategies: Object.create(null),
    /**
     * Whether to suppress warnings.
     */
    silent: false,
    /**
     * Show production mode tip message on boot?
     */
    productionTip: "development" !== 'production',
    /**
     * Whether to enable devtools
     */
    devtools: "development" !== 'production',
    /**
     * Whether to record perf
     */
    performance: false,
    /**
     * Error handler for watcher errors
     */
    errorHandler: null,
    /**
     * Warn handler for watcher warns
     */
    warnHandler: null,
    /**
     * Ignore certain custom elements
     */
    ignoredElements: [],
    /**
     * Custom user key aliases for v-on
     */
    // $flow-disable-line
    keyCodes: Object.create(null),
    /**
     * Check if a tag is reserved so that it cannot be registered as a
     * component. This is platform-dependent and may be overwritten.
     */
    isReservedTag: no,
    /**
     * Check if an attribute is reserved so that it cannot be used as a component
     * prop. This is platform-dependent and may be overwritten.
     */
    isReservedAttr: no,
    /**
     * Check if a tag is an unknown element.
     * Platform-dependent.
     */
    isUnknownElement: no,
    /**
     * Get the namespace of an element
     */
    getTagNamespace: noop,
    /**
     * Parse the real tag name for the specific platform.
     */
    parsePlatformTagName: identity,
    /**
     * Check if an attribute must be bound using property, e.g. value
     * Platform-dependent.
     */
    mustUseProp: no,
    /**
     * Perform updates asynchronously. Intended to be used by Vue Test Utils
     * This will significantly reduce performance if set to false.
     */
    async: true,
    /**
     * Exposed for legacy reasons
     */
    _lifecycleHooks: LIFECYCLE_HOOKS
};

/**
 * unicode letters used for parsing html tags, component names and property paths.
 * using https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname
 * skipping \u10000-\uEFFFF due to it freezing up PhantomJS
 */
var unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/;
/**
 * Check if a string starts with $ or _
 */
function isReserved(str) {
    var c = (str + '').charCodeAt(0);
    return c === 0x24 || c === 0x5f;
}
/**
 * Define a property.
 */
function def(obj, key, val, enumerable) {
    Object.defineProperty(obj, key, {
        value: val,
        enumerable: !!enumerable,
        writable: true,
        configurable: true
    });
}
/**
 * Parse simple path.
 */
var bailRE = new RegExp("[^".concat(unicodeRegExp.source, ".$_\\d]"));
function parsePath(path) {
    if (bailRE.test(path)) {
        return;
    }
    var segments = path.split('.');
    return function (obj) {
        for (var i = 0; i < segments.length; i++) {
            if (!obj)
                return;
            obj = obj[segments[i]];
        }
        return obj;
    };
}

// can we use __proto__?
var hasProto = '__proto__' in {};
// Browser environment sniffing
var inBrowser = typeof window !== 'undefined';
var UA = inBrowser && window.navigator.userAgent.toLowerCase();
var isIE = UA && /msie|trident/.test(UA);
var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
var isEdge = UA && UA.indexOf('edge/') > 0;
UA && UA.indexOf('android') > 0;
var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA);
UA && /chrome\/\d+/.test(UA) && !isEdge;
UA && /phantomjs/.test(UA);
var isFF = UA && UA.match(/firefox\/(\d+)/);
// Firefox has a "watch" function on Object.prototype...
// @ts-expect-error firebox support
var nativeWatch = {}.watch;
var supportsPassive = false;
if (inBrowser) {
    try {
        var opts = {};
        Object.defineProperty(opts, 'passive', {
            get: function () {
                /* istanbul ignore next */
                supportsPassive = true;
            }
        }); // https://github.com/facebook/flow/issues/285
        window.addEventListener('test-passive', null, opts);
    }
    catch (e) { }
}
// this needs to be lazy-evaled because vue may be required before
// vue-server-renderer can set VUE_ENV
var _isServer;
var isServerRendering = function () {
    if (_isServer === undefined) {
        /* istanbul ignore if */
        if (!inBrowser && typeof __webpack_require__.g !== 'undefined') {
            // detect presence of vue-server-renderer and avoid
            // Webpack shimming the process
            _isServer =
                __webpack_require__.g['process'] && __webpack_require__.g['process'].env.VUE_ENV === 'server';
        }
        else {
            _isServer = false;
        }
    }
    return _isServer;
};
// detect devtools
var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__;
/* istanbul ignore next */
function isNative(Ctor) {
    return typeof Ctor === 'function' && /native code/.test(Ctor.toString());
}
var hasSymbol = typeof Symbol !== 'undefined' &&
    isNative(Symbol) &&
    typeof Reflect !== 'undefined' &&
    isNative(Reflect.ownKeys);
var _Set; // $flow-disable-line
/* istanbul ignore if */ if (typeof Set !== 'undefined' && isNative(Set)) {
    // use native Set when available.
    _Set = Set;
}
else {
    // a non-standard Set polyfill that only works with primitive keys.
    _Set = /** @class */ (function () {
        function Set() {
            this.set = Object.create(null);
        }
        Set.prototype.has = function (key) {
            return this.set[key] === true;
        };
        Set.prototype.add = function (key) {
            this.set[key] = true;
        };
        Set.prototype.clear = function () {
            this.set = Object.create(null);
        };
        return Set;
    }());
}

var currentInstance = null;
/**
 * This is exposed for compatibility with v3 (e.g. some functions in VueUse
 * relies on it). Do not use this internally, just use `currentInstance`.
 *
 * @internal this function needs manual type declaration because it relies
 * on previously manually authored types from Vue 2
 */
function getCurrentInstance() {
    return currentInstance && { proxy: currentInstance };
}
/**
 * @internal
 */
function setCurrentInstance(vm) {
    if (vm === void 0) { vm = null; }
    if (!vm)
        currentInstance && currentInstance._scope.off();
    currentInstance = vm;
    vm && vm._scope.on();
}

/**
 * @internal
 */
var VNode = /** @class */ (function () {
    function VNode(tag, data, children, text, elm, context, componentOptions, asyncFactory) {
        this.tag = tag;
        this.data = data;
        this.children = children;
        this.text = text;
        this.elm = elm;
        this.ns = undefined;
        this.context = context;
        this.fnContext = undefined;
        this.fnOptions = undefined;
        this.fnScopeId = undefined;
        this.key = data && data.key;
        this.componentOptions = componentOptions;
        this.componentInstance = undefined;
        this.parent = undefined;
        this.raw = false;
        this.isStatic = false;
        this.isRootInsert = true;
        this.isComment = false;
        this.isCloned = false;
        this.isOnce = false;
        this.asyncFactory = asyncFactory;
        this.asyncMeta = undefined;
        this.isAsyncPlaceholder = false;
    }
    Object.defineProperty(VNode.prototype, "child", {
        // DEPRECATED: alias for componentInstance for backwards compat.
        /* istanbul ignore next */
        get: function () {
            return this.componentInstance;
        },
        enumerable: false,
        configurable: true
    });
    return VNode;
}());
var createEmptyVNode = function (text) {
    if (text === void 0) { text = ''; }
    var node = new VNode();
    node.text = text;
    node.isComment = true;
    return node;
};
function createTextVNode(val) {
    return new VNode(undefined, undefined, undefined, String(val));
}
// optimized shallow clone
// used for static nodes and slot nodes because they may be reused across
// multiple renders, cloning them avoids errors when DOM manipulations rely
// on their elm reference.
function cloneVNode(vnode) {
    var cloned = new VNode(vnode.tag, vnode.data, 
    // #7975
    // clone children array to avoid mutating original in case of cloning
    // a child.
    vnode.children && vnode.children.slice(), vnode.text, vnode.elm, vnode.context, vnode.componentOptions, vnode.asyncFactory);
    cloned.ns = vnode.ns;
    cloned.isStatic = vnode.isStatic;
    cloned.key = vnode.key;
    cloned.isComment = vnode.isComment;
    cloned.fnContext = vnode.fnContext;
    cloned.fnOptions = vnode.fnOptions;
    cloned.fnScopeId = vnode.fnScopeId;
    cloned.asyncMeta = vnode.asyncMeta;
    cloned.isCloned = true;
    return cloned;
}

/******************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

var __assign = function() {
    __assign = Object.assign || function __assign(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};

typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
    var e = new Error(message);
    return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};

var uid$2 = 0;
var pendingCleanupDeps = [];
var cleanupDeps = function () {
    for (var i = 0; i < pendingCleanupDeps.length; i++) {
        var dep = pendingCleanupDeps[i];
        dep.subs = dep.subs.filter(function (s) { return s; });
        dep._pending = false;
    }
    pendingCleanupDeps.length = 0;
};
/**
 * A dep is an observable that can have multiple
 * directives subscribing to it.
 * @internal
 */
var Dep = /** @class */ (function () {
    function Dep() {
        // pending subs cleanup
        this._pending = false;
        this.id = uid$2++;
        this.subs = [];
    }
    Dep.prototype.addSub = function (sub) {
        this.subs.push(sub);
    };
    Dep.prototype.removeSub = function (sub) {
        // #12696 deps with massive amount of subscribers are extremely slow to
        // clean up in Chromium
        // to workaround this, we unset the sub for now, and clear them on
        // next scheduler flush.
        this.subs[this.subs.indexOf(sub)] = null;
        if (!this._pending) {
            this._pending = true;
            pendingCleanupDeps.push(this);
        }
    };
    Dep.prototype.depend = function (info) {
        if (Dep.target) {
            Dep.target.addDep(this);
            if ( true && info && Dep.target.onTrack) {
                Dep.target.onTrack(__assign({ effect: Dep.target }, info));
            }
        }
    };
    Dep.prototype.notify = function (info) {
        // stabilize the subscriber list first
        var subs = this.subs.filter(function (s) { return s; });
        if ( true && !config.async) {
            // subs aren't sorted in scheduler if not running async
            // we need to sort them now to make sure they fire in correct
            // order
            subs.sort(function (a, b) { return a.id - b.id; });
        }
        for (var i = 0, l = subs.length; i < l; i++) {
            var sub = subs[i];
            if ( true && info) {
                sub.onTrigger &&
                    sub.onTrigger(__assign({ effect: subs[i] }, info));
            }
            sub.update();
        }
    };
    return Dep;
}());
// The current target watcher being evaluated.
// This is globally unique because only one watcher
// can be evaluated at a time.
Dep.target = null;
var targetStack = [];
function pushTarget(target) {
    targetStack.push(target);
    Dep.target = target;
}
function popTarget() {
    targetStack.pop();
    Dep.target = targetStack[targetStack.length - 1];
}

/*
 * not type checking this file because flow doesn't play well with
 * dynamically accessing methods on Array prototype
 */
var arrayProto = Array.prototype;
var arrayMethods = Object.create(arrayProto);
var methodsToPatch = [
    'push',
    'pop',
    'shift',
    'unshift',
    'splice',
    'sort',
    'reverse'
];
/**
 * Intercept mutating methods and emit events
 */
methodsToPatch.forEach(function (method) {
    // cache original method
    var original = arrayProto[method];
    def(arrayMethods, method, function mutator() {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        var result = original.apply(this, args);
        var ob = this.__ob__;
        var inserted;
        switch (method) {
            case 'push':
            case 'unshift':
                inserted = args;
                break;
            case 'splice':
                inserted = args.slice(2);
                break;
        }
        if (inserted)
            ob.observeArray(inserted);
        // notify change
        if (true) {
            ob.dep.notify({
                type: "array mutation" /* TriggerOpTypes.ARRAY_MUTATION */,
                target: this,
                key: method
            });
        }
        else {}
        return result;
    });
});

var arrayKeys = Object.getOwnPropertyNames(arrayMethods);
var NO_INITIAL_VALUE = {};
/**
 * In some cases we may want to disable observation inside a component's
 * update computation.
 */
var shouldObserve = true;
function toggleObserving(value) {
    shouldObserve = value;
}
// ssr mock dep
var mockDep = {
    notify: noop,
    depend: noop,
    addSub: noop,
    removeSub: noop
};
/**
 * Observer class that is attached to each observed
 * object. Once attached, the observer converts the target
 * object's property keys into getter/setters that
 * collect dependencies and dispatch updates.
 */
var Observer = /** @class */ (function () {
    function Observer(value, shallow, mock) {
        if (shallow === void 0) { shallow = false; }
        if (mock === void 0) { mock = false; }
        this.value = value;
        this.shallow = shallow;
        this.mock = mock;
        // this.value = value
        this.dep = mock ? mockDep : new Dep();
        this.vmCount = 0;
        def(value, '__ob__', this);
        if (isArray(value)) {
            if (!mock) {
                if (hasProto) {
                    value.__proto__ = arrayMethods;
                    /* eslint-enable no-proto */
                }
                else {
                    for (var i = 0, l = arrayKeys.length; i < l; i++) {
                        var key = arrayKeys[i];
                        def(value, key, arrayMethods[key]);
                    }
                }
            }
            if (!shallow) {
                this.observeArray(value);
            }
        }
        else {
            /**
             * Walk through all properties and convert them into
             * getter/setters. This method should only be called when
             * value type is Object.
             */
            var keys = Object.keys(value);
            for (var i = 0; i < keys.length; i++) {
                var key = keys[i];
                defineReactive(value, key, NO_INITIAL_VALUE, undefined, shallow, mock);
            }
        }
    }
    /**
     * Observe a list of Array items.
     */
    Observer.prototype.observeArray = function (value) {
        for (var i = 0, l = value.length; i < l; i++) {
            observe(value[i], false, this.mock);
        }
    };
    return Observer;
}());
// helpers
/**
 * Attempt to create an observer instance for a value,
 * returns the new observer if successfully observed,
 * or the existing observer if the value already has one.
 */
function observe(value, shallow, ssrMockReactivity) {
    if (value && hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
        return value.__ob__;
    }
    if (shouldObserve &&
        (ssrMockReactivity || !isServerRendering()) &&
        (isArray(value) || isPlainObject(value)) &&
        Object.isExtensible(value) &&
        !value.__v_skip /* ReactiveFlags.SKIP */ &&
        !isRef(value) &&
        !(value instanceof VNode)) {
        return new Observer(value, shallow, ssrMockReactivity);
    }
}
/**
 * Define a reactive property on an Object.
 */
function defineReactive(obj, key, val, customSetter, shallow, mock, observeEvenIfShallow) {
    if (observeEvenIfShallow === void 0) { observeEvenIfShallow = false; }
    var dep = new Dep();
    var property = Object.getOwnPropertyDescriptor(obj, key);
    if (property && property.configurable === false) {
        return;
    }
    // cater for pre-defined getter/setters
    var getter = property && property.get;
    var setter = property && property.set;
    if ((!getter || setter) &&
        (val === NO_INITIAL_VALUE || arguments.length === 2)) {
        val = obj[key];
    }
    var childOb = shallow ? val && val.__ob__ : observe(val, false, mock);
    Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: function reactiveGetter() {
            var value = getter ? getter.call(obj) : val;
            if (Dep.target) {
                if (true) {
                    dep.depend({
                        target: obj,
                        type: "get" /* TrackOpTypes.GET */,
                        key: key
                    });
                }
                else {}
                if (childOb) {
                    childOb.dep.depend();
                    if (isArray(value)) {
                        dependArray(value);
                    }
                }
            }
            return isRef(value) && !shallow ? value.value : value;
        },
        set: function reactiveSetter(newVal) {
            var value = getter ? getter.call(obj) : val;
            if (!hasChanged(value, newVal)) {
                return;
            }
            if ( true && customSetter) {
                customSetter();
            }
            if (setter) {
                setter.call(obj, newVal);
            }
            else if (getter) {
                // #7981: for accessor properties without setter
                return;
            }
            else if (!shallow && isRef(value) && !isRef(newVal)) {
                value.value = newVal;
                return;
            }
            else {
                val = newVal;
            }
            childOb = shallow ? newVal && newVal.__ob__ : observe(newVal, false, mock);
            if (true) {
                dep.notify({
                    type: "set" /* TriggerOpTypes.SET */,
                    target: obj,
                    key: key,
                    newValue: newVal,
                    oldValue: value
                });
            }
            else {}
        }
    });
    return dep;
}
function set(target, key, val) {
    if ( true && (isUndef(target) || isPrimitive(target))) {
        warn("Cannot set reactive property on undefined, null, or primitive value: ".concat(target));
    }
    if (isReadonly(target)) {
         true && warn("Set operation on key \"".concat(key, "\" failed: target is readonly."));
        return;
    }
    var ob = target.__ob__;
    if (isArray(target) && isValidArrayIndex(key)) {
        target.length = Math.max(target.length, key);
        target.splice(key, 1, val);
        // when mocking for SSR, array methods are not hijacked
        if (ob && !ob.shallow && ob.mock) {
            observe(val, false, true);
        }
        return val;
    }
    if (key in target && !(key in Object.prototype)) {
        target[key] = val;
        return val;
    }
    if (target._isVue || (ob && ob.vmCount)) {
         true &&
            warn('Avoid adding reactive properties to a Vue instance or its root $data ' +
                'at runtime - declare it upfront in the data option.');
        return val;
    }
    if (!ob) {
        target[key] = val;
        return val;
    }
    defineReactive(ob.value, key, val, undefined, ob.shallow, ob.mock);
    if (true) {
        ob.dep.notify({
            type: "add" /* TriggerOpTypes.ADD */,
            target: target,
            key: key,
            newValue: val,
            oldValue: undefined
        });
    }
    else {}
    return val;
}
function del(target, key) {
    if ( true && (isUndef(target) || isPrimitive(target))) {
        warn("Cannot delete reactive property on undefined, null, or primitive value: ".concat(target));
    }
    if (isArray(target) && isValidArrayIndex(key)) {
        target.splice(key, 1);
        return;
    }
    var ob = target.__ob__;
    if (target._isVue || (ob && ob.vmCount)) {
         true &&
            warn('Avoid deleting properties on a Vue instance or its root $data ' +
                '- just set it to null.');
        return;
    }
    if (isReadonly(target)) {
         true &&
            warn("Delete operation on key \"".concat(key, "\" failed: target is readonly."));
        return;
    }
    if (!hasOwn(target, key)) {
        return;
    }
    delete target[key];
    if (!ob) {
        return;
    }
    if (true) {
        ob.dep.notify({
            type: "delete" /* TriggerOpTypes.DELETE */,
            target: target,
            key: key
        });
    }
    else {}
}
/**
 * Collect dependencies on array elements when the array is touched, since
 * we cannot intercept array element access like property getters.
 */
function dependArray(value) {
    for (var e = void 0, i = 0, l = value.length; i < l; i++) {
        e = value[i];
        if (e && e.__ob__) {
            e.__ob__.dep.depend();
        }
        if (isArray(e)) {
            dependArray(e);
        }
    }
}

function reactive(target) {
    makeReactive(target, false);
    return target;
}
/**
 * Return a shallowly-reactive copy of the original object, where only the root
 * level properties are reactive. It also does not auto-unwrap refs (even at the
 * root level).
 */
function shallowReactive(target) {
    makeReactive(target, true);
    def(target, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, true);
    return target;
}
function makeReactive(target, shallow) {
    // if trying to observe a readonly proxy, return the readonly version.
    if (!isReadonly(target)) {
        if (true) {
            if (isArray(target)) {
                warn("Avoid using Array as root value for ".concat(shallow ? "shallowReactive()" : "reactive()", " as it cannot be tracked in watch() or watchEffect(). Use ").concat(shallow ? "shallowRef()" : "ref()", " instead. This is a Vue-2-only limitation."));
            }
            var existingOb = target && target.__ob__;
            if (existingOb && existingOb.shallow !== shallow) {
                warn("Target is already a ".concat(existingOb.shallow ? "" : "non-", "shallow reactive object, and cannot be converted to ").concat(shallow ? "" : "non-", "shallow."));
            }
        }
        var ob = observe(target, shallow, isServerRendering() /* ssr mock reactivity */);
        if ( true && !ob) {
            if (target == null || isPrimitive(target)) {
                warn("value cannot be made reactive: ".concat(String(target)));
            }
            if (isCollectionType(target)) {
                warn("Vue 2 does not support reactive collection types such as Map or Set.");
            }
        }
    }
}
function isReactive(value) {
    if (isReadonly(value)) {
        return isReactive(value["__v_raw" /* ReactiveFlags.RAW */]);
    }
    return !!(value && value.__ob__);
}
function isShallow(value) {
    return !!(value && value.__v_isShallow);
}
function isReadonly(value) {
    return !!(value && value.__v_isReadonly);
}
function isProxy(value) {
    return isReactive(value) || isReadonly(value);
}
function toRaw(observed) {
    var raw = observed && observed["__v_raw" /* ReactiveFlags.RAW */];
    return raw ? toRaw(raw) : observed;
}
function markRaw(value) {
    // non-extensible objects won't be observed anyway
    if (Object.isExtensible(value)) {
        def(value, "__v_skip" /* ReactiveFlags.SKIP */, true);
    }
    return value;
}
/**
 * @internal
 */
function isCollectionType(value) {
    var type = toRawType(value);
    return (type === 'Map' || type === 'WeakMap' || type === 'Set' || type === 'WeakSet');
}

/**
 * @internal
 */
var RefFlag = "__v_isRef";
function isRef(r) {
    return !!(r && r.__v_isRef === true);
}
function ref$1(value) {
    return createRef(value, false);
}
function shallowRef(value) {
    return createRef(value, true);
}
function createRef(rawValue, shallow) {
    if (isRef(rawValue)) {
        return rawValue;
    }
    var ref = {};
    def(ref, RefFlag, true);
    def(ref, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, shallow);
    def(ref, 'dep', defineReactive(ref, 'value', rawValue, null, shallow, isServerRendering()));
    return ref;
}
function triggerRef(ref) {
    if ( true && !ref.dep) {
        warn("received object is not a triggerable ref.");
    }
    if (true) {
        ref.dep &&
            ref.dep.notify({
                type: "set" /* TriggerOpTypes.SET */,
                target: ref,
                key: 'value'
            });
    }
    else {}
}
function unref(ref) {
    return isRef(ref) ? ref.value : ref;
}
function proxyRefs(objectWithRefs) {
    if (isReactive(objectWithRefs)) {
        return objectWithRefs;
    }
    var proxy = {};
    var keys = Object.keys(objectWithRefs);
    for (var i = 0; i < keys.length; i++) {
        proxyWithRefUnwrap(proxy, objectWithRefs, keys[i]);
    }
    return proxy;
}
function proxyWithRefUnwrap(target, source, key) {
    Object.defineProperty(target, key, {
        enumerable: true,
        configurable: true,
        get: function () {
            var val = source[key];
            if (isRef(val)) {
                return val.value;
            }
            else {
                var ob = val && val.__ob__;
                if (ob)
                    ob.dep.depend();
                return val;
            }
        },
        set: function (value) {
            var oldValue = source[key];
            if (isRef(oldValue) && !isRef(value)) {
                oldValue.value = value;
            }
            else {
                source[key] = value;
            }
        }
    });
}
function customRef(factory) {
    var dep = new Dep();
    var _a = factory(function () {
        if (true) {
            dep.depend({
                target: ref,
                type: "get" /* TrackOpTypes.GET */,
                key: 'value'
            });
        }
        else {}
    }, function () {
        if (true) {
            dep.notify({
                target: ref,
                type: "set" /* TriggerOpTypes.SET */,
                key: 'value'
            });
        }
        else {}
    }), get = _a.get, set = _a.set;
    var ref = {
        get value() {
            return get();
        },
        set value(newVal) {
            set(newVal);
        }
    };
    def(ref, RefFlag, true);
    return ref;
}
function toRefs(object) {
    if ( true && !isReactive(object)) {
        warn("toRefs() expects a reactive object but received a plain one.");
    }
    var ret = isArray(object) ? new Array(object.length) : {};
    for (var key in object) {
        ret[key] = toRef(object, key);
    }
    return ret;
}
function toRef(object, key, defaultValue) {
    var val = object[key];
    if (isRef(val)) {
        return val;
    }
    var ref = {
        get value() {
            var val = object[key];
            return val === undefined ? defaultValue : val;
        },
        set value(newVal) {
            object[key] = newVal;
        }
    };
    def(ref, RefFlag, true);
    return ref;
}

var rawToReadonlyFlag = "__v_rawToReadonly";
var rawToShallowReadonlyFlag = "__v_rawToShallowReadonly";
function readonly(target) {
    return createReadonly(target, false);
}
function createReadonly(target, shallow) {
    if (!isPlainObject(target)) {
        if (true) {
            if (isArray(target)) {
                warn("Vue 2 does not support readonly arrays.");
            }
            else if (isCollectionType(target)) {
                warn("Vue 2 does not support readonly collection types such as Map or Set.");
            }
            else {
                warn("value cannot be made readonly: ".concat(typeof target));
            }
        }
        return target;
    }
    if ( true && !Object.isExtensible(target)) {
        warn("Vue 2 does not support creating readonly proxy for non-extensible object.");
    }
    // already a readonly object
    if (isReadonly(target)) {
        return target;
    }
    // already has a readonly proxy
    var existingFlag = shallow ? rawToShallowReadonlyFlag : rawToReadonlyFlag;
    var existingProxy = target[existingFlag];
    if (existingProxy) {
        return existingProxy;
    }
    var proxy = Object.create(Object.getPrototypeOf(target));
    def(target, existingFlag, proxy);
    def(proxy, "__v_isReadonly" /* ReactiveFlags.IS_READONLY */, true);
    def(proxy, "__v_raw" /* ReactiveFlags.RAW */, target);
    if (isRef(target)) {
        def(proxy, RefFlag, true);
    }
    if (shallow || isShallow(target)) {
        def(proxy, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, true);
    }
    var keys = Object.keys(target);
    for (var i = 0; i < keys.length; i++) {
        defineReadonlyProperty(proxy, target, keys[i], shallow);
    }
    return proxy;
}
function defineReadonlyProperty(proxy, target, key, shallow) {
    Object.defineProperty(proxy, key, {
        enumerable: true,
        configurable: true,
        get: function () {
            var val = target[key];
            return shallow || !isPlainObject(val) ? val : readonly(val);
        },
        set: function () {
             true &&
                warn("Set operation on key \"".concat(key, "\" failed: target is readonly."));
        }
    });
}
/**
 * Returns a reactive-copy of the original object, where only the root level
 * properties are readonly, and does NOT unwrap refs nor recursively convert
 * returned properties.
 * This is used for creating the props proxy object for stateful components.
 */
function shallowReadonly(target) {
    return createReadonly(target, true);
}

function computed(getterOrOptions, debugOptions) {
    var getter;
    var setter;
    var onlyGetter = isFunction(getterOrOptions);
    if (onlyGetter) {
        getter = getterOrOptions;
        setter =  true
            ? function () {
                warn('Write operation failed: computed value is readonly');
            }
            : 0;
    }
    else {
        getter = getterOrOptions.get;
        setter = getterOrOptions.set;
    }
    var watcher = isServerRendering()
        ? null
        : new Watcher(currentInstance, getter, noop, { lazy: true });
    if ( true && watcher && debugOptions) {
        watcher.onTrack = debugOptions.onTrack;
        watcher.onTrigger = debugOptions.onTrigger;
    }
    var ref = {
        // some libs rely on the presence effect for checking computed refs
        // from normal refs, but the implementation doesn't matter
        effect: watcher,
        get value() {
            if (watcher) {
                if (watcher.dirty) {
                    watcher.evaluate();
                }
                if (Dep.target) {
                    if ( true && Dep.target.onTrack) {
                        Dep.target.onTrack({
                            effect: Dep.target,
                            target: ref,
                            type: "get" /* TrackOpTypes.GET */,
                            key: 'value'
                        });
                    }
                    watcher.depend();
                }
                return watcher.value;
            }
            else {
                return getter();
            }
        },
        set value(newVal) {
            setter(newVal);
        }
    };
    def(ref, RefFlag, true);
    def(ref, "__v_isReadonly" /* ReactiveFlags.IS_READONLY */, onlyGetter);
    return ref;
}

var WATCHER = "watcher";
var WATCHER_CB = "".concat(WATCHER, " callback");
var WATCHER_GETTER = "".concat(WATCHER, " getter");
var WATCHER_CLEANUP = "".concat(WATCHER, " cleanup");
// Simple effect.
function watchEffect(effect, options) {
    return doWatch(effect, null, options);
}
function watchPostEffect(effect, options) {
    return doWatch(effect, null, ( true
        ? __assign(__assign({}, options), { flush: 'post' }) : 0));
}
function watchSyncEffect(effect, options) {
    return doWatch(effect, null, ( true
        ? __assign(__assign({}, options), { flush: 'sync' }) : 0));
}
// initial value for watchers to trigger on undefined initial values
var INITIAL_WATCHER_VALUE = {};
// implementation
function watch(source, cb, options) {
    if ( true && typeof cb !== 'function') {
        warn("`watch(fn, options?)` signature has been moved to a separate API. " +
            "Use `watchEffect(fn, options?)` instead. `watch` now only " +
            "supports `watch(source, cb, options?) signature.");
    }
    return doWatch(source, cb, options);
}
function doWatch(source, cb, _a) {
    var _b = _a === void 0 ? emptyObject : _a, immediate = _b.immediate, deep = _b.deep, _c = _b.flush, flush = _c === void 0 ? 'pre' : _c, onTrack = _b.onTrack, onTrigger = _b.onTrigger;
    if ( true && !cb) {
        if (immediate !== undefined) {
            warn("watch() \"immediate\" option is only respected when using the " +
                "watch(source, callback, options?) signature.");
        }
        if (deep !== undefined) {
            warn("watch() \"deep\" option is only respected when using the " +
                "watch(source, callback, options?) signature.");
        }
    }
    var warnInvalidSource = function (s) {
        warn("Invalid watch source: ".concat(s, ". A watch source can only be a getter/effect ") +
            "function, a ref, a reactive object, or an array of these types.");
    };
    var instance = currentInstance;
    var call = function (fn, type, args) {
        if (args === void 0) { args = null; }
        var res = invokeWithErrorHandling(fn, null, args, instance, type);
        if (deep && res && res.__ob__)
            res.__ob__.dep.depend();
        return res;
    };
    var getter;
    var forceTrigger = false;
    var isMultiSource = false;
    if (isRef(source)) {
        getter = function () { return source.value; };
        forceTrigger = isShallow(source);
    }
    else if (isReactive(source)) {
        getter = function () {
            source.__ob__.dep.depend();
            return source;
        };
        deep = true;
    }
    else if (isArray(source)) {
        isMultiSource = true;
        forceTrigger = source.some(function (s) { return isReactive(s) || isShallow(s); });
        getter = function () {
            return source.map(function (s) {
                if (isRef(s)) {
                    return s.value;
                }
                else if (isReactive(s)) {
                    s.__ob__.dep.depend();
                    return traverse(s);
                }
                else if (isFunction(s)) {
                    return call(s, WATCHER_GETTER);
                }
                else {
                     true && warnInvalidSource(s);
                }
            });
        };
    }
    else if (isFunction(source)) {
        if (cb) {
            // getter with cb
            getter = function () { return call(source, WATCHER_GETTER); };
        }
        else {
            // no cb -> simple effect
            getter = function () {
                if (instance && instance._isDestroyed) {
                    return;
                }
                if (cleanup) {
                    cleanup();
                }
                return call(source, WATCHER, [onCleanup]);
            };
        }
    }
    else {
        getter = noop;
         true && warnInvalidSource(source);
    }
    if (cb && deep) {
        var baseGetter_1 = getter;
        getter = function () { return traverse(baseGetter_1()); };
    }
    var cleanup;
    var onCleanup = function (fn) {
        cleanup = watcher.onStop = function () {
            call(fn, WATCHER_CLEANUP);
        };
    };
    // in SSR there is no need to setup an actual effect, and it should be noop
    // unless it's eager
    if (isServerRendering()) {
        // we will also not call the invalidate callback (+ runner is not set up)
        onCleanup = noop;
        if (!cb) {
            getter();
        }
        else if (immediate) {
            call(cb, WATCHER_CB, [
                getter(),
                isMultiSource ? [] : undefined,
                onCleanup
            ]);
        }
        return noop;
    }
    var watcher = new Watcher(currentInstance, getter, noop, {
        lazy: true
    });
    watcher.noRecurse = !cb;
    var oldValue = isMultiSource ? [] : INITIAL_WATCHER_VALUE;
    // overwrite default run
    watcher.run = function () {
        if (!watcher.active) {
            return;
        }
        if (cb) {
            // watch(source, cb)
            var newValue = watcher.get();
            if (deep ||
                forceTrigger ||
                (isMultiSource
                    ? newValue.some(function (v, i) {
                        return hasChanged(v, oldValue[i]);
                    })
                    : hasChanged(newValue, oldValue))) {
                // cleanup before running cb again
                if (cleanup) {
                    cleanup();
                }
                call(cb, WATCHER_CB, [
                    newValue,
                    // pass undefined as the old value when it's changed for the first time
                    oldValue === INITIAL_WATCHER_VALUE ? undefined : oldValue,
                    onCleanup
                ]);
                oldValue = newValue;
            }
        }
        else {
            // watchEffect
            watcher.get();
        }
    };
    if (flush === 'sync') {
        watcher.update = watcher.run;
    }
    else if (flush === 'post') {
        watcher.post = true;
        watcher.update = function () { return queueWatcher(watcher); };
    }
    else {
        // pre
        watcher.update = function () {
            if (instance && instance === currentInstance && !instance._isMounted) {
                // pre-watcher triggered before
                var buffer = instance._preWatchers || (instance._preWatchers = []);
                if (buffer.indexOf(watcher) < 0)
                    buffer.push(watcher);
            }
            else {
                queueWatcher(watcher);
            }
        };
    }
    if (true) {
        watcher.onTrack = onTrack;
        watcher.onTrigger = onTrigger;
    }
    // initial run
    if (cb) {
        if (immediate) {
            watcher.run();
        }
        else {
            oldValue = watcher.get();
        }
    }
    else if (flush === 'post' && instance) {
        instance.$once('hook:mounted', function () { return watcher.get(); });
    }
    else {
        watcher.get();
    }
    return function () {
        watcher.teardown();
    };
}

var activeEffectScope;
var EffectScope = /** @class */ (function () {
    function EffectScope(detached) {
        if (detached === void 0) { detached = false; }
        this.detached = detached;
        /**
         * @internal
         */
        this.active = true;
        /**
         * @internal
         */
        this.effects = [];
        /**
         * @internal
         */
        this.cleanups = [];
        this.parent = activeEffectScope;
        if (!detached && activeEffectScope) {
            this.index =
                (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push(this) - 1;
        }
    }
    EffectScope.prototype.run = function (fn) {
        if (this.active) {
            var currentEffectScope = activeEffectScope;
            try {
                activeEffectScope = this;
                return fn();
            }
            finally {
                activeEffectScope = currentEffectScope;
            }
        }
        else if (true) {
            warn("cannot run an inactive effect scope.");
        }
    };
    /**
     * This should only be called on non-detached scopes
     * @internal
     */
    EffectScope.prototype.on = function () {
        activeEffectScope = this;
    };
    /**
     * This should only be called on non-detached scopes
     * @internal
     */
    EffectScope.prototype.off = function () {
        activeEffectScope = this.parent;
    };
    EffectScope.prototype.stop = function (fromParent) {
        if (this.active) {
            var i = void 0, l = void 0;
            for (i = 0, l = this.effects.length; i < l; i++) {
                this.effects[i].teardown();
            }
            for (i = 0, l = this.cleanups.length; i < l; i++) {
                this.cleanups[i]();
            }
            if (this.scopes) {
                for (i = 0, l = this.scopes.length; i < l; i++) {
                    this.scopes[i].stop(true);
                }
            }
            // nested scope, dereference from parent to avoid memory leaks
            if (!this.detached && this.parent && !fromParent) {
                // optimized O(1) removal
                var last = this.parent.scopes.pop();
                if (last && last !== this) {
                    this.parent.scopes[this.index] = last;
                    last.index = this.index;
                }
            }
            this.parent = undefined;
            this.active = false;
        }
    };
    return EffectScope;
}());
function effectScope(detached) {
    return new EffectScope(detached);
}
/**
 * @internal
 */
function recordEffectScope(effect, scope) {
    if (scope === void 0) { scope = activeEffectScope; }
    if (scope && scope.active) {
        scope.effects.push(effect);
    }
}
function getCurrentScope() {
    return activeEffectScope;
}
function onScopeDispose(fn) {
    if (activeEffectScope) {
        activeEffectScope.cleanups.push(fn);
    }
    else if (true) {
        warn("onScopeDispose() is called when there is no active effect scope" +
            " to be associated with.");
    }
}

function provide(key, value) {
    if (!currentInstance) {
        if (true) {
            warn("provide() can only be used inside setup().");
        }
    }
    else {
        // TS doesn't allow symbol as index type
        resolveProvided(currentInstance)[key] = value;
    }
}
function resolveProvided(vm) {
    // by default an instance inherits its parent's provides object
    // but when it needs to provide values of its own, it creates its
    // own provides object using parent provides object as prototype.
    // this way in `inject` we can simply look up injections from direct
    // parent and let the prototype chain do the work.
    var existing = vm._provided;
    var parentProvides = vm.$parent && vm.$parent._provided;
    if (parentProvides === existing) {
        return (vm._provided = Object.create(parentProvides));
    }
    else {
        return existing;
    }
}
function inject(key, defaultValue, treatDefaultAsFactory) {
    if (treatDefaultAsFactory === void 0) { treatDefaultAsFactory = false; }
    // fallback to `currentRenderingInstance` so that this can be called in
    // a functional component
    var instance = currentInstance;
    if (instance) {
        // #2400
        // to support `app.use` plugins,
        // fallback to appContext's `provides` if the instance is at root
        var provides = instance.$parent && instance.$parent._provided;
        if (provides && key in provides) {
            // TS doesn't allow symbol as index type
            return provides[key];
        }
        else if (arguments.length > 1) {
            return treatDefaultAsFactory && isFunction(defaultValue)
                ? defaultValue.call(instance)
                : defaultValue;
        }
        else if (true) {
            warn("injection \"".concat(String(key), "\" not found."));
        }
    }
    else if (true) {
        warn("inject() can only be used inside setup() or functional components.");
    }
}

var normalizeEvent = cached(function (name) {
    var passive = name.charAt(0) === '&';
    name = passive ? name.slice(1) : name;
    var once = name.charAt(0) === '~'; // Prefixed last, checked first
    name = once ? name.slice(1) : name;
    var capture = name.charAt(0) === '!';
    name = capture ? name.slice(1) : name;
    return {
        name: name,
        once: once,
        capture: capture,
        passive: passive
    };
});
function createFnInvoker(fns, vm) {
    function invoker() {
        var fns = invoker.fns;
        if (isArray(fns)) {
            var cloned = fns.slice();
            for (var i = 0; i < cloned.length; i++) {
                invokeWithErrorHandling(cloned[i], null, arguments, vm, "v-on handler");
            }
        }
        else {
            // return handler return value for single handlers
            return invokeWithErrorHandling(fns, null, arguments, vm, "v-on handler");
        }
    }
    invoker.fns = fns;
    return invoker;
}
function updateListeners(on, oldOn, add, remove, createOnceHandler, vm) {
    var name, cur, old, event;
    for (name in on) {
        cur = on[name];
        old = oldOn[name];
        event = normalizeEvent(name);
        if (isUndef(cur)) {
             true &&
                warn("Invalid handler for event \"".concat(event.name, "\": got ") + String(cur), vm);
        }
        else if (isUndef(old)) {
            if (isUndef(cur.fns)) {
                cur = on[name] = createFnInvoker(cur, vm);
            }
            if (isTrue(event.once)) {
                cur = on[name] = createOnceHandler(event.name, cur, event.capture);
            }
            add(event.name, cur, event.capture, event.passive, event.params);
        }
        else if (cur !== old) {
            old.fns = cur;
            on[name] = old;
        }
    }
    for (name in oldOn) {
        if (isUndef(on[name])) {
            event = normalizeEvent(name);
            remove(event.name, oldOn[name], event.capture);
        }
    }
}

function mergeVNodeHook(def, hookKey, hook) {
    if (def instanceof VNode) {
        def = def.data.hook || (def.data.hook = {});
    }
    var invoker;
    var oldHook = def[hookKey];
    function wrappedHook() {
        hook.apply(this, arguments);
        // important: remove merged hook to ensure it's called only once
        // and prevent memory leak
        remove$2(invoker.fns, wrappedHook);
    }
    if (isUndef(oldHook)) {
        // no existing hook
        invoker = createFnInvoker([wrappedHook]);
    }
    else {
        /* istanbul ignore if */
        if (isDef(oldHook.fns) && isTrue(oldHook.merged)) {
            // already a merged invoker
            invoker = oldHook;
            invoker.fns.push(wrappedHook);
        }
        else {
            // existing plain hook
            invoker = createFnInvoker([oldHook, wrappedHook]);
        }
    }
    invoker.merged = true;
    def[hookKey] = invoker;
}

function extractPropsFromVNodeData(data, Ctor, tag) {
    // we are only extracting raw values here.
    // validation and default values are handled in the child
    // component itself.
    var propOptions = Ctor.options.props;
    if (isUndef(propOptions)) {
        return;
    }
    var res = {};
    var attrs = data.attrs, props = data.props;
    if (isDef(attrs) || isDef(props)) {
        for (var key in propOptions) {
            var altKey = hyphenate(key);
            if (true) {
                var keyInLowerCase = key.toLowerCase();
                if (key !== keyInLowerCase && attrs && hasOwn(attrs, keyInLowerCase)) {
                    tip("Prop \"".concat(keyInLowerCase, "\" is passed to component ") +
                        "".concat(formatComponentName(
                        // @ts-expect-error tag is string
                        tag || Ctor), ", but the declared prop name is") +
                        " \"".concat(key, "\". ") +
                        "Note that HTML attributes are case-insensitive and camelCased " +
                        "props need to use their kebab-case equivalents when using in-DOM " +
                        "templates. You should probably use \"".concat(altKey, "\" instead of \"").concat(key, "\"."));
                }
            }
            checkProp(res, props, key, altKey, true) ||
                checkProp(res, attrs, key, altKey, false);
        }
    }
    return res;
}
function checkProp(res, hash, key, altKey, preserve) {
    if (isDef(hash)) {
        if (hasOwn(hash, key)) {
            res[key] = hash[key];
            if (!preserve) {
                delete hash[key];
            }
            return true;
        }
        else if (hasOwn(hash, altKey)) {
            res[key] = hash[altKey];
            if (!preserve) {
                delete hash[altKey];
            }
            return true;
        }
    }
    return false;
}

// The template compiler attempts to minimize the need for normalization by
// statically analyzing the template at compile time.
//
// For plain HTML markup, normalization can be completely skipped because the
// generated render function is guaranteed to return Array<VNode>. There are
// two cases where extra normalization is needed:
// 1. When the children contains components - because a functional component
// may return an Array instead of a single root. In this case, just a simple
// normalization is needed - if any child is an Array, we flatten the whole
// thing with Array.prototype.concat. It is guaranteed to be only 1-level deep
// because functional components already normalize their own children.
function simpleNormalizeChildren(children) {
    for (var i = 0; i < children.length; i++) {
        if (isArray(children[i])) {
            return Array.prototype.concat.apply([], children);
        }
    }
    return children;
}
// 2. When the children contains constructs that always generated nested Arrays,
// e.g. <template>, <slot>, v-for, or when the children is provided by user
// with hand-written render functions / JSX. In such cases a full normalization
// is needed to cater to all possible types of children values.
function normalizeChildren(children) {
    return isPrimitive(children)
        ? [createTextVNode(children)]
        : isArray(children)
            ? normalizeArrayChildren(children)
            : undefined;
}
function isTextNode(node) {
    return isDef(node) && isDef(node.text) && isFalse(node.isComment);
}
function normalizeArrayChildren(children, nestedIndex) {
    var res = [];
    var i, c, lastIndex, last;
    for (i = 0; i < children.length; i++) {
        c = children[i];
        if (isUndef(c) || typeof c === 'boolean')
            continue;
        lastIndex = res.length - 1;
        last = res[lastIndex];
        //  nested
        if (isArray(c)) {
            if (c.length > 0) {
                c = normalizeArrayChildren(c, "".concat(nestedIndex || '', "_").concat(i));
                // merge adjacent text nodes
                if (isTextNode(c[0]) && isTextNode(last)) {
                    res[lastIndex] = createTextVNode(last.text + c[0].text);
                    c.shift();
                }
                res.push.apply(res, c);
            }
        }
        else if (isPrimitive(c)) {
            if (isTextNode(last)) {
                // merge adjacent text nodes
                // this is necessary for SSR hydration because text nodes are
                // essentially merged when rendered to HTML strings
                res[lastIndex] = createTextVNode(last.text + c);
            }
            else if (c !== '') {
                // convert primitive to vnode
                res.push(createTextVNode(c));
            }
        }
        else {
            if (isTextNode(c) && isTextNode(last)) {
                // merge adjacent text nodes
                res[lastIndex] = createTextVNode(last.text + c.text);
            }
            else {
                // default key for nested array children (likely generated by v-for)
                if (isTrue(children._isVList) &&
                    isDef(c.tag) &&
                    isUndef(c.key) &&
                    isDef(nestedIndex)) {
                    c.key = "__vlist".concat(nestedIndex, "_").concat(i, "__");
                }
                res.push(c);
            }
        }
    }
    return res;
}

/**
 * Runtime helper for rendering v-for lists.
 */
function renderList(val, render) {
    var ret = null, i, l, keys, key;
    if (isArray(val) || typeof val === 'string') {
        ret = new Array(val.length);
        for (i = 0, l = val.length; i < l; i++) {
            ret[i] = render(val[i], i);
        }
    }
    else if (typeof val === 'number') {
        ret = new Array(val);
        for (i = 0; i < val; i++) {
            ret[i] = render(i + 1, i);
        }
    }
    else if (isObject(val)) {
        if (hasSymbol && val[Symbol.iterator]) {
            ret = [];
            var iterator = val[Symbol.iterator]();
            var result = iterator.next();
            while (!result.done) {
                ret.push(render(result.value, ret.length));
                result = iterator.next();
            }
        }
        else {
            keys = Object.keys(val);
            ret = new Array(keys.length);
            for (i = 0, l = keys.length; i < l; i++) {
                key = keys[i];
                ret[i] = render(val[key], key, i);
            }
        }
    }
    if (!isDef(ret)) {
        ret = [];
    }
    ret._isVList = true;
    return ret;
}

/**
 * Runtime helper for rendering <slot>
 */
function renderSlot(name, fallbackRender, props, bindObject) {
    var scopedSlotFn = this.$scopedSlots[name];
    var nodes;
    if (scopedSlotFn) {
        // scoped slot
        props = props || {};
        if (bindObject) {
            if ( true && !isObject(bindObject)) {
                warn('slot v-bind without argument expects an Object', this);
            }
            props = extend(extend({}, bindObject), props);
        }
        nodes =
            scopedSlotFn(props) ||
                (isFunction(fallbackRender) ? fallbackRender() : fallbackRender);
    }
    else {
        nodes =
            this.$slots[name] ||
                (isFunction(fallbackRender) ? fallbackRender() : fallbackRender);
    }
    var target = props && props.slot;
    if (target) {
        return this.$createElement('template', { slot: target }, nodes);
    }
    else {
        return nodes;
    }
}

/**
 * Runtime helper for resolving filters
 */
function resolveFilter(id) {
    return resolveAsset(this.$options, 'filters', id, true) || identity;
}

function isKeyNotMatch(expect, actual) {
    if (isArray(expect)) {
        return expect.indexOf(actual) === -1;
    }
    else {
        return expect !== actual;
    }
}
/**
 * Runtime helper for checking keyCodes from config.
 * exposed as Vue.prototype._k
 * passing in eventKeyName as last argument separately for backwards compat
 */
function checkKeyCodes(eventKeyCode, key, builtInKeyCode, eventKeyName, builtInKeyName) {
    var mappedKeyCode = config.keyCodes[key] || builtInKeyCode;
    if (builtInKeyName && eventKeyName && !config.keyCodes[key]) {
        return isKeyNotMatch(builtInKeyName, eventKeyName);
    }
    else if (mappedKeyCode) {
        return isKeyNotMatch(mappedKeyCode, eventKeyCode);
    }
    else if (eventKeyName) {
        return hyphenate(eventKeyName) !== key;
    }
    return eventKeyCode === undefined;
}

/**
 * Runtime helper for merging v-bind="object" into a VNode's data.
 */
function bindObjectProps(data, tag, value, asProp, isSync) {
    if (value) {
        if (!isObject(value)) {
             true &&
                warn('v-bind without argument expects an Object or Array value', this);
        }
        else {
            if (isArray(value)) {
                value = toObject(value);
            }
            var hash = void 0;
            var _loop_1 = function (key) {
                if (key === 'class' || key === 'style' || isReservedAttribute(key)) {
                    hash = data;
                }
                else {
                    var type = data.attrs && data.attrs.type;
                    hash =
                        asProp || config.mustUseProp(tag, type, key)
                            ? data.domProps || (data.domProps = {})
                            : data.attrs || (data.attrs = {});
                }
                var camelizedKey = camelize(key);
                var hyphenatedKey = hyphenate(key);
                if (!(camelizedKey in hash) && !(hyphenatedKey in hash)) {
                    hash[key] = value[key];
                    if (isSync) {
                        var on = data.on || (data.on = {});
                        on["update:".concat(key)] = function ($event) {
                            value[key] = $event;
                        };
                    }
                }
            };
            for (var key in value) {
                _loop_1(key);
            }
        }
    }
    return data;
}

/**
 * Runtime helper for rendering static trees.
 */
function renderStatic(index, isInFor) {
    var cached = this._staticTrees || (this._staticTrees = []);
    var tree = cached[index];
    // if has already-rendered static tree and not inside v-for,
    // we can reuse the same tree.
    if (tree && !isInFor) {
        return tree;
    }
    // otherwise, render a fresh tree.
    tree = cached[index] = this.$options.staticRenderFns[index].call(this._renderProxy, this._c, this // for render fns generated for functional component templates
    );
    markStatic(tree, "__static__".concat(index), false);
    return tree;
}
/**
 * Runtime helper for v-once.
 * Effectively it means marking the node as static with a unique key.
 */
function markOnce(tree, index, key) {
    markStatic(tree, "__once__".concat(index).concat(key ? "_".concat(key) : ""), true);
    return tree;
}
function markStatic(tree, key, isOnce) {
    if (isArray(tree)) {
        for (var i = 0; i < tree.length; i++) {
            if (tree[i] && typeof tree[i] !== 'string') {
                markStaticNode(tree[i], "".concat(key, "_").concat(i), isOnce);
            }
        }
    }
    else {
        markStaticNode(tree, key, isOnce);
    }
}
function markStaticNode(node, key, isOnce) {
    node.isStatic = true;
    node.key = key;
    node.isOnce = isOnce;
}

function bindObjectListeners(data, value) {
    if (value) {
        if (!isPlainObject(value)) {
             true && warn('v-on without argument expects an Object value', this);
        }
        else {
            var on = (data.on = data.on ? extend({}, data.on) : {});
            for (var key in value) {
                var existing = on[key];
                var ours = value[key];
                on[key] = existing ? [].concat(existing, ours) : ours;
            }
        }
    }
    return data;
}

function resolveScopedSlots(fns, res, 
// the following are added in 2.6
hasDynamicKeys, contentHashKey) {
    res = res || { $stable: !hasDynamicKeys };
    for (var i = 0; i < fns.length; i++) {
        var slot = fns[i];
        if (isArray(slot)) {
            resolveScopedSlots(slot, res, hasDynamicKeys);
        }
        else if (slot) {
            // marker for reverse proxying v-slot without scope on this.$slots
            // @ts-expect-error
            if (slot.proxy) {
                // @ts-expect-error
                slot.fn.proxy = true;
            }
            res[slot.key] = slot.fn;
        }
    }
    if (contentHashKey) {
        res.$key = contentHashKey;
    }
    return res;
}

// helper to process dynamic keys for dynamic arguments in v-bind and v-on.
function bindDynamicKeys(baseObj, values) {
    for (var i = 0; i < values.length; i += 2) {
        var key = values[i];
        if (typeof key === 'string' && key) {
            baseObj[values[i]] = values[i + 1];
        }
        else if ( true && key !== '' && key !== null) {
            // null is a special value for explicitly removing a binding
            warn("Invalid value for dynamic directive argument (expected string or null): ".concat(key), this);
        }
    }
    return baseObj;
}
// helper to dynamically append modifier runtime markers to event names.
// ensure only append when value is already string, otherwise it will be cast
// to string and cause the type check to miss.
function prependModifier(value, symbol) {
    return typeof value === 'string' ? symbol + value : value;
}

function installRenderHelpers(target) {
    target._o = markOnce;
    target._n = toNumber;
    target._s = toString;
    target._l = renderList;
    target._t = renderSlot;
    target._q = looseEqual;
    target._i = looseIndexOf;
    target._m = renderStatic;
    target._f = resolveFilter;
    target._k = checkKeyCodes;
    target._b = bindObjectProps;
    target._v = createTextVNode;
    target._e = createEmptyVNode;
    target._u = resolveScopedSlots;
    target._g = bindObjectListeners;
    target._d = bindDynamicKeys;
    target._p = prependModifier;
}

/**
 * Runtime helper for resolving raw children VNodes into a slot object.
 */
function resolveSlots(children, context) {
    if (!children || !children.length) {
        return {};
    }
    var slots = {};
    for (var i = 0, l = children.length; i < l; i++) {
        var child = children[i];
        var data = child.data;
        // remove slot attribute if the node is resolved as a Vue slot node
        if (data && data.attrs && data.attrs.slot) {
            delete data.attrs.slot;
        }
        // named slots should only be respected if the vnode was rendered in the
        // same context.
        if ((child.context === context || child.fnContext === context) &&
            data &&
            data.slot != null) {
            var name_1 = data.slot;
            var slot = slots[name_1] || (slots[name_1] = []);
            if (child.tag === 'template') {
                slot.push.apply(slot, child.children || []);
            }
            else {
                slot.push(child);
            }
        }
        else {
            (slots.default || (slots.default = [])).push(child);
        }
    }
    // ignore slots that contains only whitespace
    for (var name_2 in slots) {
        if (slots[name_2].every(isWhitespace)) {
            delete slots[name_2];
        }
    }
    return slots;
}
function isWhitespace(node) {
    return (node.isComment && !node.asyncFactory) || node.text === ' ';
}

function isAsyncPlaceholder(node) {
    // @ts-expect-error not really boolean type
    return node.isComment && node.asyncFactory;
}

function normalizeScopedSlots(ownerVm, scopedSlots, normalSlots, prevScopedSlots) {
    var res;
    var hasNormalSlots = Object.keys(normalSlots).length > 0;
    var isStable = scopedSlots ? !!scopedSlots.$stable : !hasNormalSlots;
    var key = scopedSlots && scopedSlots.$key;
    if (!scopedSlots) {
        res = {};
    }
    else if (scopedSlots._normalized) {
        // fast path 1: child component re-render only, parent did not change
        return scopedSlots._normalized;
    }
    else if (isStable &&
        prevScopedSlots &&
        prevScopedSlots !== emptyObject &&
        key === prevScopedSlots.$key &&
        !hasNormalSlots &&
        !prevScopedSlots.$hasNormal) {
        // fast path 2: stable scoped slots w/ no normal slots to proxy,
        // only need to normalize once
        return prevScopedSlots;
    }
    else {
        res = {};
        for (var key_1 in scopedSlots) {
            if (scopedSlots[key_1] && key_1[0] !== '$') {
                res[key_1] = normalizeScopedSlot(ownerVm, normalSlots, key_1, scopedSlots[key_1]);
            }
        }
    }
    // expose normal slots on scopedSlots
    for (var key_2 in normalSlots) {
        if (!(key_2 in res)) {
            res[key_2] = proxyNormalSlot(normalSlots, key_2);
        }
    }
    // avoriaz seems to mock a non-extensible $scopedSlots object
    // and when that is passed down this would cause an error
    if (scopedSlots && Object.isExtensible(scopedSlots)) {
        scopedSlots._normalized = res;
    }
    def(res, '$stable', isStable);
    def(res, '$key', key);
    def(res, '$hasNormal', hasNormalSlots);
    return res;
}
function normalizeScopedSlot(vm, normalSlots, key, fn) {
    var normalized = function () {
        var cur = currentInstance;
        setCurrentInstance(vm);
        var res = arguments.length ? fn.apply(null, arguments) : fn({});
        res =
            res && typeof res === 'object' && !isArray(res)
                ? [res] // single vnode
                : normalizeChildren(res);
        var vnode = res && res[0];
        setCurrentInstance(cur);
        return res &&
            (!vnode ||
                (res.length === 1 && vnode.isComment && !isAsyncPlaceholder(vnode))) // #9658, #10391
            ? undefined
            : res;
    };
    // this is a slot using the new v-slot syntax without scope. although it is
    // compiled as a scoped slot, render fn users would expect it to be present
    // on this.$slots because the usage is semantically a normal slot.
    if (fn.proxy) {
        Object.defineProperty(normalSlots, key, {
            get: normalized,
            enumerable: true,
            configurable: true
        });
    }
    return normalized;
}
function proxyNormalSlot(slots, key) {
    return function () { return slots[key]; };
}

function initSetup(vm) {
    var options = vm.$options;
    var setup = options.setup;
    if (setup) {
        var ctx = (vm._setupContext = createSetupContext(vm));
        setCurrentInstance(vm);
        pushTarget();
        var setupResult = invokeWithErrorHandling(setup, null, [vm._props || shallowReactive({}), ctx], vm, "setup");
        popTarget();
        setCurrentInstance();
        if (isFunction(setupResult)) {
            // render function
            // @ts-ignore
            options.render = setupResult;
        }
        else if (isObject(setupResult)) {
            // bindings
            if ( true && setupResult instanceof VNode) {
                warn("setup() should not return VNodes directly - " +
                    "return a render function instead.");
            }
            vm._setupState = setupResult;
            // __sfc indicates compiled bindings from <script setup>
            if (!setupResult.__sfc) {
                for (var key in setupResult) {
                    if (!isReserved(key)) {
                        proxyWithRefUnwrap(vm, setupResult, key);
                    }
                    else if (true) {
                        warn("Avoid using variables that start with _ or $ in setup().");
                    }
                }
            }
            else {
                // exposed for compiled render fn
                var proxy = (vm._setupProxy = {});
                for (var key in setupResult) {
                    if (key !== '__sfc') {
                        proxyWithRefUnwrap(proxy, setupResult, key);
                    }
                }
            }
        }
        else if ( true && setupResult !== undefined) {
            warn("setup() should return an object. Received: ".concat(setupResult === null ? 'null' : typeof setupResult));
        }
    }
}
function createSetupContext(vm) {
    var exposeCalled = false;
    return {
        get attrs() {
            if (!vm._attrsProxy) {
                var proxy = (vm._attrsProxy = {});
                def(proxy, '_v_attr_proxy', true);
                syncSetupProxy(proxy, vm.$attrs, emptyObject, vm, '$attrs');
            }
            return vm._attrsProxy;
        },
        get listeners() {
            if (!vm._listenersProxy) {
                var proxy = (vm._listenersProxy = {});
                syncSetupProxy(proxy, vm.$listeners, emptyObject, vm, '$listeners');
            }
            return vm._listenersProxy;
        },
        get slots() {
            return initSlotsProxy(vm);
        },
        emit: bind(vm.$emit, vm),
        expose: function (exposed) {
            if (true) {
                if (exposeCalled) {
                    warn("expose() should be called only once per setup().", vm);
                }
                exposeCalled = true;
            }
            if (exposed) {
                Object.keys(exposed).forEach(function (key) {
                    return proxyWithRefUnwrap(vm, exposed, key);
                });
            }
        }
    };
}
function syncSetupProxy(to, from, prev, instance, type) {
    var changed = false;
    for (var key in from) {
        if (!(key in to)) {
            changed = true;
            defineProxyAttr(to, key, instance, type);
        }
        else if (from[key] !== prev[key]) {
            changed = true;
        }
    }
    for (var key in to) {
        if (!(key in from)) {
            changed = true;
            delete to[key];
        }
    }
    return changed;
}
function defineProxyAttr(proxy, key, instance, type) {
    Object.defineProperty(proxy, key, {
        enumerable: true,
        configurable: true,
        get: function () {
            return instance[type][key];
        }
    });
}
function initSlotsProxy(vm) {
    if (!vm._slotsProxy) {
        syncSetupSlots((vm._slotsProxy = {}), vm.$scopedSlots);
    }
    return vm._slotsProxy;
}
function syncSetupSlots(to, from) {
    for (var key in from) {
        to[key] = from[key];
    }
    for (var key in to) {
        if (!(key in from)) {
            delete to[key];
        }
    }
}
/**
 * @internal use manual type def because public setup context type relies on
 * legacy VNode types
 */
function useSlots() {
    return getContext().slots;
}
/**
 * @internal use manual type def because public setup context type relies on
 * legacy VNode types
 */
function useAttrs() {
    return getContext().attrs;
}
/**
 * Vue 2 only
 * @internal use manual type def because public setup context type relies on
 * legacy VNode types
 */
function useListeners() {
    return getContext().listeners;
}
function getContext() {
    if ( true && !currentInstance) {
        warn("useContext() called without active instance.");
    }
    var vm = currentInstance;
    return vm._setupContext || (vm._setupContext = createSetupContext(vm));
}
/**
 * Runtime helper for merging default declarations. Imported by compiled code
 * only.
 * @internal
 */
function mergeDefaults(raw, defaults) {
    var props = isArray(raw)
        ? raw.reduce(function (normalized, p) { return ((normalized[p] = {}), normalized); }, {})
        : raw;
    for (var key in defaults) {
        var opt = props[key];
        if (opt) {
            if (isArray(opt) || isFunction(opt)) {
                props[key] = { type: opt, default: defaults[key] };
            }
            else {
                opt.default = defaults[key];
            }
        }
        else if (opt === null) {
            props[key] = { default: defaults[key] };
        }
        else if (true) {
            warn("props default key \"".concat(key, "\" has no corresponding declaration."));
        }
    }
    return props;
}

function initRender(vm) {
    vm._vnode = null; // the root of the child tree
    vm._staticTrees = null; // v-once cached trees
    var options = vm.$options;
    var parentVnode = (vm.$vnode = options._parentVnode); // the placeholder node in parent tree
    var renderContext = parentVnode && parentVnode.context;
    vm.$slots = resolveSlots(options._renderChildren, renderContext);
    vm.$scopedSlots = parentVnode
        ? normalizeScopedSlots(vm.$parent, parentVnode.data.scopedSlots, vm.$slots)
        : emptyObject;
    // bind the createElement fn to this instance
    // so that we get proper render context inside it.
    // args order: tag, data, children, normalizationType, alwaysNormalize
    // internal version is used by render functions compiled from templates
    // @ts-expect-error
    vm._c = function (a, b, c, d) { return createElement$1(vm, a, b, c, d, false); };
    // normalization is always applied for the public version, used in
    // user-written render functions.
    // @ts-expect-error
    vm.$createElement = function (a, b, c, d) { return createElement$1(vm, a, b, c, d, true); };
    // $attrs & $listeners are exposed for easier HOC creation.
    // they need to be reactive so that HOCs using them are always updated
    var parentData = parentVnode && parentVnode.data;
    /* istanbul ignore else */
    if (true) {
        defineReactive(vm, '$attrs', (parentData && parentData.attrs) || emptyObject, function () {
            !isUpdatingChildComponent && warn("$attrs is readonly.", vm);
        }, true);
        defineReactive(vm, '$listeners', options._parentListeners || emptyObject, function () {
            !isUpdatingChildComponent && warn("$listeners is readonly.", vm);
        }, true);
    }
    else {}
}
var currentRenderingInstance = null;
function renderMixin(Vue) {
    // install runtime convenience helpers
    installRenderHelpers(Vue.prototype);
    Vue.prototype.$nextTick = function (fn) {
        return nextTick(fn, this);
    };
    Vue.prototype._render = function () {
        var vm = this;
        var _a = vm.$options, render = _a.render, _parentVnode = _a._parentVnode;
        if (_parentVnode && vm._isMounted) {
            vm.$scopedSlots = normalizeScopedSlots(vm.$parent, _parentVnode.data.scopedSlots, vm.$slots, vm.$scopedSlots);
            if (vm._slotsProxy) {
                syncSetupSlots(vm._slotsProxy, vm.$scopedSlots);
            }
        }
        // set parent vnode. this allows render functions to have access
        // to the data on the placeholder node.
        vm.$vnode = _parentVnode;
        // render self
        var prevInst = currentInstance;
        var prevRenderInst = currentRenderingInstance;
        var vnode;
        try {
            setCurrentInstance(vm);
            currentRenderingInstance = vm;
            vnode = render.call(vm._renderProxy, vm.$createElement);
        }
        catch (e) {
            handleError(e, vm, "render");
            // return error render result,
            // or previous vnode to prevent render error causing blank component
            /* istanbul ignore else */
            if ( true && vm.$options.renderError) {
                try {
                    vnode = vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e);
                }
                catch (e) {
                    handleError(e, vm, "renderError");
                    vnode = vm._vnode;
                }
            }
            else {
                vnode = vm._vnode;
            }
        }
        finally {
            currentRenderingInstance = prevRenderInst;
            setCurrentInstance(prevInst);
        }
        // if the returned array contains only a single node, allow it
        if (isArray(vnode) && vnode.length === 1) {
            vnode = vnode[0];
        }
        // return empty vnode in case the render function errored out
        if (!(vnode instanceof VNode)) {
            if ( true && isArray(vnode)) {
                warn('Multiple root nodes returned from render function. Render function ' +
                    'should return a single root node.', vm);
            }
            vnode = createEmptyVNode();
        }
        // set parent
        vnode.parent = _parentVnode;
        return vnode;
    };
}

function ensureCtor(comp, base) {
    if (comp.__esModule || (hasSymbol && comp[Symbol.toStringTag] === 'Module')) {
        comp = comp.default;
    }
    return isObject(comp) ? base.extend(comp) : comp;
}
function createAsyncPlaceholder(factory, data, context, children, tag) {
    var node = createEmptyVNode();
    node.asyncFactory = factory;
    node.asyncMeta = { data: data, context: context, children: children, tag: tag };
    return node;
}
function resolveAsyncComponent(factory, baseCtor) {
    if (isTrue(factory.error) && isDef(factory.errorComp)) {
        return factory.errorComp;
    }
    if (isDef(factory.resolved)) {
        return factory.resolved;
    }
    var owner = currentRenderingInstance;
    if (owner && isDef(factory.owners) && factory.owners.indexOf(owner) === -1) {
        // already pending
        factory.owners.push(owner);
    }
    if (isTrue(factory.loading) && isDef(factory.loadingComp)) {
        return factory.loadingComp;
    }
    if (owner && !isDef(factory.owners)) {
        var owners_1 = (factory.owners = [owner]);
        var sync_1 = true;
        var timerLoading_1 = null;
        var timerTimeout_1 = null;
        owner.$on('hook:destroyed', function () { return remove$2(owners_1, owner); });
        var forceRender_1 = function (renderCompleted) {
            for (var i = 0, l = owners_1.length; i < l; i++) {
                owners_1[i].$forceUpdate();
            }
            if (renderCompleted) {
                owners_1.length = 0;
                if (timerLoading_1 !== null) {
                    clearTimeout(timerLoading_1);
                    timerLoading_1 = null;
                }
                if (timerTimeout_1 !== null) {
                    clearTimeout(timerTimeout_1);
                    timerTimeout_1 = null;
                }
            }
        };
        var resolve = once(function (res) {
            // cache resolved
            factory.resolved = ensureCtor(res, baseCtor);
            // invoke callbacks only if this is not a synchronous resolve
            // (async resolves are shimmed as synchronous during SSR)
            if (!sync_1) {
                forceRender_1(true);
            }
            else {
                owners_1.length = 0;
            }
        });
        var reject_1 = once(function (reason) {
             true &&
                warn("Failed to resolve async component: ".concat(String(factory)) +
                    (reason ? "\nReason: ".concat(reason) : ''));
            if (isDef(factory.errorComp)) {
                factory.error = true;
                forceRender_1(true);
            }
        });
        var res_1 = factory(resolve, reject_1);
        if (isObject(res_1)) {
            if (isPromise(res_1)) {
                // () => Promise
                if (isUndef(factory.resolved)) {
                    res_1.then(resolve, reject_1);
                }
            }
            else if (isPromise(res_1.component)) {
                res_1.component.then(resolve, reject_1);
                if (isDef(res_1.error)) {
                    factory.errorComp = ensureCtor(res_1.error, baseCtor);
                }
                if (isDef(res_1.loading)) {
                    factory.loadingComp = ensureCtor(res_1.loading, baseCtor);
                    if (res_1.delay === 0) {
                        factory.loading = true;
                    }
                    else {
                        // @ts-expect-error NodeJS timeout type
                        timerLoading_1 = setTimeout(function () {
                            timerLoading_1 = null;
                            if (isUndef(factory.resolved) && isUndef(factory.error)) {
                                factory.loading = true;
                                forceRender_1(false);
                            }
                        }, res_1.delay || 200);
                    }
                }
                if (isDef(res_1.timeout)) {
                    // @ts-expect-error NodeJS timeout type
                    timerTimeout_1 = setTimeout(function () {
                        timerTimeout_1 = null;
                        if (isUndef(factory.resolved)) {
                            reject_1( true ? "timeout (".concat(res_1.timeout, "ms)") : 0);
                        }
                    }, res_1.timeout);
                }
            }
        }
        sync_1 = false;
        // return in case resolved synchronously
        return factory.loading ? factory.loadingComp : factory.resolved;
    }
}

function getFirstComponentChild(children) {
    if (isArray(children)) {
        for (var i = 0; i < children.length; i++) {
            var c = children[i];
            if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {
                return c;
            }
        }
    }
}

var SIMPLE_NORMALIZE = 1;
var ALWAYS_NORMALIZE = 2;
// wrapper function for providing a more flexible interface
// without getting yelled at by flow
function createElement$1(context, tag, data, children, normalizationType, alwaysNormalize) {
    if (isArray(data) || isPrimitive(data)) {
        normalizationType = children;
        children = data;
        data = undefined;
    }
    if (isTrue(alwaysNormalize)) {
        normalizationType = ALWAYS_NORMALIZE;
    }
    return _createElement(context, tag, data, children, normalizationType);
}
function _createElement(context, tag, data, children, normalizationType) {
    if (isDef(data) && isDef(data.__ob__)) {
         true &&
            warn("Avoid using observed data object as vnode data: ".concat(JSON.stringify(data), "\n") + 'Always create fresh vnode data objects in each render!', context);
        return createEmptyVNode();
    }
    // object syntax in v-bind
    if (isDef(data) && isDef(data.is)) {
        tag = data.is;
    }
    if (!tag) {
        // in case of component :is set to falsy value
        return createEmptyVNode();
    }
    // warn against non-primitive key
    if ( true && isDef(data) && isDef(data.key) && !isPrimitive(data.key)) {
        warn('Avoid using non-primitive value as key, ' +
            'use string/number value instead.', context);
    }
    // support single function children as default scoped slot
    if (isArray(children) && isFunction(children[0])) {
        data = data || {};
        data.scopedSlots = { default: children[0] };
        children.length = 0;
    }
    if (normalizationType === ALWAYS_NORMALIZE) {
        children = normalizeChildren(children);
    }
    else if (normalizationType === SIMPLE_NORMALIZE) {
        children = simpleNormalizeChildren(children);
    }
    var vnode, ns;
    if (typeof tag === 'string') {
        var Ctor = void 0;
        ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag);
        if (config.isReservedTag(tag)) {
            // platform built-in elements
            if ( true &&
                isDef(data) &&
                isDef(data.nativeOn) &&
                data.tag !== 'component') {
                warn("The .native modifier for v-on is only valid on components but it was used on <".concat(tag, ">."), context);
            }
            vnode = new VNode(config.parsePlatformTagName(tag), data, children, undefined, undefined, context);
        }
        else if ((!data || !data.pre) &&
            isDef((Ctor = resolveAsset(context.$options, 'components', tag)))) {
            // component
            vnode = createComponent(Ctor, data, context, children, tag);
        }
        else {
            // unknown or unlisted namespaced elements
            // check at runtime because it may get assigned a namespace when its
            // parent normalizes children
            vnode = new VNode(tag, data, children, undefined, undefined, context);
        }
    }
    else {
        // direct component options / constructor
        vnode = createComponent(tag, data, context, children);
    }
    if (isArray(vnode)) {
        return vnode;
    }
    else if (isDef(vnode)) {
        if (isDef(ns))
            applyNS(vnode, ns);
        if (isDef(data))
            registerDeepBindings(data);
        return vnode;
    }
    else {
        return createEmptyVNode();
    }
}
function applyNS(vnode, ns, force) {
    vnode.ns = ns;
    if (vnode.tag === 'foreignObject') {
        // use default namespace inside foreignObject
        ns = undefined;
        force = true;
    }
    if (isDef(vnode.children)) {
        for (var i = 0, l = vnode.children.length; i < l; i++) {
            var child = vnode.children[i];
            if (isDef(child.tag) &&
                (isUndef(child.ns) || (isTrue(force) && child.tag !== 'svg'))) {
                applyNS(child, ns, force);
            }
        }
    }
}
// ref #5318
// necessary to ensure parent re-render when deep bindings like :style and
// :class are used on slot nodes
function registerDeepBindings(data) {
    if (isObject(data.style)) {
        traverse(data.style);
    }
    if (isObject(data.class)) {
        traverse(data.class);
    }
}

/**
 * @internal this function needs manual public type declaration because it relies
 * on previously manually authored types from Vue 2
 */
function h(type, props, children) {
    if (!currentInstance) {
         true &&
            warn("globally imported h() can only be invoked when there is an active " +
                "component instance, e.g. synchronously in a component's render or setup function.");
    }
    return createElement$1(currentInstance, type, props, children, 2, true);
}

function handleError(err, vm, info) {
    // Deactivate deps tracking while processing error handler to avoid possible infinite rendering.
    // See: https://github.com/vuejs/vuex/issues/1505
    pushTarget();
    try {
        if (vm) {
            var cur = vm;
            while ((cur = cur.$parent)) {
                var hooks = cur.$options.errorCaptured;
                if (hooks) {
                    for (var i = 0; i < hooks.length; i++) {
                        try {
                            var capture = hooks[i].call(cur, err, vm, info) === false;
                            if (capture)
                                return;
                        }
                        catch (e) {
                            globalHandleError(e, cur, 'errorCaptured hook');
                        }
                    }
                }
            }
        }
        globalHandleError(err, vm, info);
    }
    finally {
        popTarget();
    }
}
function invokeWithErrorHandling(handler, context, args, vm, info) {
    var res;
    try {
        res = args ? handler.apply(context, args) : handler.call(context);
        if (res && !res._isVue && isPromise(res) && !res._handled) {
            res.catch(function (e) { return handleError(e, vm, info + " (Promise/async)"); });
            res._handled = true;
        }
    }
    catch (e) {
        handleError(e, vm, info);
    }
    return res;
}
function globalHandleError(err, vm, info) {
    if (config.errorHandler) {
        try {
            return config.errorHandler.call(null, err, vm, info);
        }
        catch (e) {
            // if the user intentionally throws the original error in the handler,
            // do not log it twice
            if (e !== err) {
                logError(e, null, 'config.errorHandler');
            }
        }
    }
    logError(err, vm, info);
}
function logError(err, vm, info) {
    if (true) {
        warn("Error in ".concat(info, ": \"").concat(err.toString(), "\""), vm);
    }
    /* istanbul ignore else */
    if (inBrowser && typeof console !== 'undefined') {
        console.error(err);
    }
    else {
        throw err;
    }
}

/* globals MutationObserver */
var isUsingMicroTask = false;
var callbacks = [];
var pending = false;
function flushCallbacks() {
    pending = false;
    var copies = callbacks.slice(0);
    callbacks.length = 0;
    for (var i = 0; i < copies.length; i++) {
        copies[i]();
    }
}
// Here we have async deferring wrappers using microtasks.
// In 2.5 we used (macro) tasks (in combination with microtasks).
// However, it has subtle problems when state is changed right before repaint
// (e.g. #6813, out-in transitions).
// Also, using (macro) tasks in event handler would cause some weird behaviors
// that cannot be circumvented (e.g. #7109, #7153, #7546, #7834, #8109).
// So we now use microtasks everywhere, again.
// A major drawback of this tradeoff is that there are some scenarios
// where microtasks have too high a priority and fire in between supposedly
// sequential events (e.g. #4521, #6690, which have workarounds)
// or even between bubbling of the same event (#6566).
var timerFunc;
// The nextTick behavior leverages the microtask queue, which can be accessed
// via either native Promise.then or MutationObserver.
// MutationObserver has wider support, however it is seriously bugged in
// UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It
// completely stops working after triggering a few times... so, if native
// Promise is available, we will use it:
/* istanbul ignore next, $flow-disable-line */
if (typeof Promise !== 'undefined' && isNative(Promise)) {
    var p_1 = Promise.resolve();
    timerFunc = function () {
        p_1.then(flushCallbacks);
        // In problematic UIWebViews, Promise.then doesn't completely break, but
        // it can get stuck in a weird state where callbacks are pushed into the
        // microtask queue but the queue isn't being flushed, until the browser
        // needs to do some other work, e.g. handle a timer. Therefore we can
        // "force" the microtask queue to be flushed by adding an empty timer.
        if (isIOS)
            setTimeout(noop);
    };
    isUsingMicroTask = true;
}
else if (!isIE &&
    typeof MutationObserver !== 'undefined' &&
    (isNative(MutationObserver) ||
        // PhantomJS and iOS 7.x
        MutationObserver.toString() === '[object MutationObserverConstructor]')) {
    // Use MutationObserver where native Promise is not available,
    // e.g. PhantomJS, iOS7, Android 4.4
    // (#6466 MutationObserver is unreliable in IE11)
    var counter_1 = 1;
    var observer = new MutationObserver(flushCallbacks);
    var textNode_1 = document.createTextNode(String(counter_1));
    observer.observe(textNode_1, {
        characterData: true
    });
    timerFunc = function () {
        counter_1 = (counter_1 + 1) % 2;
        textNode_1.data = String(counter_1);
    };
    isUsingMicroTask = true;
}
else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
    // Fallback to setImmediate.
    // Technically it leverages the (macro) task queue,
    // but it is still a better choice than setTimeout.
    timerFunc = function () {
        setImmediate(flushCallbacks);
    };
}
else {
    // Fallback to setTimeout.
    timerFunc = function () {
        setTimeout(flushCallbacks, 0);
    };
}
/**
 * @internal
 */
function nextTick(cb, ctx) {
    var _resolve;
    callbacks.push(function () {
        if (cb) {
            try {
                cb.call(ctx);
            }
            catch (e) {
                handleError(e, ctx, 'nextTick');
            }
        }
        else if (_resolve) {
            _resolve(ctx);
        }
    });
    if (!pending) {
        pending = true;
        timerFunc();
    }
    // $flow-disable-line
    if (!cb && typeof Promise !== 'undefined') {
        return new Promise(function (resolve) {
            _resolve = resolve;
        });
    }
}

function useCssModule(name) {
    if (name === void 0) { name = '$style'; }
    /* istanbul ignore else */
    {
        if (!currentInstance) {
             true && warn("useCssModule must be called inside setup()");
            return emptyObject;
        }
        var mod = currentInstance[name];
        if (!mod) {
             true &&
                warn("Current instance does not have CSS module named \"".concat(name, "\"."));
            return emptyObject;
        }
        return mod;
    }
}

/**
 * Runtime helper for SFC's CSS variable injection feature.
 * @private
 */
function useCssVars(getter) {
    if (!inBrowser && !false)
        return;
    var instance = currentInstance;
    if (!instance) {
         true &&
            warn("useCssVars is called without current active component instance.");
        return;
    }
    watchPostEffect(function () {
        var el = instance.$el;
        var vars = getter(instance, instance._setupProxy);
        if (el && el.nodeType === 1) {
            var style = el.style;
            for (var key in vars) {
                style.setProperty("--".concat(key), vars[key]);
            }
        }
    });
}

/**
 * v3-compatible async component API.
 * @internal the type is manually declared in <root>/types/v3-define-async-component.d.ts
 * because it relies on existing manual types
 */
function defineAsyncComponent(source) {
    if (isFunction(source)) {
        source = { loader: source };
    }
    var loader = source.loader, loadingComponent = source.loadingComponent, errorComponent = source.errorComponent, _a = source.delay, delay = _a === void 0 ? 200 : _a, timeout = source.timeout, // undefined = never times out
    _b = source.suspensible, // undefined = never times out
    suspensible = _b === void 0 ? false : _b, // in Vue 3 default is true
    userOnError = source.onError;
    if ( true && suspensible) {
        warn("The suspensible option for async components is not supported in Vue2. It is ignored.");
    }
    var pendingRequest = null;
    var retries = 0;
    var retry = function () {
        retries++;
        pendingRequest = null;
        return load();
    };
    var load = function () {
        var thisRequest;
        return (pendingRequest ||
            (thisRequest = pendingRequest =
                loader()
                    .catch(function (err) {
                    err = err instanceof Error ? err : new Error(String(err));
                    if (userOnError) {
                        return new Promise(function (resolve, reject) {
                            var userRetry = function () { return resolve(retry()); };
                            var userFail = function () { return reject(err); };
                            userOnError(err, userRetry, userFail, retries + 1);
                        });
                    }
                    else {
                        throw err;
                    }
                })
                    .then(function (comp) {
                    if (thisRequest !== pendingRequest && pendingRequest) {
                        return pendingRequest;
                    }
                    if ( true && !comp) {
                        warn("Async component loader resolved to undefined. " +
                            "If you are using retry(), make sure to return its return value.");
                    }
                    // interop module default
                    if (comp &&
                        (comp.__esModule || comp[Symbol.toStringTag] === 'Module')) {
                        comp = comp.default;
                    }
                    if ( true && comp && !isObject(comp) && !isFunction(comp)) {
                        throw new Error("Invalid async component load result: ".concat(comp));
                    }
                    return comp;
                })));
    };
    return function () {
        var component = load();
        return {
            component: component,
            delay: delay,
            timeout: timeout,
            error: errorComponent,
            loading: loadingComponent
        };
    };
}

function createLifeCycle(hookName) {
    return function (fn, target) {
        if (target === void 0) { target = currentInstance; }
        if (!target) {
             true &&
                warn("".concat(formatName(hookName), " is called when there is no active component instance to be ") +
                    "associated with. " +
                    "Lifecycle injection APIs can only be used during execution of setup().");
            return;
        }
        return injectHook(target, hookName, fn);
    };
}
function formatName(name) {
    if (name === 'beforeDestroy') {
        name = 'beforeUnmount';
    }
    else if (name === 'destroyed') {
        name = 'unmounted';
    }
    return "on".concat(name[0].toUpperCase() + name.slice(1));
}
function injectHook(instance, hookName, fn) {
    var options = instance.$options;
    options[hookName] = mergeLifecycleHook(options[hookName], fn);
}
var onBeforeMount = createLifeCycle('beforeMount');
var onMounted = createLifeCycle('mounted');
var onBeforeUpdate = createLifeCycle('beforeUpdate');
var onUpdated = createLifeCycle('updated');
var onBeforeUnmount = createLifeCycle('beforeDestroy');
var onUnmounted = createLifeCycle('destroyed');
var onActivated = createLifeCycle('activated');
var onDeactivated = createLifeCycle('deactivated');
var onServerPrefetch = createLifeCycle('serverPrefetch');
var onRenderTracked = createLifeCycle('renderTracked');
var onRenderTriggered = createLifeCycle('renderTriggered');
var injectErrorCapturedHook = createLifeCycle('errorCaptured');
function onErrorCaptured(hook, target) {
    if (target === void 0) { target = currentInstance; }
    injectErrorCapturedHook(hook, target);
}

/**
 * Note: also update dist/vue.runtime.mjs when adding new exports to this file.
 */
var version = '2.7.16';
/**
 * @internal type is manually declared in <root>/types/v3-define-component.d.ts
 */
function defineComponent(options) {
    return options;
}

var seenObjects = new _Set();
/**
 * Recursively traverse an object to evoke all converted
 * getters, so that every nested property inside the object
 * is collected as a "deep" dependency.
 */
function traverse(val) {
    _traverse(val, seenObjects);
    seenObjects.clear();
    return val;
}
function _traverse(val, seen) {
    var i, keys;
    var isA = isArray(val);
    if ((!isA && !isObject(val)) ||
        val.__v_skip /* ReactiveFlags.SKIP */ ||
        Object.isFrozen(val) ||
        val instanceof VNode) {
        return;
    }
    if (val.__ob__) {
        var depId = val.__ob__.dep.id;
        if (seen.has(depId)) {
            return;
        }
        seen.add(depId);
    }
    if (isA) {
        i = val.length;
        while (i--)
            _traverse(val[i], seen);
    }
    else if (isRef(val)) {
        _traverse(val.value, seen);
    }
    else {
        keys = Object.keys(val);
        i = keys.length;
        while (i--)
            _traverse(val[keys[i]], seen);
    }
}

var uid$1 = 0;
/**
 * A watcher parses an expression, collects dependencies,
 * and fires callback when the expression value changes.
 * This is used for both the $watch() api and directives.
 * @internal
 */
var Watcher = /** @class */ (function () {
    function Watcher(vm, expOrFn, cb, options, isRenderWatcher) {
        recordEffectScope(this, 
        // if the active effect scope is manually created (not a component scope),
        // prioritize it
        activeEffectScope && !activeEffectScope._vm
            ? activeEffectScope
            : vm
                ? vm._scope
                : undefined);
        if ((this.vm = vm) && isRenderWatcher) {
            vm._watcher = this;
        }
        // options
        if (options) {
            this.deep = !!options.deep;
            this.user = !!options.user;
            this.lazy = !!options.lazy;
            this.sync = !!options.sync;
            this.before = options.before;
            if (true) {
                this.onTrack = options.onTrack;
                this.onTrigger = options.onTrigger;
            }
        }
        else {
            this.deep = this.user = this.lazy = this.sync = false;
        }
        this.cb = cb;
        this.id = ++uid$1; // uid for batching
        this.active = true;
        this.post = false;
        this.dirty = this.lazy; // for lazy watchers
        this.deps = [];
        this.newDeps = [];
        this.depIds = new _Set();
        this.newDepIds = new _Set();
        this.expression =  true ? expOrFn.toString() : 0;
        // parse expression for getter
        if (isFunction(expOrFn)) {
            this.getter = expOrFn;
        }
        else {
            this.getter = parsePath(expOrFn);
            if (!this.getter) {
                this.getter = noop;
                 true &&
                    warn("Failed watching path: \"".concat(expOrFn, "\" ") +
                        'Watcher only accepts simple dot-delimited paths. ' +
                        'For full control, use a function instead.', vm);
            }
        }
        this.value = this.lazy ? undefined : this.get();
    }
    /**
     * Evaluate the getter, and re-collect dependencies.
     */
    Watcher.prototype.get = function () {
        pushTarget(this);
        var value;
        var vm = this.vm;
        try {
            value = this.getter.call(vm, vm);
        }
        catch (e) {
            if (this.user) {
                handleError(e, vm, "getter for watcher \"".concat(this.expression, "\""));
            }
            else {
                throw e;
            }
        }
        finally {
            // "touch" every property so they are all tracked as
            // dependencies for deep watching
            if (this.deep) {
                traverse(value);
            }
            popTarget();
            this.cleanupDeps();
        }
        return value;
    };
    /**
     * Add a dependency to this directive.
     */
    Watcher.prototype.addDep = function (dep) {
        var id = dep.id;
        if (!this.newDepIds.has(id)) {
            this.newDepIds.add(id);
            this.newDeps.push(dep);
            if (!this.depIds.has(id)) {
                dep.addSub(this);
            }
        }
    };
    /**
     * Clean up for dependency collection.
     */
    Watcher.prototype.cleanupDeps = function () {
        var i = this.deps.length;
        while (i--) {
            var dep = this.deps[i];
            if (!this.newDepIds.has(dep.id)) {
                dep.removeSub(this);
            }
        }
        var tmp = this.depIds;
        this.depIds = this.newDepIds;
        this.newDepIds = tmp;
        this.newDepIds.clear();
        tmp = this.deps;
        this.deps = this.newDeps;
        this.newDeps = tmp;
        this.newDeps.length = 0;
    };
    /**
     * Subscriber interface.
     * Will be called when a dependency changes.
     */
    Watcher.prototype.update = function () {
        /* istanbul ignore else */
        if (this.lazy) {
            this.dirty = true;
        }
        else if (this.sync) {
            this.run();
        }
        else {
            queueWatcher(this);
        }
    };
    /**
     * Scheduler job interface.
     * Will be called by the scheduler.
     */
    Watcher.prototype.run = function () {
        if (this.active) {
            var value = this.get();
            if (value !== this.value ||
                // Deep watchers and watchers on Object/Arrays should fire even
                // when the value is the same, because the value may
                // have mutated.
                isObject(value) ||
                this.deep) {
                // set new value
                var oldValue = this.value;
                this.value = value;
                if (this.user) {
                    var info = "callback for watcher \"".concat(this.expression, "\"");
                    invokeWithErrorHandling(this.cb, this.vm, [value, oldValue], this.vm, info);
                }
                else {
                    this.cb.call(this.vm, value, oldValue);
                }
            }
        }
    };
    /**
     * Evaluate the value of the watcher.
     * This only gets called for lazy watchers.
     */
    Watcher.prototype.evaluate = function () {
        this.value = this.get();
        this.dirty = false;
    };
    /**
     * Depend on all deps collected by this watcher.
     */
    Watcher.prototype.depend = function () {
        var i = this.deps.length;
        while (i--) {
            this.deps[i].depend();
        }
    };
    /**
     * Remove self from all dependencies' subscriber list.
     */
    Watcher.prototype.teardown = function () {
        if (this.vm && !this.vm._isBeingDestroyed) {
            remove$2(this.vm._scope.effects, this);
        }
        if (this.active) {
            var i = this.deps.length;
            while (i--) {
                this.deps[i].removeSub(this);
            }
            this.active = false;
            if (this.onStop) {
                this.onStop();
            }
        }
    };
    return Watcher;
}());

var mark;
var measure;
if (true) {
    var perf_1 = inBrowser && window.performance;
    /* istanbul ignore if */
    if (perf_1 &&
        // @ts-ignore
        perf_1.mark &&
        // @ts-ignore
        perf_1.measure &&
        // @ts-ignore
        perf_1.clearMarks &&
        // @ts-ignore
        perf_1.clearMeasures) {
        mark = function (tag) { return perf_1.mark(tag); };
        measure = function (name, startTag, endTag) {
            perf_1.measure(name, startTag, endTag);
            perf_1.clearMarks(startTag);
            perf_1.clearMarks(endTag);
            // perf.clearMeasures(name)
        };
    }
}

function initEvents(vm) {
    vm._events = Object.create(null);
    vm._hasHookEvent = false;
    // init parent attached events
    var listeners = vm.$options._parentListeners;
    if (listeners) {
        updateComponentListeners(vm, listeners);
    }
}
var target$1;
function add$1(event, fn) {
    target$1.$on(event, fn);
}
function remove$1(event, fn) {
    target$1.$off(event, fn);
}
function createOnceHandler$1(event, fn) {
    var _target = target$1;
    return function onceHandler() {
        var res = fn.apply(null, arguments);
        if (res !== null) {
            _target.$off(event, onceHandler);
        }
    };
}
function updateComponentListeners(vm, listeners, oldListeners) {
    target$1 = vm;
    updateListeners(listeners, oldListeners || {}, add$1, remove$1, createOnceHandler$1, vm);
    target$1 = undefined;
}
function eventsMixin(Vue) {
    var hookRE = /^hook:/;
    Vue.prototype.$on = function (event, fn) {
        var vm = this;
        if (isArray(event)) {
            for (var i = 0, l = event.length; i < l; i++) {
                vm.$on(event[i], fn);
            }
        }
        else {
            (vm._events[event] || (vm._events[event] = [])).push(fn);
            // optimize hook:event cost by using a boolean flag marked at registration
            // instead of a hash lookup
            if (hookRE.test(event)) {
                vm._hasHookEvent = true;
            }
        }
        return vm;
    };
    Vue.prototype.$once = function (event, fn) {
        var vm = this;
        function on() {
            vm.$off(event, on);
            fn.apply(vm, arguments);
        }
        on.fn = fn;
        vm.$on(event, on);
        return vm;
    };
    Vue.prototype.$off = function (event, fn) {
        var vm = this;
        // all
        if (!arguments.length) {
            vm._events = Object.create(null);
            return vm;
        }
        // array of events
        if (isArray(event)) {
            for (var i_1 = 0, l = event.length; i_1 < l; i_1++) {
                vm.$off(event[i_1], fn);
            }
            return vm;
        }
        // specific event
        var cbs = vm._events[event];
        if (!cbs) {
            return vm;
        }
        if (!fn) {
            vm._events[event] = null;
            return vm;
        }
        // specific handler
        var cb;
        var i = cbs.length;
        while (i--) {
            cb = cbs[i];
            if (cb === fn || cb.fn === fn) {
                cbs.splice(i, 1);
                break;
            }
        }
        return vm;
    };
    Vue.prototype.$emit = function (event) {
        var vm = this;
        if (true) {
            var lowerCaseEvent = event.toLowerCase();
            if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
                tip("Event \"".concat(lowerCaseEvent, "\" is emitted in component ") +
                    "".concat(formatComponentName(vm), " but the handler is registered for \"").concat(event, "\". ") +
                    "Note that HTML attributes are case-insensitive and you cannot use " +
                    "v-on to listen to camelCase events when using in-DOM templates. " +
                    "You should probably use \"".concat(hyphenate(event), "\" instead of \"").concat(event, "\"."));
            }
        }
        var cbs = vm._events[event];
        if (cbs) {
            cbs = cbs.length > 1 ? toArray(cbs) : cbs;
            var args = toArray(arguments, 1);
            var info = "event handler for \"".concat(event, "\"");
            for (var i = 0, l = cbs.length; i < l; i++) {
                invokeWithErrorHandling(cbs[i], vm, args, vm, info);
            }
        }
        return vm;
    };
}

var activeInstance = null;
var isUpdatingChildComponent = false;
function setActiveInstance(vm) {
    var prevActiveInstance = activeInstance;
    activeInstance = vm;
    return function () {
        activeInstance = prevActiveInstance;
    };
}
function initLifecycle(vm) {
    var options = vm.$options;
    // locate first non-abstract parent
    var parent = options.parent;
    if (parent && !options.abstract) {
        while (parent.$options.abstract && parent.$parent) {
            parent = parent.$parent;
        }
        parent.$children.push(vm);
    }
    vm.$parent = parent;
    vm.$root = parent ? parent.$root : vm;
    vm.$children = [];
    vm.$refs = {};
    vm._provided = parent ? parent._provided : Object.create(null);
    vm._watcher = null;
    vm._inactive = null;
    vm._directInactive = false;
    vm._isMounted = false;
    vm._isDestroyed = false;
    vm._isBeingDestroyed = false;
}
function lifecycleMixin(Vue) {
    Vue.prototype._update = function (vnode, hydrating) {
        var vm = this;
        var prevEl = vm.$el;
        var prevVnode = vm._vnode;
        var restoreActiveInstance = setActiveInstance(vm);
        vm._vnode = vnode;
        // Vue.prototype.__patch__ is injected in entry points
        // based on the rendering backend used.
        if (!prevVnode) {
            // initial render
            vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */);
        }
        else {
            // updates
            vm.$el = vm.__patch__(prevVnode, vnode);
        }
        restoreActiveInstance();
        // update __vue__ reference
        if (prevEl) {
            prevEl.__vue__ = null;
        }
        if (vm.$el) {
            vm.$el.__vue__ = vm;
        }
        // if parent is an HOC, update its $el as well
        var wrapper = vm;
        while (wrapper &&
            wrapper.$vnode &&
            wrapper.$parent &&
            wrapper.$vnode === wrapper.$parent._vnode) {
            wrapper.$parent.$el = wrapper.$el;
            wrapper = wrapper.$parent;
        }
        // updated hook is called by the scheduler to ensure that children are
        // updated in a parent's updated hook.
    };
    Vue.prototype.$forceUpdate = function () {
        var vm = this;
        if (vm._watcher) {
            vm._watcher.update();
        }
    };
    Vue.prototype.$destroy = function () {
        var vm = this;
        if (vm._isBeingDestroyed) {
            return;
        }
        callHook$1(vm, 'beforeDestroy');
        vm._isBeingDestroyed = true;
        // remove self from parent
        var parent = vm.$parent;
        if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {
            remove$2(parent.$children, vm);
        }
        // teardown scope. this includes both the render watcher and other
        // watchers created
        vm._scope.stop();
        // remove reference from data ob
        // frozen object may not have observer.
        if (vm._data.__ob__) {
            vm._data.__ob__.vmCount--;
        }
        // call the last hook...
        vm._isDestroyed = true;
        // invoke destroy hooks on current rendered tree
        vm.__patch__(vm._vnode, null);
        // fire destroyed hook
        callHook$1(vm, 'destroyed');
        // turn off all instance listeners.
        vm.$off();
        // remove __vue__ reference
        if (vm.$el) {
            vm.$el.__vue__ = null;
        }
        // release circular reference (#6759)
        if (vm.$vnode) {
            vm.$vnode.parent = null;
        }
    };
}
function mountComponent(vm, el, hydrating) {
    vm.$el = el;
    if (!vm.$options.render) {
        // @ts-expect-error invalid type
        vm.$options.render = createEmptyVNode;
        if (true) {
            /* istanbul ignore if */
            if ((vm.$options.template && vm.$options.template.charAt(0) !== '#') ||
                vm.$options.el ||
                el) {
                warn('You are using the runtime-only build of Vue where the template ' +
                    'compiler is not available. Either pre-compile the templates into ' +
                    'render functions, or use the compiler-included build.', vm);
            }
            else {
                warn('Failed to mount component: template or render function not defined.', vm);
            }
        }
    }
    callHook$1(vm, 'beforeMount');
    var updateComponent;
    /* istanbul ignore if */
    if ( true && config.performance && mark) {
        updateComponent = function () {
            var name = vm._name;
            var id = vm._uid;
            var startTag = "vue-perf-start:".concat(id);
            var endTag = "vue-perf-end:".concat(id);
            mark(startTag);
            var vnode = vm._render();
            mark(endTag);
            measure("vue ".concat(name, " render"), startTag, endTag);
            mark(startTag);
            vm._update(vnode, hydrating);
            mark(endTag);
            measure("vue ".concat(name, " patch"), startTag, endTag);
        };
    }
    else {
        updateComponent = function () {
            vm._update(vm._render(), hydrating);
        };
    }
    var watcherOptions = {
        before: function () {
            if (vm._isMounted && !vm._isDestroyed) {
                callHook$1(vm, 'beforeUpdate');
            }
        }
    };
    if (true) {
        watcherOptions.onTrack = function (e) { return callHook$1(vm, 'renderTracked', [e]); };
        watcherOptions.onTrigger = function (e) { return callHook$1(vm, 'renderTriggered', [e]); };
    }
    // we set this to vm._watcher inside the watcher's constructor
    // since the watcher's initial patch may call $forceUpdate (e.g. inside child
    // component's mounted hook), which relies on vm._watcher being already defined
    new Watcher(vm, updateComponent, noop, watcherOptions, true /* isRenderWatcher */);
    hydrating = false;
    // flush buffer for flush: "pre" watchers queued in setup()
    var preWatchers = vm._preWatchers;
    if (preWatchers) {
        for (var i = 0; i < preWatchers.length; i++) {
            preWatchers[i].run();
        }
    }
    // manually mounted instance, call mounted on self
    // mounted is called for render-created child components in its inserted hook
    if (vm.$vnode == null) {
        vm._isMounted = true;
        callHook$1(vm, 'mounted');
    }
    return vm;
}
function updateChildComponent(vm, propsData, listeners, parentVnode, renderChildren) {
    if (true) {
        isUpdatingChildComponent = true;
    }
    // determine whether component has slot children
    // we need to do this before overwriting $options._renderChildren.
    // check if there are dynamic scopedSlots (hand-written or compiled but with
    // dynamic slot names). Static scoped slots compiled from template has the
    // "$stable" marker.
    var newScopedSlots = parentVnode.data.scopedSlots;
    var oldScopedSlots = vm.$scopedSlots;
    var hasDynamicScopedSlot = !!((newScopedSlots && !newScopedSlots.$stable) ||
        (oldScopedSlots !== emptyObject && !oldScopedSlots.$stable) ||
        (newScopedSlots && vm.$scopedSlots.$key !== newScopedSlots.$key) ||
        (!newScopedSlots && vm.$scopedSlots.$key));
    // Any static slot children from the parent may have changed during parent's
    // update. Dynamic scoped slots may also have changed. In such cases, a forced
    // update is necessary to ensure correctness.
    var needsForceUpdate = !!(renderChildren || // has new static slots
        vm.$options._renderChildren || // has old static slots
        hasDynamicScopedSlot);
    var prevVNode = vm.$vnode;
    vm.$options._parentVnode = parentVnode;
    vm.$vnode = parentVnode; // update vm's placeholder node without re-render
    if (vm._vnode) {
        // update child tree's parent
        vm._vnode.parent = parentVnode;
    }
    vm.$options._renderChildren = renderChildren;
    // update $attrs and $listeners hash
    // these are also reactive so they may trigger child update if the child
    // used them during render
    var attrs = parentVnode.data.attrs || emptyObject;
    if (vm._attrsProxy) {
        // force update if attrs are accessed and has changed since it may be
        // passed to a child component.
        if (syncSetupProxy(vm._attrsProxy, attrs, (prevVNode.data && prevVNode.data.attrs) || emptyObject, vm, '$attrs')) {
            needsForceUpdate = true;
        }
    }
    vm.$attrs = attrs;
    // update listeners
    listeners = listeners || emptyObject;
    var prevListeners = vm.$options._parentListeners;
    if (vm._listenersProxy) {
        syncSetupProxy(vm._listenersProxy, listeners, prevListeners || emptyObject, vm, '$listeners');
    }
    vm.$listeners = vm.$options._parentListeners = listeners;
    updateComponentListeners(vm, listeners, prevListeners);
    // update props
    if (propsData && vm.$options.props) {
        toggleObserving(false);
        var props = vm._props;
        var propKeys = vm.$options._propKeys || [];
        for (var i = 0; i < propKeys.length; i++) {
            var key = propKeys[i];
            var propOptions = vm.$options.props; // wtf flow?
            props[key] = validateProp(key, propOptions, propsData, vm);
        }
        toggleObserving(true);
        // keep a copy of raw propsData
        vm.$options.propsData = propsData;
    }
    // resolve slots + force update if has children
    if (needsForceUpdate) {
        vm.$slots = resolveSlots(renderChildren, parentVnode.context);
        vm.$forceUpdate();
    }
    if (true) {
        isUpdatingChildComponent = false;
    }
}
function isInInactiveTree(vm) {
    while (vm && (vm = vm.$parent)) {
        if (vm._inactive)
            return true;
    }
    return false;
}
function activateChildComponent(vm, direct) {
    if (direct) {
        vm._directInactive = false;
        if (isInInactiveTree(vm)) {
            return;
        }
    }
    else if (vm._directInactive) {
        return;
    }
    if (vm._inactive || vm._inactive === null) {
        vm._inactive = false;
        for (var i = 0; i < vm.$children.length; i++) {
            activateChildComponent(vm.$children[i]);
        }
        callHook$1(vm, 'activated');
    }
}
function deactivateChildComponent(vm, direct) {
    if (direct) {
        vm._directInactive = true;
        if (isInInactiveTree(vm)) {
            return;
        }
    }
    if (!vm._inactive) {
        vm._inactive = true;
        for (var i = 0; i < vm.$children.length; i++) {
            deactivateChildComponent(vm.$children[i]);
        }
        callHook$1(vm, 'deactivated');
    }
}
function callHook$1(vm, hook, args, setContext) {
    if (setContext === void 0) { setContext = true; }
    // #7573 disable dep collection when invoking lifecycle hooks
    pushTarget();
    var prevInst = currentInstance;
    var prevScope = getCurrentScope();
    setContext && setCurrentInstance(vm);
    var handlers = vm.$options[hook];
    var info = "".concat(hook, " hook");
    if (handlers) {
        for (var i = 0, j = handlers.length; i < j; i++) {
            invokeWithErrorHandling(handlers[i], vm, args || null, vm, info);
        }
    }
    if (vm._hasHookEvent) {
        vm.$emit('hook:' + hook);
    }
    if (setContext) {
        setCurrentInstance(prevInst);
        prevScope && prevScope.on();
    }
    popTarget();
}

var MAX_UPDATE_COUNT = 100;
var queue = [];
var activatedChildren = [];
var has = {};
var circular = {};
var waiting = false;
var flushing = false;
var index = 0;
/**
 * Reset the scheduler's state.
 */
function resetSchedulerState() {
    index = queue.length = activatedChildren.length = 0;
    has = {};
    if (true) {
        circular = {};
    }
    waiting = flushing = false;
}
// Async edge case #6566 requires saving the timestamp when event listeners are
// attached. However, calling performance.now() has a perf overhead especially
// if the page has thousands of event listeners. Instead, we take a timestamp
// every time the scheduler flushes and use that for all event listeners
// attached during that flush.
var currentFlushTimestamp = 0;
// Async edge case fix requires storing an event listener's attach timestamp.
var getNow = Date.now;
// Determine what event timestamp the browser is using. Annoyingly, the
// timestamp can either be hi-res (relative to page load) or low-res
// (relative to UNIX epoch), so in order to compare time we have to use the
// same timestamp type when saving the flush timestamp.
// All IE versions use low-res event timestamps, and have problematic clock
// implementations (#9632)
if (inBrowser && !isIE) {
    var performance_1 = window.performance;
    if (performance_1 &&
        typeof performance_1.now === 'function' &&
        getNow() > document.createEvent('Event').timeStamp) {
        // if the event timestamp, although evaluated AFTER the Date.now(), is
        // smaller than it, it means the event is using a hi-res timestamp,
        // and we need to use the hi-res version for event listener timestamps as
        // well.
        getNow = function () { return performance_1.now(); };
    }
}
var sortCompareFn = function (a, b) {
    if (a.post) {
        if (!b.post)
            return 1;
    }
    else if (b.post) {
        return -1;
    }
    return a.id - b.id;
};
/**
 * Flush both queues and run the watchers.
 */
function flushSchedulerQueue() {
    currentFlushTimestamp = getNow();
    flushing = true;
    var watcher, id;
    // Sort queue before flush.
    // This ensures that:
    // 1. Components are updated from parent to child. (because parent is always
    //    created before the child)
    // 2. A component's user watchers are run before its render watcher (because
    //    user watchers are created before the render watcher)
    // 3. If a component is destroyed during a parent component's watcher run,
    //    its watchers can be skipped.
    queue.sort(sortCompareFn);
    // do not cache length because more watchers might be pushed
    // as we run existing watchers
    for (index = 0; index < queue.length; index++) {
        watcher = queue[index];
        if (watcher.before) {
            watcher.before();
        }
        id = watcher.id;
        has[id] = null;
        watcher.run();
        // in dev build, check and stop circular updates.
        if ( true && has[id] != null) {
            circular[id] = (circular[id] || 0) + 1;
            if (circular[id] > MAX_UPDATE_COUNT) {
                warn('You may have an infinite update loop ' +
                    (watcher.user
                        ? "in watcher with expression \"".concat(watcher.expression, "\"")
                        : "in a component render function."), watcher.vm);
                break;
            }
        }
    }
    // keep copies of post queues before resetting state
    var activatedQueue = activatedChildren.slice();
    var updatedQueue = queue.slice();
    resetSchedulerState();
    // call component updated and activated hooks
    callActivatedHooks(activatedQueue);
    callUpdatedHooks(updatedQueue);
    cleanupDeps();
    // devtool hook
    /* istanbul ignore if */
    if (devtools && config.devtools) {
        devtools.emit('flush');
    }
}
function callUpdatedHooks(queue) {
    var i = queue.length;
    while (i--) {
        var watcher = queue[i];
        var vm = watcher.vm;
        if (vm && vm._watcher === watcher && vm._isMounted && !vm._isDestroyed) {
            callHook$1(vm, 'updated');
        }
    }
}
/**
 * Queue a kept-alive component that was activated during patch.
 * The queue will be processed after the entire tree has been patched.
 */
function queueActivatedComponent(vm) {
    // setting _inactive to false here so that a render function can
    // rely on checking whether it's in an inactive tree (e.g. router-view)
    vm._inactive = false;
    activatedChildren.push(vm);
}
function callActivatedHooks(queue) {
    for (var i = 0; i < queue.length; i++) {
        queue[i]._inactive = true;
        activateChildComponent(queue[i], true /* true */);
    }
}
/**
 * Push a watcher into the watcher queue.
 * Jobs with duplicate IDs will be skipped unless it's
 * pushed when the queue is being flushed.
 */
function queueWatcher(watcher) {
    var id = watcher.id;
    if (has[id] != null) {
        return;
    }
    if (watcher === Dep.target && watcher.noRecurse) {
        return;
    }
    has[id] = true;
    if (!flushing) {
        queue.push(watcher);
    }
    else {
        // if already flushing, splice the watcher based on its id
        // if already past its id, it will be run next immediately.
        var i = queue.length - 1;
        while (i > index && queue[i].id > watcher.id) {
            i--;
        }
        queue.splice(i + 1, 0, watcher);
    }
    // queue the flush
    if (!waiting) {
        waiting = true;
        if ( true && !config.async) {
            flushSchedulerQueue();
            return;
        }
        nextTick(flushSchedulerQueue);
    }
}

function initProvide(vm) {
    var provideOption = vm.$options.provide;
    if (provideOption) {
        var provided = isFunction(provideOption)
            ? provideOption.call(vm)
            : provideOption;
        if (!isObject(provided)) {
            return;
        }
        var source = resolveProvided(vm);
        // IE9 doesn't support Object.getOwnPropertyDescriptors so we have to
        // iterate the keys ourselves.
        var keys = hasSymbol ? Reflect.ownKeys(provided) : Object.keys(provided);
        for (var i = 0; i < keys.length; i++) {
            var key = keys[i];
            Object.defineProperty(source, key, Object.getOwnPropertyDescriptor(provided, key));
        }
    }
}
function initInjections(vm) {
    var result = resolveInject(vm.$options.inject, vm);
    if (result) {
        toggleObserving(false);
        Object.keys(result).forEach(function (key) {
            /* istanbul ignore else */
            if (true) {
                defineReactive(vm, key, result[key], function () {
                    warn("Avoid mutating an injected value directly since the changes will be " +
                        "overwritten whenever the provided component re-renders. " +
                        "injection being mutated: \"".concat(key, "\""), vm);
                });
            }
            else {}
        });
        toggleObserving(true);
    }
}
function resolveInject(inject, vm) {
    if (inject) {
        // inject is :any because flow is not smart enough to figure out cached
        var result = Object.create(null);
        var keys = hasSymbol ? Reflect.ownKeys(inject) : Object.keys(inject);
        for (var i = 0; i < keys.length; i++) {
            var key = keys[i];
            // #6574 in case the inject object is observed...
            if (key === '__ob__')
                continue;
            var provideKey = inject[key].from;
            if (provideKey in vm._provided) {
                result[key] = vm._provided[provideKey];
            }
            else if ('default' in inject[key]) {
                var provideDefault = inject[key].default;
                result[key] = isFunction(provideDefault)
                    ? provideDefault.call(vm)
                    : provideDefault;
            }
            else if (true) {
                warn("Injection \"".concat(key, "\" not found"), vm);
            }
        }
        return result;
    }
}

function FunctionalRenderContext(data, props, children, parent, Ctor) {
    var _this = this;
    var options = Ctor.options;
    // ensure the createElement function in functional components
    // gets a unique context - this is necessary for correct named slot check
    var contextVm;
    if (hasOwn(parent, '_uid')) {
        contextVm = Object.create(parent);
        contextVm._original = parent;
    }
    else {
        // the context vm passed in is a functional context as well.
        // in this case we want to make sure we are able to get a hold to the
        // real context instance.
        contextVm = parent;
        // @ts-ignore
        parent = parent._original;
    }
    var isCompiled = isTrue(options._compiled);
    var needNormalization = !isCompiled;
    this.data = data;
    this.props = props;
    this.children = children;
    this.parent = parent;
    this.listeners = data.on || emptyObject;
    this.injections = resolveInject(options.inject, parent);
    this.slots = function () {
        if (!_this.$slots) {
            normalizeScopedSlots(parent, data.scopedSlots, (_this.$slots = resolveSlots(children, parent)));
        }
        return _this.$slots;
    };
    Object.defineProperty(this, 'scopedSlots', {
        enumerable: true,
        get: function () {
            return normalizeScopedSlots(parent, data.scopedSlots, this.slots());
        }
    });
    // support for compiled functional template
    if (isCompiled) {
        // exposing $options for renderStatic()
        this.$options = options;
        // pre-resolve slots for renderSlot()
        this.$slots = this.slots();
        this.$scopedSlots = normalizeScopedSlots(parent, data.scopedSlots, this.$slots);
    }
    if (options._scopeId) {
        this._c = function (a, b, c, d) {
            var vnode = createElement$1(contextVm, a, b, c, d, needNormalization);
            if (vnode && !isArray(vnode)) {
                vnode.fnScopeId = options._scopeId;
                vnode.fnContext = parent;
            }
            return vnode;
        };
    }
    else {
        this._c = function (a, b, c, d) {
            return createElement$1(contextVm, a, b, c, d, needNormalization);
        };
    }
}
installRenderHelpers(FunctionalRenderContext.prototype);
function createFunctionalComponent(Ctor, propsData, data, contextVm, children) {
    var options = Ctor.options;
    var props = {};
    var propOptions = options.props;
    if (isDef(propOptions)) {
        for (var key in propOptions) {
            props[key] = validateProp(key, propOptions, propsData || emptyObject);
        }
    }
    else {
        if (isDef(data.attrs))
            mergeProps(props, data.attrs);
        if (isDef(data.props))
            mergeProps(props, data.props);
    }
    var renderContext = new FunctionalRenderContext(data, props, children, contextVm, Ctor);
    var vnode = options.render.call(null, renderContext._c, renderContext);
    if (vnode instanceof VNode) {
        return cloneAndMarkFunctionalResult(vnode, data, renderContext.parent, options, renderContext);
    }
    else if (isArray(vnode)) {
        var vnodes = normalizeChildren(vnode) || [];
        var res = new Array(vnodes.length);
        for (var i = 0; i < vnodes.length; i++) {
            res[i] = cloneAndMarkFunctionalResult(vnodes[i], data, renderContext.parent, options, renderContext);
        }
        return res;
    }
}
function cloneAndMarkFunctionalResult(vnode, data, contextVm, options, renderContext) {
    // #7817 clone node before setting fnContext, otherwise if the node is reused
    // (e.g. it was from a cached normal slot) the fnContext causes named slots
    // that should not be matched to match.
    var clone = cloneVNode(vnode);
    clone.fnContext = contextVm;
    clone.fnOptions = options;
    if (true) {
        (clone.devtoolsMeta = clone.devtoolsMeta || {}).renderContext =
            renderContext;
    }
    if (data.slot) {
        (clone.data || (clone.data = {})).slot = data.slot;
    }
    return clone;
}
function mergeProps(to, from) {
    for (var key in from) {
        to[camelize(key)] = from[key];
    }
}

function getComponentName(options) {
    return options.name || options.__name || options._componentTag;
}
// inline hooks to be invoked on component VNodes during patch
var componentVNodeHooks = {
    init: function (vnode, hydrating) {
        if (vnode.componentInstance &&
            !vnode.componentInstance._isDestroyed &&
            vnode.data.keepAlive) {
            // kept-alive components, treat as a patch
            var mountedNode = vnode; // work around flow
            componentVNodeHooks.prepatch(mountedNode, mountedNode);
        }
        else {
            var child = (vnode.componentInstance = createComponentInstanceForVnode(vnode, activeInstance));
            child.$mount(hydrating ? vnode.elm : undefined, hydrating);
        }
    },
    prepatch: function (oldVnode, vnode) {
        var options = vnode.componentOptions;
        var child = (vnode.componentInstance = oldVnode.componentInstance);
        updateChildComponent(child, options.propsData, // updated props
        options.listeners, // updated listeners
        vnode, // new parent vnode
        options.children // new children
        );
    },
    insert: function (vnode) {
        var context = vnode.context, componentInstance = vnode.componentInstance;
        if (!componentInstance._isMounted) {
            componentInstance._isMounted = true;
            callHook$1(componentInstance, 'mounted');
        }
        if (vnode.data.keepAlive) {
            if (context._isMounted) {
                // vue-router#1212
                // During updates, a kept-alive component's child components may
                // change, so directly walking the tree here may call activated hooks
                // on incorrect children. Instead we push them into a queue which will
                // be processed after the whole patch process ended.
                queueActivatedComponent(componentInstance);
            }
            else {
                activateChildComponent(componentInstance, true /* direct */);
            }
        }
    },
    destroy: function (vnode) {
        var componentInstance = vnode.componentInstance;
        if (!componentInstance._isDestroyed) {
            if (!vnode.data.keepAlive) {
                componentInstance.$destroy();
            }
            else {
                deactivateChildComponent(componentInstance, true /* direct */);
            }
        }
    }
};
var hooksToMerge = Object.keys(componentVNodeHooks);
function createComponent(Ctor, data, context, children, tag) {
    if (isUndef(Ctor)) {
        return;
    }
    var baseCtor = context.$options._base;
    // plain options object: turn it into a constructor
    if (isObject(Ctor)) {
        Ctor = baseCtor.extend(Ctor);
    }
    // if at this stage it's not a constructor or an async component factory,
    // reject.
    if (typeof Ctor !== 'function') {
        if (true) {
            warn("Invalid Component definition: ".concat(String(Ctor)), context);
        }
        return;
    }
    // async component
    var asyncFactory;
    // @ts-expect-error
    if (isUndef(Ctor.cid)) {
        asyncFactory = Ctor;
        Ctor = resolveAsyncComponent(asyncFactory, baseCtor);
        if (Ctor === undefined) {
            // return a placeholder node for async component, which is rendered
            // as a comment node but preserves all the raw information for the node.
            // the information will be used for async server-rendering and hydration.
            return createAsyncPlaceholder(asyncFactory, data, context, children, tag);
        }
    }
    data = data || {};
    // resolve constructor options in case global mixins are applied after
    // component constructor creation
    resolveConstructorOptions(Ctor);
    // transform component v-model data into props & events
    if (isDef(data.model)) {
        // @ts-expect-error
        transformModel(Ctor.options, data);
    }
    // extract props
    // @ts-expect-error
    var propsData = extractPropsFromVNodeData(data, Ctor, tag);
    // functional component
    // @ts-expect-error
    if (isTrue(Ctor.options.functional)) {
        return createFunctionalComponent(Ctor, propsData, data, context, children);
    }
    // extract listeners, since these needs to be treated as
    // child component listeners instead of DOM listeners
    var listeners = data.on;
    // replace with listeners with .native modifier
    // so it gets processed during parent component patch.
    data.on = data.nativeOn;
    // @ts-expect-error
    if (isTrue(Ctor.options.abstract)) {
        // abstract components do not keep anything
        // other than props & listeners & slot
        // work around flow
        var slot = data.slot;
        data = {};
        if (slot) {
            data.slot = slot;
        }
    }
    // install component management hooks onto the placeholder node
    installComponentHooks(data);
    // return a placeholder vnode
    // @ts-expect-error
    var name = getComponentName(Ctor.options) || tag;
    var vnode = new VNode(
    // @ts-expect-error
    "vue-component-".concat(Ctor.cid).concat(name ? "-".concat(name) : ''), data, undefined, undefined, undefined, context, 
    // @ts-expect-error
    { Ctor: Ctor, propsData: propsData, listeners: listeners, tag: tag, children: children }, asyncFactory);
    return vnode;
}
function createComponentInstanceForVnode(
// we know it's MountedComponentVNode but flow doesn't
vnode, 
// activeInstance in lifecycle state
parent) {
    var options = {
        _isComponent: true,
        _parentVnode: vnode,
        parent: parent
    };
    // check inline-template render functions
    var inlineTemplate = vnode.data.inlineTemplate;
    if (isDef(inlineTemplate)) {
        options.render = inlineTemplate.render;
        options.staticRenderFns = inlineTemplate.staticRenderFns;
    }
    return new vnode.componentOptions.Ctor(options);
}
function installComponentHooks(data) {
    var hooks = data.hook || (data.hook = {});
    for (var i = 0; i < hooksToMerge.length; i++) {
        var key = hooksToMerge[i];
        var existing = hooks[key];
        var toMerge = componentVNodeHooks[key];
        // @ts-expect-error
        if (existing !== toMerge && !(existing && existing._merged)) {
            hooks[key] = existing ? mergeHook(toMerge, existing) : toMerge;
        }
    }
}
function mergeHook(f1, f2) {
    var merged = function (a, b) {
        // flow complains about extra args which is why we use any
        f1(a, b);
        f2(a, b);
    };
    merged._merged = true;
    return merged;
}
// transform component v-model info (value and callback) into
// prop and event handler respectively.
function transformModel(options, data) {
    var prop = (options.model && options.model.prop) || 'value';
    var event = (options.model && options.model.event) || 'input';
    (data.attrs || (data.attrs = {}))[prop] = data.model.value;
    var on = data.on || (data.on = {});
    var existing = on[event];
    var callback = data.model.callback;
    if (isDef(existing)) {
        if (isArray(existing)
            ? existing.indexOf(callback) === -1
            : existing !== callback) {
            on[event] = [callback].concat(existing);
        }
    }
    else {
        on[event] = callback;
    }
}

var warn = noop;
var tip = noop;
var generateComponentTrace; // work around flow check
var formatComponentName;
if (true) {
    var hasConsole_1 = typeof console !== 'undefined';
    var classifyRE_1 = /(?:^|[-_])(\w)/g;
    var classify_1 = function (str) {
        return str.replace(classifyRE_1, function (c) { return c.toUpperCase(); }).replace(/[-_]/g, '');
    };
    warn = function (msg, vm) {
        if (vm === void 0) { vm = currentInstance; }
        var trace = vm ? generateComponentTrace(vm) : '';
        if (config.warnHandler) {
            config.warnHandler.call(null, msg, vm, trace);
        }
        else if (hasConsole_1 && !config.silent) {
            console.error("[Vue warn]: ".concat(msg).concat(trace));
        }
    };
    tip = function (msg, vm) {
        if (hasConsole_1 && !config.silent) {
            console.warn("[Vue tip]: ".concat(msg) + (vm ? generateComponentTrace(vm) : ''));
        }
    };
    formatComponentName = function (vm, includeFile) {
        if (vm.$root === vm) {
            return '<Root>';
        }
        var options = isFunction(vm) && vm.cid != null
            ? vm.options
            : vm._isVue
                ? vm.$options || vm.constructor.options
                : vm;
        var name = getComponentName(options);
        var file = options.__file;
        if (!name && file) {
            var match = file.match(/([^/\\]+)\.vue$/);
            name = match && match[1];
        }
        return ((name ? "<".concat(classify_1(name), ">") : "<Anonymous>") +
            (file && includeFile !== false ? " at ".concat(file) : ''));
    };
    var repeat_1 = function (str, n) {
        var res = '';
        while (n) {
            if (n % 2 === 1)
                res += str;
            if (n > 1)
                str += str;
            n >>= 1;
        }
        return res;
    };
    generateComponentTrace = function (vm) {
        if (vm._isVue && vm.$parent) {
            var tree = [];
            var currentRecursiveSequence = 0;
            while (vm) {
                if (tree.length > 0) {
                    var last = tree[tree.length - 1];
                    if (last.constructor === vm.constructor) {
                        currentRecursiveSequence++;
                        vm = vm.$parent;
                        continue;
                    }
                    else if (currentRecursiveSequence > 0) {
                        tree[tree.length - 1] = [last, currentRecursiveSequence];
                        currentRecursiveSequence = 0;
                    }
                }
                tree.push(vm);
                vm = vm.$parent;
            }
            return ('\n\nfound in\n\n' +
                tree
                    .map(function (vm, i) {
                    return "".concat(i === 0 ? '---> ' : repeat_1(' ', 5 + i * 2)).concat(isArray(vm)
                        ? "".concat(formatComponentName(vm[0]), "... (").concat(vm[1], " recursive calls)")
                        : formatComponentName(vm));
                })
                    .join('\n'));
        }
        else {
            return "\n\n(found in ".concat(formatComponentName(vm), ")");
        }
    };
}

/**
 * Option overwriting strategies are functions that handle
 * how to merge a parent option value and a child option
 * value into the final value.
 */
var strats = config.optionMergeStrategies;
/**
 * Options with restrictions
 */
if (true) {
    strats.el = strats.propsData = function (parent, child, vm, key) {
        if (!vm) {
            warn("option \"".concat(key, "\" can only be used during instance ") +
                'creation with the `new` keyword.');
        }
        return defaultStrat(parent, child);
    };
}
/**
 * Helper that recursively merges two data objects together.
 */
function mergeData(to, from, recursive) {
    if (recursive === void 0) { recursive = true; }
    if (!from)
        return to;
    var key, toVal, fromVal;
    var keys = hasSymbol
        ? Reflect.ownKeys(from)
        : Object.keys(from);
    for (var i = 0; i < keys.length; i++) {
        key = keys[i];
        // in case the object is already observed...
        if (key === '__ob__')
            continue;
        toVal = to[key];
        fromVal = from[key];
        if (!recursive || !hasOwn(to, key)) {
            set(to, key, fromVal);
        }
        else if (toVal !== fromVal &&
            isPlainObject(toVal) &&
            isPlainObject(fromVal)) {
            mergeData(toVal, fromVal);
        }
    }
    return to;
}
/**
 * Data
 */
function mergeDataOrFn(parentVal, childVal, vm) {
    if (!vm) {
        // in a Vue.extend merge, both should be functions
        if (!childVal) {
            return parentVal;
        }
        if (!parentVal) {
            return childVal;
        }
        // when parentVal & childVal are both present,
        // we need to return a function that returns the
        // merged result of both functions... no need to
        // check if parentVal is a function here because
        // it has to be a function to pass previous merges.
        return function mergedDataFn() {
            return mergeData(isFunction(childVal) ? childVal.call(this, this) : childVal, isFunction(parentVal) ? parentVal.call(this, this) : parentVal);
        };
    }
    else {
        return function mergedInstanceDataFn() {
            // instance merge
            var instanceData = isFunction(childVal)
                ? childVal.call(vm, vm)
                : childVal;
            var defaultData = isFunction(parentVal)
                ? parentVal.call(vm, vm)
                : parentVal;
            if (instanceData) {
                return mergeData(instanceData, defaultData);
            }
            else {
                return defaultData;
            }
        };
    }
}
strats.data = function (parentVal, childVal, vm) {
    if (!vm) {
        if (childVal && typeof childVal !== 'function') {
             true &&
                warn('The "data" option should be a function ' +
                    'that returns a per-instance value in component ' +
                    'definitions.', vm);
            return parentVal;
        }
        return mergeDataOrFn(parentVal, childVal);
    }
    return mergeDataOrFn(parentVal, childVal, vm);
};
/**
 * Hooks and props are merged as arrays.
 */
function mergeLifecycleHook(parentVal, childVal) {
    var res = childVal
        ? parentVal
            ? parentVal.concat(childVal)
            : isArray(childVal)
                ? childVal
                : [childVal]
        : parentVal;
    return res ? dedupeHooks(res) : res;
}
function dedupeHooks(hooks) {
    var res = [];
    for (var i = 0; i < hooks.length; i++) {
        if (res.indexOf(hooks[i]) === -1) {
            res.push(hooks[i]);
        }
    }
    return res;
}
LIFECYCLE_HOOKS.forEach(function (hook) {
    strats[hook] = mergeLifecycleHook;
});
/**
 * Assets
 *
 * When a vm is present (instance creation), we need to do
 * a three-way merge between constructor options, instance
 * options and parent options.
 */
function mergeAssets(parentVal, childVal, vm, key) {
    var res = Object.create(parentVal || null);
    if (childVal) {
         true && assertObjectType(key, childVal, vm);
        return extend(res, childVal);
    }
    else {
        return res;
    }
}
ASSET_TYPES.forEach(function (type) {
    strats[type + 's'] = mergeAssets;
});
/**
 * Watchers.
 *
 * Watchers hashes should not overwrite one
 * another, so we merge them as arrays.
 */
strats.watch = function (parentVal, childVal, vm, key) {
    // work around Firefox's Object.prototype.watch...
    //@ts-expect-error work around
    if (parentVal === nativeWatch)
        parentVal = undefined;
    //@ts-expect-error work around
    if (childVal === nativeWatch)
        childVal = undefined;
    /* istanbul ignore if */
    if (!childVal)
        return Object.create(parentVal || null);
    if (true) {
        assertObjectType(key, childVal, vm);
    }
    if (!parentVal)
        return childVal;
    var ret = {};
    extend(ret, parentVal);
    for (var key_1 in childVal) {
        var parent_1 = ret[key_1];
        var child = childVal[key_1];
        if (parent_1 && !isArray(parent_1)) {
            parent_1 = [parent_1];
        }
        ret[key_1] = parent_1 ? parent_1.concat(child) : isArray(child) ? child : [child];
    }
    return ret;
};
/**
 * Other object hashes.
 */
strats.props =
    strats.methods =
        strats.inject =
            strats.computed =
                function (parentVal, childVal, vm, key) {
                    if (childVal && "development" !== 'production') {
                        assertObjectType(key, childVal, vm);
                    }
                    if (!parentVal)
                        return childVal;
                    var ret = Object.create(null);
                    extend(ret, parentVal);
                    if (childVal)
                        extend(ret, childVal);
                    return ret;
                };
strats.provide = function (parentVal, childVal) {
    if (!parentVal)
        return childVal;
    return function () {
        var ret = Object.create(null);
        mergeData(ret, isFunction(parentVal) ? parentVal.call(this) : parentVal);
        if (childVal) {
            mergeData(ret, isFunction(childVal) ? childVal.call(this) : childVal, false // non-recursive
            );
        }
        return ret;
    };
};
/**
 * Default strategy.
 */
var defaultStrat = function (parentVal, childVal) {
    return childVal === undefined ? parentVal : childVal;
};
/**
 * Validate component names
 */
function checkComponents(options) {
    for (var key in options.components) {
        validateComponentName(key);
    }
}
function validateComponentName(name) {
    if (!new RegExp("^[a-zA-Z][\\-\\.0-9_".concat(unicodeRegExp.source, "]*$")).test(name)) {
        warn('Invalid component name: "' +
            name +
            '". Component names ' +
            'should conform to valid custom element name in html5 specification.');
    }
    if (isBuiltInTag(name) || config.isReservedTag(name)) {
        warn('Do not use built-in or reserved HTML elements as component ' +
            'id: ' +
            name);
    }
}
/**
 * Ensure all props option syntax are normalized into the
 * Object-based format.
 */
function normalizeProps(options, vm) {
    var props = options.props;
    if (!props)
        return;
    var res = {};
    var i, val, name;
    if (isArray(props)) {
        i = props.length;
        while (i--) {
            val = props[i];
            if (typeof val === 'string') {
                name = camelize(val);
                res[name] = { type: null };
            }
            else if (true) {
                warn('props must be strings when using array syntax.');
            }
        }
    }
    else if (isPlainObject(props)) {
        for (var key in props) {
            val = props[key];
            name = camelize(key);
            res[name] = isPlainObject(val) ? val : { type: val };
        }
    }
    else if (true) {
        warn("Invalid value for option \"props\": expected an Array or an Object, " +
            "but got ".concat(toRawType(props), "."), vm);
    }
    options.props = res;
}
/**
 * Normalize all injections into Object-based format
 */
function normalizeInject(options, vm) {
    var inject = options.inject;
    if (!inject)
        return;
    var normalized = (options.inject = {});
    if (isArray(inject)) {
        for (var i = 0; i < inject.length; i++) {
            normalized[inject[i]] = { from: inject[i] };
        }
    }
    else if (isPlainObject(inject)) {
        for (var key in inject) {
            var val = inject[key];
            normalized[key] = isPlainObject(val)
                ? extend({ from: key }, val)
                : { from: val };
        }
    }
    else if (true) {
        warn("Invalid value for option \"inject\": expected an Array or an Object, " +
            "but got ".concat(toRawType(inject), "."), vm);
    }
}
/**
 * Normalize raw function directives into object format.
 */
function normalizeDirectives$1(options) {
    var dirs = options.directives;
    if (dirs) {
        for (var key in dirs) {
            var def = dirs[key];
            if (isFunction(def)) {
                dirs[key] = { bind: def, update: def };
            }
        }
    }
}
function assertObjectType(name, value, vm) {
    if (!isPlainObject(value)) {
        warn("Invalid value for option \"".concat(name, "\": expected an Object, ") +
            "but got ".concat(toRawType(value), "."), vm);
    }
}
/**
 * Merge two option objects into a new one.
 * Core utility used in both instantiation and inheritance.
 */
function mergeOptions(parent, child, vm) {
    if (true) {
        checkComponents(child);
    }
    if (isFunction(child)) {
        // @ts-expect-error
        child = child.options;
    }
    normalizeProps(child, vm);
    normalizeInject(child, vm);
    normalizeDirectives$1(child);
    // Apply extends and mixins on the child options,
    // but only if it is a raw options object that isn't
    // the result of another mergeOptions call.
    // Only merged options has the _base property.
    if (!child._base) {
        if (child.extends) {
            parent = mergeOptions(parent, child.extends, vm);
        }
        if (child.mixins) {
            for (var i = 0, l = child.mixins.length; i < l; i++) {
                parent = mergeOptions(parent, child.mixins[i], vm);
            }
        }
    }
    var options = {};
    var key;
    for (key in parent) {
        mergeField(key);
    }
    for (key in child) {
        if (!hasOwn(parent, key)) {
            mergeField(key);
        }
    }
    function mergeField(key) {
        var strat = strats[key] || defaultStrat;
        options[key] = strat(parent[key], child[key], vm, key);
    }
    return options;
}
/**
 * Resolve an asset.
 * This function is used because child instances need access
 * to assets defined in its ancestor chain.
 */
function resolveAsset(options, type, id, warnMissing) {
    /* istanbul ignore if */
    if (typeof id !== 'string') {
        return;
    }
    var assets = options[type];
    // check local registration variations first
    if (hasOwn(assets, id))
        return assets[id];
    var camelizedId = camelize(id);
    if (hasOwn(assets, camelizedId))
        return assets[camelizedId];
    var PascalCaseId = capitalize(camelizedId);
    if (hasOwn(assets, PascalCaseId))
        return assets[PascalCaseId];
    // fallback to prototype chain
    var res = assets[id] || assets[camelizedId] || assets[PascalCaseId];
    if ( true && warnMissing && !res) {
        warn('Failed to resolve ' + type.slice(0, -1) + ': ' + id);
    }
    return res;
}

function validateProp(key, propOptions, propsData, vm) {
    var prop = propOptions[key];
    var absent = !hasOwn(propsData, key);
    var value = propsData[key];
    // boolean casting
    var booleanIndex = getTypeIndex(Boolean, prop.type);
    if (booleanIndex > -1) {
        if (absent && !hasOwn(prop, 'default')) {
            value = false;
        }
        else if (value === '' || value === hyphenate(key)) {
            // only cast empty string / same name to boolean if
            // boolean has higher priority
            var stringIndex = getTypeIndex(String, prop.type);
            if (stringIndex < 0 || booleanIndex < stringIndex) {
                value = true;
            }
        }
    }
    // check default value
    if (value === undefined) {
        value = getPropDefaultValue(vm, prop, key);
        // since the default value is a fresh copy,
        // make sure to observe it.
        var prevShouldObserve = shouldObserve;
        toggleObserving(true);
        observe(value);
        toggleObserving(prevShouldObserve);
    }
    if (true) {
        assertProp(prop, key, value, vm, absent);
    }
    return value;
}
/**
 * Get the default value of a prop.
 */
function getPropDefaultValue(vm, prop, key) {
    // no default, return undefined
    if (!hasOwn(prop, 'default')) {
        return undefined;
    }
    var def = prop.default;
    // warn against non-factory defaults for Object & Array
    if ( true && isObject(def)) {
        warn('Invalid default value for prop "' +
            key +
            '": ' +
            'Props with type Object/Array must use a factory function ' +
            'to return the default value.', vm);
    }
    // the raw prop value was also undefined from previous render,
    // return previous default value to avoid unnecessary watcher trigger
    if (vm &&
        vm.$options.propsData &&
        vm.$options.propsData[key] === undefined &&
        vm._props[key] !== undefined) {
        return vm._props[key];
    }
    // call factory function for non-Function types
    // a value is Function if its prototype is function even across different execution context
    return isFunction(def) && getType(prop.type) !== 'Function'
        ? def.call(vm)
        : def;
}
/**
 * Assert whether a prop is valid.
 */
function assertProp(prop, name, value, vm, absent) {
    if (prop.required && absent) {
        warn('Missing required prop: "' + name + '"', vm);
        return;
    }
    if (value == null && !prop.required) {
        return;
    }
    var type = prop.type;
    var valid = !type || type === true;
    var expectedTypes = [];
    if (type) {
        if (!isArray(type)) {
            type = [type];
        }
        for (var i = 0; i < type.length && !valid; i++) {
            var assertedType = assertType(value, type[i], vm);
            expectedTypes.push(assertedType.expectedType || '');
            valid = assertedType.valid;
        }
    }
    var haveExpectedTypes = expectedTypes.some(function (t) { return t; });
    if (!valid && haveExpectedTypes) {
        warn(getInvalidTypeMessage(name, value, expectedTypes), vm);
        return;
    }
    var validator = prop.validator;
    if (validator) {
        if (!validator(value)) {
            warn('Invalid prop: custom validator check failed for prop "' + name + '".', vm);
        }
    }
}
var simpleCheckRE = /^(String|Number|Boolean|Function|Symbol|BigInt)$/;
function assertType(value, type, vm) {
    var valid;
    var expectedType = getType(type);
    if (simpleCheckRE.test(expectedType)) {
        var t = typeof value;
        valid = t === expectedType.toLowerCase();
        // for primitive wrapper objects
        if (!valid && t === 'object') {
            valid = value instanceof type;
        }
    }
    else if (expectedType === 'Object') {
        valid = isPlainObject(value);
    }
    else if (expectedType === 'Array') {
        valid = isArray(value);
    }
    else {
        try {
            valid = value instanceof type;
        }
        catch (e) {
            warn('Invalid prop type: "' + String(type) + '" is not a constructor', vm);
            valid = false;
        }
    }
    return {
        valid: valid,
        expectedType: expectedType
    };
}
var functionTypeCheckRE = /^\s*function (\w+)/;
/**
 * Use function string name to check built-in types,
 * because a simple equality check will fail when running
 * across different vms / iframes.
 */
function getType(fn) {
    var match = fn && fn.toString().match(functionTypeCheckRE);
    return match ? match[1] : '';
}
function isSameType(a, b) {
    return getType(a) === getType(b);
}
function getTypeIndex(type, expectedTypes) {
    if (!isArray(expectedTypes)) {
        return isSameType(expectedTypes, type) ? 0 : -1;
    }
    for (var i = 0, len = expectedTypes.length; i < len; i++) {
        if (isSameType(expectedTypes[i], type)) {
            return i;
        }
    }
    return -1;
}
function getInvalidTypeMessage(name, value, expectedTypes) {
    var message = "Invalid prop: type check failed for prop \"".concat(name, "\".") +
        " Expected ".concat(expectedTypes.map(capitalize).join(', '));
    var expectedType = expectedTypes[0];
    var receivedType = toRawType(value);
    // check if we need to specify expected value
    if (expectedTypes.length === 1 &&
        isExplicable(expectedType) &&
        isExplicable(typeof value) &&
        !isBoolean(expectedType, receivedType)) {
        message += " with value ".concat(styleValue(value, expectedType));
    }
    message += ", got ".concat(receivedType, " ");
    // check if we need to specify received value
    if (isExplicable(receivedType)) {
        message += "with value ".concat(styleValue(value, receivedType), ".");
    }
    return message;
}
function styleValue(value, type) {
    if (type === 'String') {
        return "\"".concat(value, "\"");
    }
    else if (type === 'Number') {
        return "".concat(Number(value));
    }
    else {
        return "".concat(value);
    }
}
var EXPLICABLE_TYPES = ['string', 'number', 'boolean'];
function isExplicable(value) {
    return EXPLICABLE_TYPES.some(function (elem) { return value.toLowerCase() === elem; });
}
function isBoolean() {
    var args = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        args[_i] = arguments[_i];
    }
    return args.some(function (elem) { return elem.toLowerCase() === 'boolean'; });
}

/* not type checking this file because flow doesn't play well with Proxy */
var initProxy;
if (true) {
    var allowedGlobals_1 = makeMap('Infinity,undefined,NaN,isFinite,isNaN,' +
        'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
        'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,' +
        'require' // for Webpack/Browserify
    );
    var warnNonPresent_1 = function (target, key) {
        warn("Property or method \"".concat(key, "\" is not defined on the instance but ") +
            'referenced during render. Make sure that this property is reactive, ' +
            'either in the data option, or for class-based components, by ' +
            'initializing the property. ' +
            'See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.', target);
    };
    var warnReservedPrefix_1 = function (target, key) {
        warn("Property \"".concat(key, "\" must be accessed with \"$data.").concat(key, "\" because ") +
            'properties starting with "$" or "_" are not proxied in the Vue instance to ' +
            'prevent conflicts with Vue internals. ' +
            'See: https://v2.vuejs.org/v2/api/#data', target);
    };
    var hasProxy_1 = typeof Proxy !== 'undefined' && isNative(Proxy);
    if (hasProxy_1) {
        var isBuiltInModifier_1 = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact');
        config.keyCodes = new Proxy(config.keyCodes, {
            set: function (target, key, value) {
                if (isBuiltInModifier_1(key)) {
                    warn("Avoid overwriting built-in modifier in config.keyCodes: .".concat(key));
                    return false;
                }
                else {
                    target[key] = value;
                    return true;
                }
            }
        });
    }
    var hasHandler_1 = {
        has: function (target, key) {
            var has = key in target;
            var isAllowed = allowedGlobals_1(key) ||
                (typeof key === 'string' &&
                    key.charAt(0) === '_' &&
                    !(key in target.$data));
            if (!has && !isAllowed) {
                if (key in target.$data)
                    warnReservedPrefix_1(target, key);
                else
                    warnNonPresent_1(target, key);
            }
            return has || !isAllowed;
        }
    };
    var getHandler_1 = {
        get: function (target, key) {
            if (typeof key === 'string' && !(key in target)) {
                if (key in target.$data)
                    warnReservedPrefix_1(target, key);
                else
                    warnNonPresent_1(target, key);
            }
            return target[key];
        }
    };
    initProxy = function initProxy(vm) {
        if (hasProxy_1) {
            // determine which proxy handler to use
            var options = vm.$options;
            var handlers = options.render && options.render._withStripped ? getHandler_1 : hasHandler_1;
            vm._renderProxy = new Proxy(vm, handlers);
        }
        else {
            vm._renderProxy = vm;
        }
    };
}

var sharedPropertyDefinition = {
    enumerable: true,
    configurable: true,
    get: noop,
    set: noop
};
function proxy(target, sourceKey, key) {
    sharedPropertyDefinition.get = function proxyGetter() {
        return this[sourceKey][key];
    };
    sharedPropertyDefinition.set = function proxySetter(val) {
        this[sourceKey][key] = val;
    };
    Object.defineProperty(target, key, sharedPropertyDefinition);
}
function initState(vm) {
    var opts = vm.$options;
    if (opts.props)
        initProps$1(vm, opts.props);
    // Composition API
    initSetup(vm);
    if (opts.methods)
        initMethods(vm, opts.methods);
    if (opts.data) {
        initData(vm);
    }
    else {
        var ob = observe((vm._data = {}));
        ob && ob.vmCount++;
    }
    if (opts.computed)
        initComputed$1(vm, opts.computed);
    if (opts.watch && opts.watch !== nativeWatch) {
        initWatch(vm, opts.watch);
    }
}
function initProps$1(vm, propsOptions) {
    var propsData = vm.$options.propsData || {};
    var props = (vm._props = shallowReactive({}));
    // cache prop keys so that future props updates can iterate using Array
    // instead of dynamic object key enumeration.
    var keys = (vm.$options._propKeys = []);
    var isRoot = !vm.$parent;
    // root instance props should be converted
    if (!isRoot) {
        toggleObserving(false);
    }
    var _loop_1 = function (key) {
        keys.push(key);
        var value = validateProp(key, propsOptions, propsData, vm);
        /* istanbul ignore else */
        if (true) {
            var hyphenatedKey = hyphenate(key);
            if (isReservedAttribute(hyphenatedKey) ||
                config.isReservedAttr(hyphenatedKey)) {
                warn("\"".concat(hyphenatedKey, "\" is a reserved attribute and cannot be used as component prop."), vm);
            }
            defineReactive(props, key, value, function () {
                if (!isRoot && !isUpdatingChildComponent) {
                    warn("Avoid mutating a prop directly since the value will be " +
                        "overwritten whenever the parent component re-renders. " +
                        "Instead, use a data or computed property based on the prop's " +
                        "value. Prop being mutated: \"".concat(key, "\""), vm);
                }
            }, true /* shallow */);
        }
        else {}
        // static props are already proxied on the component's prototype
        // during Vue.extend(). We only need to proxy props defined at
        // instantiation here.
        if (!(key in vm)) {
            proxy(vm, "_props", key);
        }
    };
    for (var key in propsOptions) {
        _loop_1(key);
    }
    toggleObserving(true);
}
function initData(vm) {
    var data = vm.$options.data;
    data = vm._data = isFunction(data) ? getData(data, vm) : data || {};
    if (!isPlainObject(data)) {
        data = {};
         true &&
            warn('data functions should return an object:\n' +
                'https://v2.vuejs.org/v2/guide/components.html#data-Must-Be-a-Function', vm);
    }
    // proxy data on instance
    var keys = Object.keys(data);
    var props = vm.$options.props;
    var methods = vm.$options.methods;
    var i = keys.length;
    while (i--) {
        var key = keys[i];
        if (true) {
            if (methods && hasOwn(methods, key)) {
                warn("Method \"".concat(key, "\" has already been defined as a data property."), vm);
            }
        }
        if (props && hasOwn(props, key)) {
             true &&
                warn("The data property \"".concat(key, "\" is already declared as a prop. ") +
                    "Use prop default value instead.", vm);
        }
        else if (!isReserved(key)) {
            proxy(vm, "_data", key);
        }
    }
    // observe data
    var ob = observe(data);
    ob && ob.vmCount++;
}
function getData(data, vm) {
    // #7573 disable dep collection when invoking data getters
    pushTarget();
    try {
        return data.call(vm, vm);
    }
    catch (e) {
        handleError(e, vm, "data()");
        return {};
    }
    finally {
        popTarget();
    }
}
var computedWatcherOptions = { lazy: true };
function initComputed$1(vm, computed) {
    // $flow-disable-line
    var watchers = (vm._computedWatchers = Object.create(null));
    // computed properties are just getters during SSR
    var isSSR = isServerRendering();
    for (var key in computed) {
        var userDef = computed[key];
        var getter = isFunction(userDef) ? userDef : userDef.get;
        if ( true && getter == null) {
            warn("Getter is missing for computed property \"".concat(key, "\"."), vm);
        }
        if (!isSSR) {
            // create internal watcher for the computed property.
            watchers[key] = new Watcher(vm, getter || noop, noop, computedWatcherOptions);
        }
        // component-defined computed properties are already defined on the
        // component prototype. We only need to define computed properties defined
        // at instantiation here.
        if (!(key in vm)) {
            defineComputed(vm, key, userDef);
        }
        else if (true) {
            if (key in vm.$data) {
                warn("The computed property \"".concat(key, "\" is already defined in data."), vm);
            }
            else if (vm.$options.props && key in vm.$options.props) {
                warn("The computed property \"".concat(key, "\" is already defined as a prop."), vm);
            }
            else if (vm.$options.methods && key in vm.$options.methods) {
                warn("The computed property \"".concat(key, "\" is already defined as a method."), vm);
            }
        }
    }
}
function defineComputed(target, key, userDef) {
    var shouldCache = !isServerRendering();
    if (isFunction(userDef)) {
        sharedPropertyDefinition.get = shouldCache
            ? createComputedGetter(key)
            : createGetterInvoker(userDef);
        sharedPropertyDefinition.set = noop;
    }
    else {
        sharedPropertyDefinition.get = userDef.get
            ? shouldCache && userDef.cache !== false
                ? createComputedGetter(key)
                : createGetterInvoker(userDef.get)
            : noop;
        sharedPropertyDefinition.set = userDef.set || noop;
    }
    if ( true && sharedPropertyDefinition.set === noop) {
        sharedPropertyDefinition.set = function () {
            warn("Computed property \"".concat(key, "\" was assigned to but it has no setter."), this);
        };
    }
    Object.defineProperty(target, key, sharedPropertyDefinition);
}
function createComputedGetter(key) {
    return function computedGetter() {
        var watcher = this._computedWatchers && this._computedWatchers[key];
        if (watcher) {
            if (watcher.dirty) {
                watcher.evaluate();
            }
            if (Dep.target) {
                if ( true && Dep.target.onTrack) {
                    Dep.target.onTrack({
                        effect: Dep.target,
                        target: this,
                        type: "get" /* TrackOpTypes.GET */,
                        key: key
                    });
                }
                watcher.depend();
            }
            return watcher.value;
        }
    };
}
function createGetterInvoker(fn) {
    return function computedGetter() {
        return fn.call(this, this);
    };
}
function initMethods(vm, methods) {
    var props = vm.$options.props;
    for (var key in methods) {
        if (true) {
            if (typeof methods[key] !== 'function') {
                warn("Method \"".concat(key, "\" has type \"").concat(typeof methods[key], "\" in the component definition. ") +
                    "Did you reference the function correctly?", vm);
            }
            if (props && hasOwn(props, key)) {
                warn("Method \"".concat(key, "\" has already been defined as a prop."), vm);
            }
            if (key in vm && isReserved(key)) {
                warn("Method \"".concat(key, "\" conflicts with an existing Vue instance method. ") +
                    "Avoid defining component methods that start with _ or $.");
            }
        }
        vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm);
    }
}
function initWatch(vm, watch) {
    for (var key in watch) {
        var handler = watch[key];
        if (isArray(handler)) {
            for (var i = 0; i < handler.length; i++) {
                createWatcher(vm, key, handler[i]);
            }
        }
        else {
            createWatcher(vm, key, handler);
        }
    }
}
function createWatcher(vm, expOrFn, handler, options) {
    if (isPlainObject(handler)) {
        options = handler;
        handler = handler.handler;
    }
    if (typeof handler === 'string') {
        handler = vm[handler];
    }
    return vm.$watch(expOrFn, handler, options);
}
function stateMixin(Vue) {
    // flow somehow has problems with directly declared definition object
    // when using Object.defineProperty, so we have to procedurally build up
    // the object here.
    var dataDef = {};
    dataDef.get = function () {
        return this._data;
    };
    var propsDef = {};
    propsDef.get = function () {
        return this._props;
    };
    if (true) {
        dataDef.set = function () {
            warn('Avoid replacing instance root $data. ' +
                'Use nested data properties instead.', this);
        };
        propsDef.set = function () {
            warn("$props is readonly.", this);
        };
    }
    Object.defineProperty(Vue.prototype, '$data', dataDef);
    Object.defineProperty(Vue.prototype, '$props', propsDef);
    Vue.prototype.$set = set;
    Vue.prototype.$delete = del;
    Vue.prototype.$watch = function (expOrFn, cb, options) {
        var vm = this;
        if (isPlainObject(cb)) {
            return createWatcher(vm, expOrFn, cb, options);
        }
        options = options || {};
        options.user = true;
        var watcher = new Watcher(vm, expOrFn, cb, options);
        if (options.immediate) {
            var info = "callback for immediate watcher \"".concat(watcher.expression, "\"");
            pushTarget();
            invokeWithErrorHandling(cb, vm, [watcher.value], vm, info);
            popTarget();
        }
        return function unwatchFn() {
            watcher.teardown();
        };
    };
}

var uid = 0;
function initMixin$1(Vue) {
    Vue.prototype._init = function (options) {
        var vm = this;
        // a uid
        vm._uid = uid++;
        var startTag, endTag;
        /* istanbul ignore if */
        if ( true && config.performance && mark) {
            startTag = "vue-perf-start:".concat(vm._uid);
            endTag = "vue-perf-end:".concat(vm._uid);
            mark(startTag);
        }
        // a flag to mark this as a Vue instance without having to do instanceof
        // check
        vm._isVue = true;
        // avoid instances from being observed
        vm.__v_skip = true;
        // effect scope
        vm._scope = new EffectScope(true /* detached */);
        // #13134 edge case where a child component is manually created during the
        // render of a parent component
        vm._scope.parent = undefined;
        vm._scope._vm = true;
        // merge options
        if (options && options._isComponent) {
            // optimize internal component instantiation
            // since dynamic options merging is pretty slow, and none of the
            // internal component options needs special treatment.
            initInternalComponent(vm, options);
        }
        else {
            vm.$options = mergeOptions(resolveConstructorOptions(vm.constructor), options || {}, vm);
        }
        /* istanbul ignore else */
        if (true) {
            initProxy(vm);
        }
        else {}
        // expose real self
        vm._self = vm;
        initLifecycle(vm);
        initEvents(vm);
        initRender(vm);
        callHook$1(vm, 'beforeCreate', undefined, false /* setContext */);
        initInjections(vm); // resolve injections before data/props
        initState(vm);
        initProvide(vm); // resolve provide after data/props
        callHook$1(vm, 'created');
        /* istanbul ignore if */
        if ( true && config.performance && mark) {
            vm._name = formatComponentName(vm, false);
            mark(endTag);
            measure("vue ".concat(vm._name, " init"), startTag, endTag);
        }
        if (vm.$options.el) {
            vm.$mount(vm.$options.el);
        }
    };
}
function initInternalComponent(vm, options) {
    var opts = (vm.$options = Object.create(vm.constructor.options));
    // doing this because it's faster than dynamic enumeration.
    var parentVnode = options._parentVnode;
    opts.parent = options.parent;
    opts._parentVnode = parentVnode;
    var vnodeComponentOptions = parentVnode.componentOptions;
    opts.propsData = vnodeComponentOptions.propsData;
    opts._parentListeners = vnodeComponentOptions.listeners;
    opts._renderChildren = vnodeComponentOptions.children;
    opts._componentTag = vnodeComponentOptions.tag;
    if (options.render) {
        opts.render = options.render;
        opts.staticRenderFns = options.staticRenderFns;
    }
}
function resolveConstructorOptions(Ctor) {
    var options = Ctor.options;
    if (Ctor.super) {
        var superOptions = resolveConstructorOptions(Ctor.super);
        var cachedSuperOptions = Ctor.superOptions;
        if (superOptions !== cachedSuperOptions) {
            // super option changed,
            // need to resolve new options.
            Ctor.superOptions = superOptions;
            // check if there are any late-modified/attached options (#4976)
            var modifiedOptions = resolveModifiedOptions(Ctor);
            // update base extend options
            if (modifiedOptions) {
                extend(Ctor.extendOptions, modifiedOptions);
            }
            options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions);
            if (options.name) {
                options.components[options.name] = Ctor;
            }
        }
    }
    return options;
}
function resolveModifiedOptions(Ctor) {
    var modified;
    var latest = Ctor.options;
    var sealed = Ctor.sealedOptions;
    for (var key in latest) {
        if (latest[key] !== sealed[key]) {
            if (!modified)
                modified = {};
            modified[key] = latest[key];
        }
    }
    return modified;
}

function Vue(options) {
    if ( true && !(this instanceof Vue)) {
        warn('Vue is a constructor and should be called with the `new` keyword');
    }
    this._init(options);
}
//@ts-expect-error Vue has function type
initMixin$1(Vue);
//@ts-expect-error Vue has function type
stateMixin(Vue);
//@ts-expect-error Vue has function type
eventsMixin(Vue);
//@ts-expect-error Vue has function type
lifecycleMixin(Vue);
//@ts-expect-error Vue has function type
renderMixin(Vue);

function initUse(Vue) {
    Vue.use = function (plugin) {
        var installedPlugins = this._installedPlugins || (this._installedPlugins = []);
        if (installedPlugins.indexOf(plugin) > -1) {
            return this;
        }
        // additional parameters
        var args = toArray(arguments, 1);
        args.unshift(this);
        if (isFunction(plugin.install)) {
            plugin.install.apply(plugin, args);
        }
        else if (isFunction(plugin)) {
            plugin.apply(null, args);
        }
        installedPlugins.push(plugin);
        return this;
    };
}

function initMixin(Vue) {
    Vue.mixin = function (mixin) {
        this.options = mergeOptions(this.options, mixin);
        return this;
    };
}

function initExtend(Vue) {
    /**
     * Each instance constructor, including Vue, has a unique
     * cid. This enables us to create wrapped "child
     * constructors" for prototypal inheritance and cache them.
     */
    Vue.cid = 0;
    var cid = 1;
    /**
     * Class inheritance
     */
    Vue.extend = function (extendOptions) {
        extendOptions = extendOptions || {};
        var Super = this;
        var SuperId = Super.cid;
        var cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {});
        if (cachedCtors[SuperId]) {
            return cachedCtors[SuperId];
        }
        var name = getComponentName(extendOptions) || getComponentName(Super.options);
        if ( true && name) {
            validateComponentName(name);
        }
        var Sub = function VueComponent(options) {
            this._init(options);
        };
        Sub.prototype = Object.create(Super.prototype);
        Sub.prototype.constructor = Sub;
        Sub.cid = cid++;
        Sub.options = mergeOptions(Super.options, extendOptions);
        Sub['super'] = Super;
        // For props and computed properties, we define the proxy getters on
        // the Vue instances at extension time, on the extended prototype. This
        // avoids Object.defineProperty calls for each instance created.
        if (Sub.options.props) {
            initProps(Sub);
        }
        if (Sub.options.computed) {
            initComputed(Sub);
        }
        // allow further extension/mixin/plugin usage
        Sub.extend = Super.extend;
        Sub.mixin = Super.mixin;
        Sub.use = Super.use;
        // create asset registers, so extended classes
        // can have their private assets too.
        ASSET_TYPES.forEach(function (type) {
            Sub[type] = Super[type];
        });
        // enable recursive self-lookup
        if (name) {
            Sub.options.components[name] = Sub;
        }
        // keep a reference to the super options at extension time.
        // later at instantiation we can check if Super's options have
        // been updated.
        Sub.superOptions = Super.options;
        Sub.extendOptions = extendOptions;
        Sub.sealedOptions = extend({}, Sub.options);
        // cache constructor
        cachedCtors[SuperId] = Sub;
        return Sub;
    };
}
function initProps(Comp) {
    var props = Comp.options.props;
    for (var key in props) {
        proxy(Comp.prototype, "_props", key);
    }
}
function initComputed(Comp) {
    var computed = Comp.options.computed;
    for (var key in computed) {
        defineComputed(Comp.prototype, key, computed[key]);
    }
}

function initAssetRegisters(Vue) {
    /**
     * Create asset registration methods.
     */
    ASSET_TYPES.forEach(function (type) {
        // @ts-expect-error function is not exact same type
        Vue[type] = function (id, definition) {
            if (!definition) {
                return this.options[type + 's'][id];
            }
            else {
                /* istanbul ignore if */
                if ( true && type === 'component') {
                    validateComponentName(id);
                }
                if (type === 'component' && isPlainObject(definition)) {
                    // @ts-expect-error
                    definition.name = definition.name || id;
                    definition = this.options._base.extend(definition);
                }
                if (type === 'directive' && isFunction(definition)) {
                    definition = { bind: definition, update: definition };
                }
                this.options[type + 's'][id] = definition;
                return definition;
            }
        };
    });
}

function _getComponentName(opts) {
    return opts && (getComponentName(opts.Ctor.options) || opts.tag);
}
function matches(pattern, name) {
    if (isArray(pattern)) {
        return pattern.indexOf(name) > -1;
    }
    else if (typeof pattern === 'string') {
        return pattern.split(',').indexOf(name) > -1;
    }
    else if (isRegExp(pattern)) {
        return pattern.test(name);
    }
    /* istanbul ignore next */
    return false;
}
function pruneCache(keepAliveInstance, filter) {
    var cache = keepAliveInstance.cache, keys = keepAliveInstance.keys, _vnode = keepAliveInstance._vnode, $vnode = keepAliveInstance.$vnode;
    for (var key in cache) {
        var entry = cache[key];
        if (entry) {
            var name_1 = entry.name;
            if (name_1 && !filter(name_1)) {
                pruneCacheEntry(cache, key, keys, _vnode);
            }
        }
    }
    $vnode.componentOptions.children = undefined;
}
function pruneCacheEntry(cache, key, keys, current) {
    var entry = cache[key];
    if (entry && (!current || entry.tag !== current.tag)) {
        // @ts-expect-error can be undefined
        entry.componentInstance.$destroy();
    }
    cache[key] = null;
    remove$2(keys, key);
}
var patternTypes = [String, RegExp, Array];
// TODO defineComponent
var KeepAlive = {
    name: 'keep-alive',
    abstract: true,
    props: {
        include: patternTypes,
        exclude: patternTypes,
        max: [String, Number]
    },
    methods: {
        cacheVNode: function () {
            var _a = this, cache = _a.cache, keys = _a.keys, vnodeToCache = _a.vnodeToCache, keyToCache = _a.keyToCache;
            if (vnodeToCache) {
                var tag = vnodeToCache.tag, componentInstance = vnodeToCache.componentInstance, componentOptions = vnodeToCache.componentOptions;
                cache[keyToCache] = {
                    name: _getComponentName(componentOptions),
                    tag: tag,
                    componentInstance: componentInstance
                };
                keys.push(keyToCache);
                // prune oldest entry
                if (this.max && keys.length > parseInt(this.max)) {
                    pruneCacheEntry(cache, keys[0], keys, this._vnode);
                }
                this.vnodeToCache = null;
            }
        }
    },
    created: function () {
        this.cache = Object.create(null);
        this.keys = [];
    },
    destroyed: function () {
        for (var key in this.cache) {
            pruneCacheEntry(this.cache, key, this.keys);
        }
    },
    mounted: function () {
        var _this = this;
        this.cacheVNode();
        this.$watch('include', function (val) {
            pruneCache(_this, function (name) { return matches(val, name); });
        });
        this.$watch('exclude', function (val) {
            pruneCache(_this, function (name) { return !matches(val, name); });
        });
    },
    updated: function () {
        this.cacheVNode();
    },
    render: function () {
        var slot = this.$slots.default;
        var vnode = getFirstComponentChild(slot);
        var componentOptions = vnode && vnode.componentOptions;
        if (componentOptions) {
            // check pattern
            var name_2 = _getComponentName(componentOptions);
            var _a = this, include = _a.include, exclude = _a.exclude;
            if (
            // not included
            (include && (!name_2 || !matches(include, name_2))) ||
                // excluded
                (exclude && name_2 && matches(exclude, name_2))) {
                return vnode;
            }
            var _b = this, cache = _b.cache, keys = _b.keys;
            var key = vnode.key == null
                ? // same constructor may get registered as different local components
                    // so cid alone is not enough (#3269)
                    componentOptions.Ctor.cid +
                        (componentOptions.tag ? "::".concat(componentOptions.tag) : '')
                : vnode.key;
            if (cache[key]) {
                vnode.componentInstance = cache[key].componentInstance;
                // make current key freshest
                remove$2(keys, key);
                keys.push(key);
            }
            else {
                // delay setting the cache until update
                this.vnodeToCache = vnode;
                this.keyToCache = key;
            }
            // @ts-expect-error can vnode.data can be undefined
            vnode.data.keepAlive = true;
        }
        return vnode || (slot && slot[0]);
    }
};

var builtInComponents = {
    KeepAlive: KeepAlive
};

function initGlobalAPI(Vue) {
    // config
    var configDef = {};
    configDef.get = function () { return config; };
    if (true) {
        configDef.set = function () {
            warn('Do not replace the Vue.config object, set individual fields instead.');
        };
    }
    Object.defineProperty(Vue, 'config', configDef);
    // exposed util methods.
    // NOTE: these are not considered part of the public API - avoid relying on
    // them unless you are aware of the risk.
    Vue.util = {
        warn: warn,
        extend: extend,
        mergeOptions: mergeOptions,
        defineReactive: defineReactive
    };
    Vue.set = set;
    Vue.delete = del;
    Vue.nextTick = nextTick;
    // 2.6 explicit observable API
    Vue.observable = function (obj) {
        observe(obj);
        return obj;
    };
    Vue.options = Object.create(null);
    ASSET_TYPES.forEach(function (type) {
        Vue.options[type + 's'] = Object.create(null);
    });
    // this is used to identify the "base" constructor to extend all plain-object
    // components with in Weex's multi-instance scenarios.
    Vue.options._base = Vue;
    extend(Vue.options.components, builtInComponents);
    initUse(Vue);
    initMixin(Vue);
    initExtend(Vue);
    initAssetRegisters(Vue);
}

initGlobalAPI(Vue);
Object.defineProperty(Vue.prototype, '$isServer', {
    get: isServerRendering
});
Object.defineProperty(Vue.prototype, '$ssrContext', {
    get: function () {
        /* istanbul ignore next */
        return this.$vnode && this.$vnode.ssrContext;
    }
});
// expose FunctionalRenderContext for ssr runtime helper installation
Object.defineProperty(Vue, 'FunctionalRenderContext', {
    value: FunctionalRenderContext
});
Vue.version = version;

// these are reserved for web because they are directly compiled away
// during template compilation
var isReservedAttr = makeMap('style,class');
// attributes that should be using props for binding
var acceptValue = makeMap('input,textarea,option,select,progress');
var mustUseProp = function (tag, type, attr) {
    return ((attr === 'value' && acceptValue(tag) && type !== 'button') ||
        (attr === 'selected' && tag === 'option') ||
        (attr === 'checked' && tag === 'input') ||
        (attr === 'muted' && tag === 'video'));
};
var isEnumeratedAttr = makeMap('contenteditable,draggable,spellcheck');
var isValidContentEditableValue = makeMap('events,caret,typing,plaintext-only');
var convertEnumeratedValue = function (key, value) {
    return isFalsyAttrValue(value) || value === 'false'
        ? 'false'
        : // allow arbitrary string value for contenteditable
            key === 'contenteditable' && isValidContentEditableValue(value)
                ? value
                : 'true';
};
var isBooleanAttr = makeMap('allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,' +
    'default,defaultchecked,defaultmuted,defaultselected,defer,disabled,' +
    'enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,' +
    'muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,' +
    'required,reversed,scoped,seamless,selected,sortable,' +
    'truespeed,typemustmatch,visible');
var xlinkNS = 'http://www.w3.org/1999/xlink';
var isXlink = function (name) {
    return name.charAt(5) === ':' && name.slice(0, 5) === 'xlink';
};
var getXlinkProp = function (name) {
    return isXlink(name) ? name.slice(6, name.length) : '';
};
var isFalsyAttrValue = function (val) {
    return val == null || val === false;
};

function genClassForVnode(vnode) {
    var data = vnode.data;
    var parentNode = vnode;
    var childNode = vnode;
    while (isDef(childNode.componentInstance)) {
        childNode = childNode.componentInstance._vnode;
        if (childNode && childNode.data) {
            data = mergeClassData(childNode.data, data);
        }
    }
    // @ts-expect-error parentNode.parent not VNodeWithData
    while (isDef((parentNode = parentNode.parent))) {
        if (parentNode && parentNode.data) {
            data = mergeClassData(data, parentNode.data);
        }
    }
    return renderClass(data.staticClass, data.class);
}
function mergeClassData(child, parent) {
    return {
        staticClass: concat(child.staticClass, parent.staticClass),
        class: isDef(child.class) ? [child.class, parent.class] : parent.class
    };
}
function renderClass(staticClass, dynamicClass) {
    if (isDef(staticClass) || isDef(dynamicClass)) {
        return concat(staticClass, stringifyClass(dynamicClass));
    }
    /* istanbul ignore next */
    return '';
}
function concat(a, b) {
    return a ? (b ? a + ' ' + b : a) : b || '';
}
function stringifyClass(value) {
    if (Array.isArray(value)) {
        return stringifyArray(value);
    }
    if (isObject(value)) {
        return stringifyObject(value);
    }
    if (typeof value === 'string') {
        return value;
    }
    /* istanbul ignore next */
    return '';
}
function stringifyArray(value) {
    var res = '';
    var stringified;
    for (var i = 0, l = value.length; i < l; i++) {
        if (isDef((stringified = stringifyClass(value[i]))) && stringified !== '') {
            if (res)
                res += ' ';
            res += stringified;
        }
    }
    return res;
}
function stringifyObject(value) {
    var res = '';
    for (var key in value) {
        if (value[key]) {
            if (res)
                res += ' ';
            res += key;
        }
    }
    return res;
}

var namespaceMap = {
    svg: 'http://www.w3.org/2000/svg',
    math: 'http://www.w3.org/1998/Math/MathML'
};
var isHTMLTag = makeMap('html,body,base,head,link,meta,style,title,' +
    'address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,' +
    'div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,' +
    'a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,' +
    's,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,' +
    'embed,object,param,source,canvas,script,noscript,del,ins,' +
    'caption,col,colgroup,table,thead,tbody,td,th,tr,' +
    'button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,' +
    'output,progress,select,textarea,' +
    'details,dialog,menu,menuitem,summary,' +
    'content,element,shadow,template,blockquote,iframe,tfoot');
// this map is intentionally selective, only covering SVG elements that may
// contain child elements.
var isSVG = makeMap('svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,' +
    'foreignobject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,' +
    'polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view', true);
var isReservedTag = function (tag) {
    return isHTMLTag(tag) || isSVG(tag);
};
function getTagNamespace(tag) {
    if (isSVG(tag)) {
        return 'svg';
    }
    // basic support for MathML
    // note it doesn't support other MathML elements being component roots
    if (tag === 'math') {
        return 'math';
    }
}
var unknownElementCache = Object.create(null);
function isUnknownElement(tag) {
    /* istanbul ignore if */
    if (!inBrowser) {
        return true;
    }
    if (isReservedTag(tag)) {
        return false;
    }
    tag = tag.toLowerCase();
    /* istanbul ignore if */
    if (unknownElementCache[tag] != null) {
        return unknownElementCache[tag];
    }
    var el = document.createElement(tag);
    if (tag.indexOf('-') > -1) {
        // https://stackoverflow.com/a/28210364/1070244
        return (unknownElementCache[tag] =
            el.constructor === window.HTMLUnknownElement ||
                el.constructor === window.HTMLElement);
    }
    else {
        return (unknownElementCache[tag] = /HTMLUnknownElement/.test(el.toString()));
    }
}
var isTextInputType = makeMap('text,number,password,search,email,tel,url');

/**
 * Query an element selector if it's not an element already.
 */
function query(el) {
    if (typeof el === 'string') {
        var selected = document.querySelector(el);
        if (!selected) {
             true && warn('Cannot find element: ' + el);
            return document.createElement('div');
        }
        return selected;
    }
    else {
        return el;
    }
}

function createElement(tagName, vnode) {
    var elm = document.createElement(tagName);
    if (tagName !== 'select') {
        return elm;
    }
    // false or null will remove the attribute but undefined will not
    if (vnode.data &&
        vnode.data.attrs &&
        vnode.data.attrs.multiple !== undefined) {
        elm.setAttribute('multiple', 'multiple');
    }
    return elm;
}
function createElementNS(namespace, tagName) {
    return document.createElementNS(namespaceMap[namespace], tagName);
}
function createTextNode(text) {
    return document.createTextNode(text);
}
function createComment(text) {
    return document.createComment(text);
}
function insertBefore(parentNode, newNode, referenceNode) {
    parentNode.insertBefore(newNode, referenceNode);
}
function removeChild(node, child) {
    node.removeChild(child);
}
function appendChild(node, child) {
    node.appendChild(child);
}
function parentNode(node) {
    return node.parentNode;
}
function nextSibling(node) {
    return node.nextSibling;
}
function tagName(node) {
    return node.tagName;
}
function setTextContent(node, text) {
    node.textContent = text;
}
function setStyleScope(node, scopeId) {
    node.setAttribute(scopeId, '');
}

var nodeOps = /*#__PURE__*/Object.freeze({
  __proto__: null,
  createElement: createElement,
  createElementNS: createElementNS,
  createTextNode: createTextNode,
  createComment: createComment,
  insertBefore: insertBefore,
  removeChild: removeChild,
  appendChild: appendChild,
  parentNode: parentNode,
  nextSibling: nextSibling,
  tagName: tagName,
  setTextContent: setTextContent,
  setStyleScope: setStyleScope
});

var ref = {
    create: function (_, vnode) {
        registerRef(vnode);
    },
    update: function (oldVnode, vnode) {
        if (oldVnode.data.ref !== vnode.data.ref) {
            registerRef(oldVnode, true);
            registerRef(vnode);
        }
    },
    destroy: function (vnode) {
        registerRef(vnode, true);
    }
};
function registerRef(vnode, isRemoval) {
    var ref = vnode.data.ref;
    if (!isDef(ref))
        return;
    var vm = vnode.context;
    var refValue = vnode.componentInstance || vnode.elm;
    var value = isRemoval ? null : refValue;
    var $refsValue = isRemoval ? undefined : refValue;
    if (isFunction(ref)) {
        invokeWithErrorHandling(ref, vm, [value], vm, "template ref function");
        return;
    }
    var isFor = vnode.data.refInFor;
    var _isString = typeof ref === 'string' || typeof ref === 'number';
    var _isRef = isRef(ref);
    var refs = vm.$refs;
    if (_isString || _isRef) {
        if (isFor) {
            var existing = _isString ? refs[ref] : ref.value;
            if (isRemoval) {
                isArray(existing) && remove$2(existing, refValue);
            }
            else {
                if (!isArray(existing)) {
                    if (_isString) {
                        refs[ref] = [refValue];
                        setSetupRef(vm, ref, refs[ref]);
                    }
                    else {
                        ref.value = [refValue];
                    }
                }
                else if (!existing.includes(refValue)) {
                    existing.push(refValue);
                }
            }
        }
        else if (_isString) {
            if (isRemoval && refs[ref] !== refValue) {
                return;
            }
            refs[ref] = $refsValue;
            setSetupRef(vm, ref, value);
        }
        else if (_isRef) {
            if (isRemoval && ref.value !== refValue) {
                return;
            }
            ref.value = value;
        }
        else if (true) {
            warn("Invalid template ref type: ".concat(typeof ref));
        }
    }
}
function setSetupRef(_a, key, val) {
    var _setupState = _a._setupState;
    if (_setupState && hasOwn(_setupState, key)) {
        if (isRef(_setupState[key])) {
            _setupState[key].value = val;
        }
        else {
            _setupState[key] = val;
        }
    }
}

/**
 * Virtual DOM patching algorithm based on Snabbdom by
 * Simon Friis Vindum (@paldepind)
 * Licensed under the MIT License
 * https://github.com/paldepind/snabbdom/blob/master/LICENSE
 *
 * modified by Evan You (@yyx990803)
 *
 * Not type-checking this because this file is perf-critical and the cost
 * of making flow understand it is not worth it.
 */
var emptyNode = new VNode('', {}, []);
var hooks = ['create', 'activate', 'update', 'remove', 'destroy'];
function sameVnode(a, b) {
    return (a.key === b.key &&
        a.asyncFactory === b.asyncFactory &&
        ((a.tag === b.tag &&
            a.isComment === b.isComment &&
            isDef(a.data) === isDef(b.data) &&
            sameInputType(a, b)) ||
            (isTrue(a.isAsyncPlaceholder) && isUndef(b.asyncFactory.error))));
}
function sameInputType(a, b) {
    if (a.tag !== 'input')
        return true;
    var i;
    var typeA = isDef((i = a.data)) && isDef((i = i.attrs)) && i.type;
    var typeB = isDef((i = b.data)) && isDef((i = i.attrs)) && i.type;
    return typeA === typeB || (isTextInputType(typeA) && isTextInputType(typeB));
}
function createKeyToOldIdx(children, beginIdx, endIdx) {
    var i, key;
    var map = {};
    for (i = beginIdx; i <= endIdx; ++i) {
        key = children[i].key;
        if (isDef(key))
            map[key] = i;
    }
    return map;
}
function createPatchFunction(backend) {
    var i, j;
    var cbs = {};
    var modules = backend.modules, nodeOps = backend.nodeOps;
    for (i = 0; i < hooks.length; ++i) {
        cbs[hooks[i]] = [];
        for (j = 0; j < modules.length; ++j) {
            if (isDef(modules[j][hooks[i]])) {
                cbs[hooks[i]].push(modules[j][hooks[i]]);
            }
        }
    }
    function emptyNodeAt(elm) {
        return new VNode(nodeOps.tagName(elm).toLowerCase(), {}, [], undefined, elm);
    }
    function createRmCb(childElm, listeners) {
        function remove() {
            if (--remove.listeners === 0) {
                removeNode(childElm);
            }
        }
        remove.listeners = listeners;
        return remove;
    }
    function removeNode(el) {
        var parent = nodeOps.parentNode(el);
        // element may have already been removed due to v-html / v-text
        if (isDef(parent)) {
            nodeOps.removeChild(parent, el);
        }
    }
    function isUnknownElement(vnode, inVPre) {
        return (!inVPre &&
            !vnode.ns &&
            !(config.ignoredElements.length &&
                config.ignoredElements.some(function (ignore) {
                    return isRegExp(ignore)
                        ? ignore.test(vnode.tag)
                        : ignore === vnode.tag;
                })) &&
            config.isUnknownElement(vnode.tag));
    }
    var creatingElmInVPre = 0;
    function createElm(vnode, insertedVnodeQueue, parentElm, refElm, nested, ownerArray, index) {
        if (isDef(vnode.elm) && isDef(ownerArray)) {
            // This vnode was used in a previous render!
            // now it's used as a new node, overwriting its elm would cause
            // potential patch errors down the road when it's used as an insertion
            // reference node. Instead, we clone the node on-demand before creating
            // associated DOM element for it.
            vnode = ownerArray[index] = cloneVNode(vnode);
        }
        vnode.isRootInsert = !nested; // for transition enter check
        if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) {
            return;
        }
        var data = vnode.data;
        var children = vnode.children;
        var tag = vnode.tag;
        if (isDef(tag)) {
            if (true) {
                if (data && data.pre) {
                    creatingElmInVPre++;
                }
                if (isUnknownElement(vnode, creatingElmInVPre)) {
                    warn('Unknown custom element: <' +
                        tag +
                        '> - did you ' +
                        'register the component correctly? For recursive components, ' +
                        'make sure to provide the "name" option.', vnode.context);
                }
            }
            vnode.elm = vnode.ns
                ? nodeOps.createElementNS(vnode.ns, tag)
                : nodeOps.createElement(tag, vnode);
            setScope(vnode);
            createChildren(vnode, children, insertedVnodeQueue);
            if (isDef(data)) {
                invokeCreateHooks(vnode, insertedVnodeQueue);
            }
            insert(parentElm, vnode.elm, refElm);
            if ( true && data && data.pre) {
                creatingElmInVPre--;
            }
        }
        else if (isTrue(vnode.isComment)) {
            vnode.elm = nodeOps.createComment(vnode.text);
            insert(parentElm, vnode.elm, refElm);
        }
        else {
            vnode.elm = nodeOps.createTextNode(vnode.text);
            insert(parentElm, vnode.elm, refElm);
        }
    }
    function createComponent(vnode, insertedVnodeQueue, parentElm, refElm) {
        var i = vnode.data;
        if (isDef(i)) {
            var isReactivated = isDef(vnode.componentInstance) && i.keepAlive;
            if (isDef((i = i.hook)) && isDef((i = i.init))) {
                i(vnode, false /* hydrating */);
            }
            // after calling the init hook, if the vnode is a child component
            // it should've created a child instance and mounted it. the child
            // component also has set the placeholder vnode's elm.
            // in that case we can just return the element and be done.
            if (isDef(vnode.componentInstance)) {
                initComponent(vnode, insertedVnodeQueue);
                insert(parentElm, vnode.elm, refElm);
                if (isTrue(isReactivated)) {
                    reactivateComponent(vnode, insertedVnodeQueue, parentElm, refElm);
                }
                return true;
            }
        }
    }
    function initComponent(vnode, insertedVnodeQueue) {
        if (isDef(vnode.data.pendingInsert)) {
            insertedVnodeQueue.push.apply(insertedVnodeQueue, vnode.data.pendingInsert);
            vnode.data.pendingInsert = null;
        }
        vnode.elm = vnode.componentInstance.$el;
        if (isPatchable(vnode)) {
            invokeCreateHooks(vnode, insertedVnodeQueue);
            setScope(vnode);
        }
        else {
            // empty component root.
            // skip all element-related modules except for ref (#3455)
            registerRef(vnode);
            // make sure to invoke the insert hook
            insertedVnodeQueue.push(vnode);
        }
    }
    function reactivateComponent(vnode, insertedVnodeQueue, parentElm, refElm) {
        var i;
        // hack for #4339: a reactivated component with inner transition
        // does not trigger because the inner node's created hooks are not called
        // again. It's not ideal to involve module-specific logic in here but
        // there doesn't seem to be a better way to do it.
        var innerNode = vnode;
        while (innerNode.componentInstance) {
            innerNode = innerNode.componentInstance._vnode;
            if (isDef((i = innerNode.data)) && isDef((i = i.transition))) {
                for (i = 0; i < cbs.activate.length; ++i) {
                    cbs.activate[i](emptyNode, innerNode);
                }
                insertedVnodeQueue.push(innerNode);
                break;
            }
        }
        // unlike a newly created component,
        // a reactivated keep-alive component doesn't insert itself
        insert(parentElm, vnode.elm, refElm);
    }
    function insert(parent, elm, ref) {
        if (isDef(parent)) {
            if (isDef(ref)) {
                if (nodeOps.parentNode(ref) === parent) {
                    nodeOps.insertBefore(parent, elm, ref);
                }
            }
            else {
                nodeOps.appendChild(parent, elm);
            }
        }
    }
    function createChildren(vnode, children, insertedVnodeQueue) {
        if (isArray(children)) {
            if (true) {
                checkDuplicateKeys(children);
            }
            for (var i_1 = 0; i_1 < children.length; ++i_1) {
                createElm(children[i_1], insertedVnodeQueue, vnode.elm, null, true, children, i_1);
            }
        }
        else if (isPrimitive(vnode.text)) {
            nodeOps.appendChild(vnode.elm, nodeOps.createTextNode(String(vnode.text)));
        }
    }
    function isPatchable(vnode) {
        while (vnode.componentInstance) {
            vnode = vnode.componentInstance._vnode;
        }
        return isDef(vnode.tag);
    }
    function invokeCreateHooks(vnode, insertedVnodeQueue) {
        for (var i_2 = 0; i_2 < cbs.create.length; ++i_2) {
            cbs.create[i_2](emptyNode, vnode);
        }
        i = vnode.data.hook; // Reuse variable
        if (isDef(i)) {
            if (isDef(i.create))
                i.create(emptyNode, vnode);
            if (isDef(i.insert))
                insertedVnodeQueue.push(vnode);
        }
    }
    // set scope id attribute for scoped CSS.
    // this is implemented as a special case to avoid the overhead
    // of going through the normal attribute patching process.
    function setScope(vnode) {
        var i;
        if (isDef((i = vnode.fnScopeId))) {
            nodeOps.setStyleScope(vnode.elm, i);
        }
        else {
            var ancestor = vnode;
            while (ancestor) {
                if (isDef((i = ancestor.context)) && isDef((i = i.$options._scopeId))) {
                    nodeOps.setStyleScope(vnode.elm, i);
                }
                ancestor = ancestor.parent;
            }
        }
        // for slot content they should also get the scopeId from the host instance.
        if (isDef((i = activeInstance)) &&
            i !== vnode.context &&
            i !== vnode.fnContext &&
            isDef((i = i.$options._scopeId))) {
            nodeOps.setStyleScope(vnode.elm, i);
        }
    }
    function addVnodes(parentElm, refElm, vnodes, startIdx, endIdx, insertedVnodeQueue) {
        for (; startIdx <= endIdx; ++startIdx) {
            createElm(vnodes[startIdx], insertedVnodeQueue, parentElm, refElm, false, vnodes, startIdx);
        }
    }
    function invokeDestroyHook(vnode) {
        var i, j;
        var data = vnode.data;
        if (isDef(data)) {
            if (isDef((i = data.hook)) && isDef((i = i.destroy)))
                i(vnode);
            for (i = 0; i < cbs.destroy.length; ++i)
                cbs.destroy[i](vnode);
        }
        if (isDef((i = vnode.children))) {
            for (j = 0; j < vnode.children.length; ++j) {
                invokeDestroyHook(vnode.children[j]);
            }
        }
    }
    function removeVnodes(vnodes, startIdx, endIdx) {
        for (; startIdx <= endIdx; ++startIdx) {
            var ch = vnodes[startIdx];
            if (isDef(ch)) {
                if (isDef(ch.tag)) {
                    removeAndInvokeRemoveHook(ch);
                    invokeDestroyHook(ch);
                }
                else {
                    // Text node
                    removeNode(ch.elm);
                }
            }
        }
    }
    function removeAndInvokeRemoveHook(vnode, rm) {
        if (isDef(rm) || isDef(vnode.data)) {
            var i_3;
            var listeners = cbs.remove.length + 1;
            if (isDef(rm)) {
                // we have a recursively passed down rm callback
                // increase the listeners count
                rm.listeners += listeners;
            }
            else {
                // directly removing
                rm = createRmCb(vnode.elm, listeners);
            }
            // recursively invoke hooks on child component root node
            if (isDef((i_3 = vnode.componentInstance)) &&
                isDef((i_3 = i_3._vnode)) &&
                isDef(i_3.data)) {
                removeAndInvokeRemoveHook(i_3, rm);
            }
            for (i_3 = 0; i_3 < cbs.remove.length; ++i_3) {
                cbs.remove[i_3](vnode, rm);
            }
            if (isDef((i_3 = vnode.data.hook)) && isDef((i_3 = i_3.remove))) {
                i_3(vnode, rm);
            }
            else {
                rm();
            }
        }
        else {
            removeNode(vnode.elm);
        }
    }
    function updateChildren(parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {
        var oldStartIdx = 0;
        var newStartIdx = 0;
        var oldEndIdx = oldCh.length - 1;
        var oldStartVnode = oldCh[0];
        var oldEndVnode = oldCh[oldEndIdx];
        var newEndIdx = newCh.length - 1;
        var newStartVnode = newCh[0];
        var newEndVnode = newCh[newEndIdx];
        var oldKeyToIdx, idxInOld, vnodeToMove, refElm;
        // removeOnly is a special flag used only by <transition-group>
        // to ensure removed elements stay in correct relative positions
        // during leaving transitions
        var canMove = !removeOnly;
        if (true) {
            checkDuplicateKeys(newCh);
        }
        while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
            if (isUndef(oldStartVnode)) {
                oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left
            }
            else if (isUndef(oldEndVnode)) {
                oldEndVnode = oldCh[--oldEndIdx];
            }
            else if (sameVnode(oldStartVnode, newStartVnode)) {
                patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue, newCh, newStartIdx);
                oldStartVnode = oldCh[++oldStartIdx];
                newStartVnode = newCh[++newStartIdx];
            }
            else if (sameVnode(oldEndVnode, newEndVnode)) {
                patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue, newCh, newEndIdx);
                oldEndVnode = oldCh[--oldEndIdx];
                newEndVnode = newCh[--newEndIdx];
            }
            else if (sameVnode(oldStartVnode, newEndVnode)) {
                // Vnode moved right
                patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue, newCh, newEndIdx);
                canMove &&
                    nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm));
                oldStartVnode = oldCh[++oldStartIdx];
                newEndVnode = newCh[--newEndIdx];
            }
            else if (sameVnode(oldEndVnode, newStartVnode)) {
                // Vnode moved left
                patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue, newCh, newStartIdx);
                canMove &&
                    nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm);
                oldEndVnode = oldCh[--oldEndIdx];
                newStartVnode = newCh[++newStartIdx];
            }
            else {
                if (isUndef(oldKeyToIdx))
                    oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);
                idxInOld = isDef(newStartVnode.key)
                    ? oldKeyToIdx[newStartVnode.key]
                    : findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx);
                if (isUndef(idxInOld)) {
                    // New element
                    createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx);
                }
                else {
                    vnodeToMove = oldCh[idxInOld];
                    if (sameVnode(vnodeToMove, newStartVnode)) {
                        patchVnode(vnodeToMove, newStartVnode, insertedVnodeQueue, newCh, newStartIdx);
                        oldCh[idxInOld] = undefined;
                        canMove &&
                            nodeOps.insertBefore(parentElm, vnodeToMove.elm, oldStartVnode.elm);
                    }
                    else {
                        // same key but different element. treat as new element
                        createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx);
                    }
                }
                newStartVnode = newCh[++newStartIdx];
            }
        }
        if (oldStartIdx > oldEndIdx) {
            refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm;
            addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);
        }
        else if (newStartIdx > newEndIdx) {
            removeVnodes(oldCh, oldStartIdx, oldEndIdx);
        }
    }
    function checkDuplicateKeys(children) {
        var seenKeys = {};
        for (var i_4 = 0; i_4 < children.length; i_4++) {
            var vnode = children[i_4];
            var key = vnode.key;
            if (isDef(key)) {
                if (seenKeys[key]) {
                    warn("Duplicate keys detected: '".concat(key, "'. This may cause an update error."), vnode.context);
                }
                else {
                    seenKeys[key] = true;
                }
            }
        }
    }
    function findIdxInOld(node, oldCh, start, end) {
        for (var i_5 = start; i_5 < end; i_5++) {
            var c = oldCh[i_5];
            if (isDef(c) && sameVnode(node, c))
                return i_5;
        }
    }
    function patchVnode(oldVnode, vnode, insertedVnodeQueue, ownerArray, index, removeOnly) {
        if (oldVnode === vnode) {
            return;
        }
        if (isDef(vnode.elm) && isDef(ownerArray)) {
            // clone reused vnode
            vnode = ownerArray[index] = cloneVNode(vnode);
        }
        var elm = (vnode.elm = oldVnode.elm);
        if (isTrue(oldVnode.isAsyncPlaceholder)) {
            if (isDef(vnode.asyncFactory.resolved)) {
                hydrate(oldVnode.elm, vnode, insertedVnodeQueue);
            }
            else {
                vnode.isAsyncPlaceholder = true;
            }
            return;
        }
        // reuse element for static trees.
        // note we only do this if the vnode is cloned -
        // if the new node is not cloned it means the render functions have been
        // reset by the hot-reload-api and we need to do a proper re-render.
        if (isTrue(vnode.isStatic) &&
            isTrue(oldVnode.isStatic) &&
            vnode.key === oldVnode.key &&
            (isTrue(vnode.isCloned) || isTrue(vnode.isOnce))) {
            vnode.componentInstance = oldVnode.componentInstance;
            return;
        }
        var i;
        var data = vnode.data;
        if (isDef(data) && isDef((i = data.hook)) && isDef((i = i.prepatch))) {
            i(oldVnode, vnode);
        }
        var oldCh = oldVnode.children;
        var ch = vnode.children;
        if (isDef(data) && isPatchable(vnode)) {
            for (i = 0; i < cbs.update.length; ++i)
                cbs.update[i](oldVnode, vnode);
            if (isDef((i = data.hook)) && isDef((i = i.update)))
                i(oldVnode, vnode);
        }
        if (isUndef(vnode.text)) {
            if (isDef(oldCh) && isDef(ch)) {
                if (oldCh !== ch)
                    updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly);
            }
            else if (isDef(ch)) {
                if (true) {
                    checkDuplicateKeys(ch);
                }
                if (isDef(oldVnode.text))
                    nodeOps.setTextContent(elm, '');
                addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);
            }
            else if (isDef(oldCh)) {
                removeVnodes(oldCh, 0, oldCh.length - 1);
            }
            else if (isDef(oldVnode.text)) {
                nodeOps.setTextContent(elm, '');
            }
        }
        else if (oldVnode.text !== vnode.text) {
            nodeOps.setTextContent(elm, vnode.text);
        }
        if (isDef(data)) {
            if (isDef((i = data.hook)) && isDef((i = i.postpatch)))
                i(oldVnode, vnode);
        }
    }
    function invokeInsertHook(vnode, queue, initial) {
        // delay insert hooks for component root nodes, invoke them after the
        // element is really inserted
        if (isTrue(initial) && isDef(vnode.parent)) {
            vnode.parent.data.pendingInsert = queue;
        }
        else {
            for (var i_6 = 0; i_6 < queue.length; ++i_6) {
                queue[i_6].data.hook.insert(queue[i_6]);
            }
        }
    }
    var hydrationBailed = false;
    // list of modules that can skip create hook during hydration because they
    // are already rendered on the client or has no need for initialization
    // Note: style is excluded because it relies on initial clone for future
    // deep updates (#7063).
    var isRenderedModule = makeMap('attrs,class,staticClass,staticStyle,key');
    // Note: this is a browser-only function so we can assume elms are DOM nodes.
    function hydrate(elm, vnode, insertedVnodeQueue, inVPre) {
        var i;
        var tag = vnode.tag, data = vnode.data, children = vnode.children;
        inVPre = inVPre || (data && data.pre);
        vnode.elm = elm;
        if (isTrue(vnode.isComment) && isDef(vnode.asyncFactory)) {
            vnode.isAsyncPlaceholder = true;
            return true;
        }
        // assert node match
        if (true) {
            if (!assertNodeMatch(elm, vnode, inVPre)) {
                return false;
            }
        }
        if (isDef(data)) {
            if (isDef((i = data.hook)) && isDef((i = i.init)))
                i(vnode, true /* hydrating */);
            if (isDef((i = vnode.componentInstance))) {
                // child component. it should have hydrated its own tree.
                initComponent(vnode, insertedVnodeQueue);
                return true;
            }
        }
        if (isDef(tag)) {
            if (isDef(children)) {
                // empty element, allow client to pick up and populate children
                if (!elm.hasChildNodes()) {
                    createChildren(vnode, children, insertedVnodeQueue);
                }
                else {
                    // v-html and domProps: innerHTML
                    if (isDef((i = data)) &&
                        isDef((i = i.domProps)) &&
                        isDef((i = i.innerHTML))) {
                        if (i !== elm.innerHTML) {
                            /* istanbul ignore if */
                            if ( true &&
                                typeof console !== 'undefined' &&
                                !hydrationBailed) {
                                hydrationBailed = true;
                                console.warn('Parent: ', elm);
                                console.warn('server innerHTML: ', i);
                                console.warn('client innerHTML: ', elm.innerHTML);
                            }
                            return false;
                        }
                    }
                    else {
                        // iterate and compare children lists
                        var childrenMatch = true;
                        var childNode = elm.firstChild;
                        for (var i_7 = 0; i_7 < children.length; i_7++) {
                            if (!childNode ||
                                !hydrate(childNode, children[i_7], insertedVnodeQueue, inVPre)) {
                                childrenMatch = false;
                                break;
                            }
                            childNode = childNode.nextSibling;
                        }
                        // if childNode is not null, it means the actual childNodes list is
                        // longer than the virtual children list.
                        if (!childrenMatch || childNode) {
                            /* istanbul ignore if */
                            if ( true &&
                                typeof console !== 'undefined' &&
                                !hydrationBailed) {
                                hydrationBailed = true;
                                console.warn('Parent: ', elm);
                                console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children);
                            }
                            return false;
                        }
                    }
                }
            }
            if (isDef(data)) {
                var fullInvoke = false;
                for (var key in data) {
                    if (!isRenderedModule(key)) {
                        fullInvoke = true;
                        invokeCreateHooks(vnode, insertedVnodeQueue);
                        break;
                    }
                }
                if (!fullInvoke && data['class']) {
                    // ensure collecting deps for deep class bindings for future updates
                    traverse(data['class']);
                }
            }
        }
        else if (elm.data !== vnode.text) {
            elm.data = vnode.text;
        }
        return true;
    }
    function assertNodeMatch(node, vnode, inVPre) {
        if (isDef(vnode.tag)) {
            return (vnode.tag.indexOf('vue-component') === 0 ||
                (!isUnknownElement(vnode, inVPre) &&
                    vnode.tag.toLowerCase() ===
                        (node.tagName && node.tagName.toLowerCase())));
        }
        else {
            return node.nodeType === (vnode.isComment ? 8 : 3);
        }
    }
    return function patch(oldVnode, vnode, hydrating, removeOnly) {
        if (isUndef(vnode)) {
            if (isDef(oldVnode))
                invokeDestroyHook(oldVnode);
            return;
        }
        var isInitialPatch = false;
        var insertedVnodeQueue = [];
        if (isUndef(oldVnode)) {
            // empty mount (likely as component), create new root element
            isInitialPatch = true;
            createElm(vnode, insertedVnodeQueue);
        }
        else {
            var isRealElement = isDef(oldVnode.nodeType);
            if (!isRealElement && sameVnode(oldVnode, vnode)) {
                // patch existing root node
                patchVnode(oldVnode, vnode, insertedVnodeQueue, null, null, removeOnly);
            }
            else {
                if (isRealElement) {
                    // mounting to a real element
                    // check if this is server-rendered content and if we can perform
                    // a successful hydration.
                    if (oldVnode.nodeType === 1 && oldVnode.hasAttribute(SSR_ATTR)) {
                        oldVnode.removeAttribute(SSR_ATTR);
                        hydrating = true;
                    }
                    if (isTrue(hydrating)) {
                        if (hydrate(oldVnode, vnode, insertedVnodeQueue)) {
                            invokeInsertHook(vnode, insertedVnodeQueue, true);
                            return oldVnode;
                        }
                        else if (true) {
                            warn('The client-side rendered virtual DOM tree is not matching ' +
                                'server-rendered content. This is likely caused by incorrect ' +
                                'HTML markup, for example nesting block-level elements inside ' +
                                '<p>, or missing <tbody>. Bailing hydration and performing ' +
                                'full client-side render.');
                        }
                    }
                    // either not server-rendered, or hydration failed.
                    // create an empty node and replace it
                    oldVnode = emptyNodeAt(oldVnode);
                }
                // replacing existing element
                var oldElm = oldVnode.elm;
                var parentElm = nodeOps.parentNode(oldElm);
                // create new node
                createElm(vnode, insertedVnodeQueue, 
                // extremely rare edge case: do not insert if old element is in a
                // leaving transition. Only happens when combining transition +
                // keep-alive + HOCs. (#4590)
                oldElm._leaveCb ? null : parentElm, nodeOps.nextSibling(oldElm));
                // update parent placeholder node element, recursively
                if (isDef(vnode.parent)) {
                    var ancestor = vnode.parent;
                    var patchable = isPatchable(vnode);
                    while (ancestor) {
                        for (var i_8 = 0; i_8 < cbs.destroy.length; ++i_8) {
                            cbs.destroy[i_8](ancestor);
                        }
                        ancestor.elm = vnode.elm;
                        if (patchable) {
                            for (var i_9 = 0; i_9 < cbs.create.length; ++i_9) {
                                cbs.create[i_9](emptyNode, ancestor);
                            }
                            // #6513
                            // invoke insert hooks that may have been merged by create hooks.
                            // e.g. for directives that uses the "inserted" hook.
                            var insert_1 = ancestor.data.hook.insert;
                            if (insert_1.merged) {
                                // start at index 1 to avoid re-invoking component mounted hook
                                // clone insert hooks to avoid being mutated during iteration.
                                // e.g. for customed directives under transition group.
                                var cloned = insert_1.fns.slice(1);
                                for (var i_10 = 0; i_10 < cloned.length; i_10++) {
                                    cloned[i_10]();
                                }
                            }
                        }
                        else {
                            registerRef(ancestor);
                        }
                        ancestor = ancestor.parent;
                    }
                }
                // destroy old node
                if (isDef(parentElm)) {
                    removeVnodes([oldVnode], 0, 0);
                }
                else if (isDef(oldVnode.tag)) {
                    invokeDestroyHook(oldVnode);
                }
            }
        }
        invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch);
        return vnode.elm;
    };
}

var directives = {
    create: updateDirectives,
    update: updateDirectives,
    destroy: function unbindDirectives(vnode) {
        // @ts-expect-error emptyNode is not VNodeWithData
        updateDirectives(vnode, emptyNode);
    }
};
function updateDirectives(oldVnode, vnode) {
    if (oldVnode.data.directives || vnode.data.directives) {
        _update(oldVnode, vnode);
    }
}
function _update(oldVnode, vnode) {
    var isCreate = oldVnode === emptyNode;
    var isDestroy = vnode === emptyNode;
    var oldDirs = normalizeDirectives(oldVnode.data.directives, oldVnode.context);
    var newDirs = normalizeDirectives(vnode.data.directives, vnode.context);
    var dirsWithInsert = [];
    var dirsWithPostpatch = [];
    var key, oldDir, dir;
    for (key in newDirs) {
        oldDir = oldDirs[key];
        dir = newDirs[key];
        if (!oldDir) {
            // new directive, bind
            callHook(dir, 'bind', vnode, oldVnode);
            if (dir.def && dir.def.inserted) {
                dirsWithInsert.push(dir);
            }
        }
        else {
            // existing directive, update
            dir.oldValue = oldDir.value;
            dir.oldArg = oldDir.arg;
            callHook(dir, 'update', vnode, oldVnode);
            if (dir.def && dir.def.componentUpdated) {
                dirsWithPostpatch.push(dir);
            }
        }
    }
    if (dirsWithInsert.length) {
        var callInsert = function () {
            for (var i = 0; i < dirsWithInsert.length; i++) {
                callHook(dirsWithInsert[i], 'inserted', vnode, oldVnode);
            }
        };
        if (isCreate) {
            mergeVNodeHook(vnode, 'insert', callInsert);
        }
        else {
            callInsert();
        }
    }
    if (dirsWithPostpatch.length) {
        mergeVNodeHook(vnode, 'postpatch', function () {
            for (var i = 0; i < dirsWithPostpatch.length; i++) {
                callHook(dirsWithPostpatch[i], 'componentUpdated', vnode, oldVnode);
            }
        });
    }
    if (!isCreate) {
        for (key in oldDirs) {
            if (!newDirs[key]) {
                // no longer present, unbind
                callHook(oldDirs[key], 'unbind', oldVnode, oldVnode, isDestroy);
            }
        }
    }
}
var emptyModifiers = Object.create(null);
function normalizeDirectives(dirs, vm) {
    var res = Object.create(null);
    if (!dirs) {
        // $flow-disable-line
        return res;
    }
    var i, dir;
    for (i = 0; i < dirs.length; i++) {
        dir = dirs[i];
        if (!dir.modifiers) {
            // $flow-disable-line
            dir.modifiers = emptyModifiers;
        }
        res[getRawDirName(dir)] = dir;
        if (vm._setupState && vm._setupState.__sfc) {
            var setupDef = dir.def || resolveAsset(vm, '_setupState', 'v-' + dir.name);
            if (typeof setupDef === 'function') {
                dir.def = {
                    bind: setupDef,
                    update: setupDef,
                };
            }
            else {
                dir.def = setupDef;
            }
        }
        dir.def = dir.def || resolveAsset(vm.$options, 'directives', dir.name, true);
    }
    // $flow-disable-line
    return res;
}
function getRawDirName(dir) {
    return (dir.rawName || "".concat(dir.name, ".").concat(Object.keys(dir.modifiers || {}).join('.')));
}
function callHook(dir, hook, vnode, oldVnode, isDestroy) {
    var fn = dir.def && dir.def[hook];
    if (fn) {
        try {
            fn(vnode.elm, dir, vnode, oldVnode, isDestroy);
        }
        catch (e) {
            handleError(e, vnode.context, "directive ".concat(dir.name, " ").concat(hook, " hook"));
        }
    }
}

var baseModules = [ref, directives];

function updateAttrs(oldVnode, vnode) {
    var opts = vnode.componentOptions;
    if (isDef(opts) && opts.Ctor.options.inheritAttrs === false) {
        return;
    }
    if (isUndef(oldVnode.data.attrs) && isUndef(vnode.data.attrs)) {
        return;
    }
    var key, cur, old;
    var elm = vnode.elm;
    var oldAttrs = oldVnode.data.attrs || {};
    var attrs = vnode.data.attrs || {};
    // clone observed objects, as the user probably wants to mutate it
    if (isDef(attrs.__ob__) || isTrue(attrs._v_attr_proxy)) {
        attrs = vnode.data.attrs = extend({}, attrs);
    }
    for (key in attrs) {
        cur = attrs[key];
        old = oldAttrs[key];
        if (old !== cur) {
            setAttr(elm, key, cur, vnode.data.pre);
        }
    }
    // #4391: in IE9, setting type can reset value for input[type=radio]
    // #6666: IE/Edge forces progress value down to 1 before setting a max
    /* istanbul ignore if */
    if ((isIE || isEdge) && attrs.value !== oldAttrs.value) {
        setAttr(elm, 'value', attrs.value);
    }
    for (key in oldAttrs) {
        if (isUndef(attrs[key])) {
            if (isXlink(key)) {
                elm.removeAttributeNS(xlinkNS, getXlinkProp(key));
            }
            else if (!isEnumeratedAttr(key)) {
                elm.removeAttribute(key);
            }
        }
    }
}
function setAttr(el, key, value, isInPre) {
    if (isInPre || el.tagName.indexOf('-') > -1) {
        baseSetAttr(el, key, value);
    }
    else if (isBooleanAttr(key)) {
        // set attribute for blank value
        // e.g. <option disabled>Select one</option>
        if (isFalsyAttrValue(value)) {
            el.removeAttribute(key);
        }
        else {
            // technically allowfullscreen is a boolean attribute for <iframe>,
            // but Flash expects a value of "true" when used on <embed> tag
            value = key === 'allowfullscreen' && el.tagName === 'EMBED' ? 'true' : key;
            el.setAttribute(key, value);
        }
    }
    else if (isEnumeratedAttr(key)) {
        el.setAttribute(key, convertEnumeratedValue(key, value));
    }
    else if (isXlink(key)) {
        if (isFalsyAttrValue(value)) {
            el.removeAttributeNS(xlinkNS, getXlinkProp(key));
        }
        else {
            el.setAttributeNS(xlinkNS, key, value);
        }
    }
    else {
        baseSetAttr(el, key, value);
    }
}
function baseSetAttr(el, key, value) {
    if (isFalsyAttrValue(value)) {
        el.removeAttribute(key);
    }
    else {
        // #7138: IE10 & 11 fires input event when setting placeholder on
        // <textarea>... block the first input event and remove the blocker
        // immediately.
        /* istanbul ignore if */
        if (isIE &&
            !isIE9 &&
            el.tagName === 'TEXTAREA' &&
            key === 'placeholder' &&
            value !== '' &&
            !el.__ieph) {
            var blocker_1 = function (e) {
                e.stopImmediatePropagation();
                el.removeEventListener('input', blocker_1);
            };
            el.addEventListener('input', blocker_1);
            // $flow-disable-line
            el.__ieph = true; /* IE placeholder patched */
        }
        el.setAttribute(key, value);
    }
}
var attrs = {
    create: updateAttrs,
    update: updateAttrs
};

function updateClass(oldVnode, vnode) {
    var el = vnode.elm;
    var data = vnode.data;
    var oldData = oldVnode.data;
    if (isUndef(data.staticClass) &&
        isUndef(data.class) &&
        (isUndef(oldData) ||
            (isUndef(oldData.staticClass) && isUndef(oldData.class)))) {
        return;
    }
    var cls = genClassForVnode(vnode);
    // handle transition classes
    var transitionClass = el._transitionClasses;
    if (isDef(transitionClass)) {
        cls = concat(cls, stringifyClass(transitionClass));
    }
    // set the class
    if (cls !== el._prevClass) {
        el.setAttribute('class', cls);
        el._prevClass = cls;
    }
}
var klass = {
    create: updateClass,
    update: updateClass
};

// in some cases, the event used has to be determined at runtime
// so we used some reserved tokens during compile.
var RANGE_TOKEN = '__r';
var CHECKBOX_RADIO_TOKEN = '__c';

// normalize v-model event tokens that can only be determined at runtime.
// it's important to place the event as the first in the array because
// the whole point is ensuring the v-model callback gets called before
// user-attached handlers.
function normalizeEvents(on) {
    /* istanbul ignore if */
    if (isDef(on[RANGE_TOKEN])) {
        // IE input[type=range] only supports `change` event
        var event_1 = isIE ? 'change' : 'input';
        on[event_1] = [].concat(on[RANGE_TOKEN], on[event_1] || []);
        delete on[RANGE_TOKEN];
    }
    // This was originally intended to fix #4521 but no longer necessary
    // after 2.5. Keeping it for backwards compat with generated code from < 2.4
    /* istanbul ignore if */
    if (isDef(on[CHECKBOX_RADIO_TOKEN])) {
        on.change = [].concat(on[CHECKBOX_RADIO_TOKEN], on.change || []);
        delete on[CHECKBOX_RADIO_TOKEN];
    }
}
var target;
function createOnceHandler(event, handler, capture) {
    var _target = target; // save current target element in closure
    return function onceHandler() {
        var res = handler.apply(null, arguments);
        if (res !== null) {
            remove(event, onceHandler, capture, _target);
        }
    };
}
// #9446: Firefox <= 53 (in particular, ESR 52) has incorrect Event.timeStamp
// implementation and does not fire microtasks in between event propagation, so
// safe to exclude.
var useMicrotaskFix = isUsingMicroTask && !(isFF && Number(isFF[1]) <= 53);
function add(name, handler, capture, passive) {
    // async edge case #6566: inner click event triggers patch, event handler
    // attached to outer element during patch, and triggered again. This
    // happens because browsers fire microtask ticks between event propagation.
    // the solution is simple: we save the timestamp when a handler is attached,
    // and the handler would only fire if the event passed to it was fired
    // AFTER it was attached.
    if (useMicrotaskFix) {
        var attachedTimestamp_1 = currentFlushTimestamp;
        var original_1 = handler;
        //@ts-expect-error
        handler = original_1._wrapper = function (e) {
            if (
            // no bubbling, should always fire.
            // this is just a safety net in case event.timeStamp is unreliable in
            // certain weird environments...
            e.target === e.currentTarget ||
                // event is fired after handler attachment
                e.timeStamp >= attachedTimestamp_1 ||
                // bail for environments that have buggy event.timeStamp implementations
                // #9462 iOS 9 bug: event.timeStamp is 0 after history.pushState
                // #9681 QtWebEngine event.timeStamp is negative value
                e.timeStamp <= 0 ||
                // #9448 bail if event is fired in another document in a multi-page
                // electron/nw.js app, since event.timeStamp will be using a different
                // starting reference
                e.target.ownerDocument !== document) {
                return original_1.apply(this, arguments);
            }
        };
    }
    target.addEventListener(name, handler, supportsPassive ? { capture: capture, passive: passive } : capture);
}
function remove(name, handler, capture, _target) {
    (_target || target).removeEventListener(name, 
    //@ts-expect-error
    handler._wrapper || handler, capture);
}
function updateDOMListeners(oldVnode, vnode) {
    if (isUndef(oldVnode.data.on) && isUndef(vnode.data.on)) {
        return;
    }
    var on = vnode.data.on || {};
    var oldOn = oldVnode.data.on || {};
    // vnode is empty when removing all listeners,
    // and use old vnode dom element
    target = vnode.elm || oldVnode.elm;
    normalizeEvents(on);
    updateListeners(on, oldOn, add, remove, createOnceHandler, vnode.context);
    target = undefined;
}
var events = {
    create: updateDOMListeners,
    update: updateDOMListeners,
    // @ts-expect-error emptyNode has actually data
    destroy: function (vnode) { return updateDOMListeners(vnode, emptyNode); }
};

var svgContainer;
function updateDOMProps(oldVnode, vnode) {
    if (isUndef(oldVnode.data.domProps) && isUndef(vnode.data.domProps)) {
        return;
    }
    var key, cur;
    var elm = vnode.elm;
    var oldProps = oldVnode.data.domProps || {};
    var props = vnode.data.domProps || {};
    // clone observed objects, as the user probably wants to mutate it
    if (isDef(props.__ob__) || isTrue(props._v_attr_proxy)) {
        props = vnode.data.domProps = extend({}, props);
    }
    for (key in oldProps) {
        if (!(key in props)) {
            elm[key] = '';
        }
    }
    for (key in props) {
        cur = props[key];
        // ignore children if the node has textContent or innerHTML,
        // as these will throw away existing DOM nodes and cause removal errors
        // on subsequent patches (#3360)
        if (key === 'textContent' || key === 'innerHTML') {
            if (vnode.children)
                vnode.children.length = 0;
            if (cur === oldProps[key])
                continue;
            // #6601 work around Chrome version <= 55 bug where single textNode
            // replaced by innerHTML/textContent retains its parentNode property
            if (elm.childNodes.length === 1) {
                elm.removeChild(elm.childNodes[0]);
            }
        }
        if (key === 'value' && elm.tagName !== 'PROGRESS') {
            // store value as _value as well since
            // non-string values will be stringified
            elm._value = cur;
            // avoid resetting cursor position when value is the same
            var strCur = isUndef(cur) ? '' : String(cur);
            if (shouldUpdateValue(elm, strCur)) {
                elm.value = strCur;
            }
        }
        else if (key === 'innerHTML' &&
            isSVG(elm.tagName) &&
            isUndef(elm.innerHTML)) {
            // IE doesn't support innerHTML for SVG elements
            svgContainer = svgContainer || document.createElement('div');
            svgContainer.innerHTML = "<svg>".concat(cur, "</svg>");
            var svg = svgContainer.firstChild;
            while (elm.firstChild) {
                elm.removeChild(elm.firstChild);
            }
            while (svg.firstChild) {
                elm.appendChild(svg.firstChild);
            }
        }
        else if (
        // skip the update if old and new VDOM state is the same.
        // `value` is handled separately because the DOM value may be temporarily
        // out of sync with VDOM state due to focus, composition and modifiers.
        // This  #4521 by skipping the unnecessary `checked` update.
        cur !== oldProps[key]) {
            // some property updates can throw
            // e.g. `value` on <progress> w/ non-finite value
            try {
                elm[key] = cur;
            }
            catch (e) { }
        }
    }
}
function shouldUpdateValue(elm, checkVal) {
    return (
    //@ts-expect-error
    !elm.composing &&
        (elm.tagName === 'OPTION' ||
            isNotInFocusAndDirty(elm, checkVal) ||
            isDirtyWithModifiers(elm, checkVal)));
}
function isNotInFocusAndDirty(elm, checkVal) {
    // return true when textbox (.number and .trim) loses focus and its value is
    // not equal to the updated value
    var notInFocus = true;
    // #6157
    // work around IE bug when accessing document.activeElement in an iframe
    try {
        notInFocus = document.activeElement !== elm;
    }
    catch (e) { }
    return notInFocus && elm.value !== checkVal;
}
function isDirtyWithModifiers(elm, newVal) {
    var value = elm.value;
    var modifiers = elm._vModifiers; // injected by v-model runtime
    if (isDef(modifiers)) {
        if (modifiers.number) {
            return toNumber(value) !== toNumber(newVal);
        }
        if (modifiers.trim) {
            return value.trim() !== newVal.trim();
        }
    }
    return value !== newVal;
}
var domProps = {
    create: updateDOMProps,
    update: updateDOMProps
};

var parseStyleText = cached(function (cssText) {
    var res = {};
    var listDelimiter = /;(?![^(]*\))/g;
    var propertyDelimiter = /:(.+)/;
    cssText.split(listDelimiter).forEach(function (item) {
        if (item) {
            var tmp = item.split(propertyDelimiter);
            tmp.length > 1 && (res[tmp[0].trim()] = tmp[1].trim());
        }
    });
    return res;
});
// merge static and dynamic style data on the same vnode
function normalizeStyleData(data) {
    var style = normalizeStyleBinding(data.style);
    // static style is pre-processed into an object during compilation
    // and is always a fresh object, so it's safe to merge into it
    return data.staticStyle ? extend(data.staticStyle, style) : style;
}
// normalize possible array / string values into Object
function normalizeStyleBinding(bindingStyle) {
    if (Array.isArray(bindingStyle)) {
        return toObject(bindingStyle);
    }
    if (typeof bindingStyle === 'string') {
        return parseStyleText(bindingStyle);
    }
    return bindingStyle;
}
/**
 * parent component style should be after child's
 * so that parent component's style could override it
 */
function getStyle(vnode, checkChild) {
    var res = {};
    var styleData;
    if (checkChild) {
        var childNode = vnode;
        while (childNode.componentInstance) {
            childNode = childNode.componentInstance._vnode;
            if (childNode &&
                childNode.data &&
                (styleData = normalizeStyleData(childNode.data))) {
                extend(res, styleData);
            }
        }
    }
    if ((styleData = normalizeStyleData(vnode.data))) {
        extend(res, styleData);
    }
    var parentNode = vnode;
    // @ts-expect-error parentNode.parent not VNodeWithData
    while ((parentNode = parentNode.parent)) {
        if (parentNode.data && (styleData = normalizeStyleData(parentNode.data))) {
            extend(res, styleData);
        }
    }
    return res;
}

var cssVarRE = /^--/;
var importantRE = /\s*!important$/;
var setProp = function (el, name, val) {
    /* istanbul ignore if */
    if (cssVarRE.test(name)) {
        el.style.setProperty(name, val);
    }
    else if (importantRE.test(val)) {
        el.style.setProperty(hyphenate(name), val.replace(importantRE, ''), 'important');
    }
    else {
        var normalizedName = normalize(name);
        if (Array.isArray(val)) {
            // Support values array created by autoprefixer, e.g.
            // {display: ["-webkit-box", "-ms-flexbox", "flex"]}
            // Set them one by one, and the browser will only set those it can recognize
            for (var i = 0, len = val.length; i < len; i++) {
                el.style[normalizedName] = val[i];
            }
        }
        else {
            el.style[normalizedName] = val;
        }
    }
};
var vendorNames = ['Webkit', 'Moz', 'ms'];
var emptyStyle;
var normalize = cached(function (prop) {
    emptyStyle = emptyStyle || document.createElement('div').style;
    prop = camelize(prop);
    if (prop !== 'filter' && prop in emptyStyle) {
        return prop;
    }
    var capName = prop.charAt(0).toUpperCase() + prop.slice(1);
    for (var i = 0; i < vendorNames.length; i++) {
        var name_1 = vendorNames[i] + capName;
        if (name_1 in emptyStyle) {
            return name_1;
        }
    }
});
function updateStyle(oldVnode, vnode) {
    var data = vnode.data;
    var oldData = oldVnode.data;
    if (isUndef(data.staticStyle) &&
        isUndef(data.style) &&
        isUndef(oldData.staticStyle) &&
        isUndef(oldData.style)) {
        return;
    }
    var cur, name;
    var el = vnode.elm;
    var oldStaticStyle = oldData.staticStyle;
    var oldStyleBinding = oldData.normalizedStyle || oldData.style || {};
    // if static style exists, stylebinding already merged into it when doing normalizeStyleData
    var oldStyle = oldStaticStyle || oldStyleBinding;
    var style = normalizeStyleBinding(vnode.data.style) || {};
    // store normalized style under a different key for next diff
    // make sure to clone it if it's reactive, since the user likely wants
    // to mutate it.
    vnode.data.normalizedStyle = isDef(style.__ob__) ? extend({}, style) : style;
    var newStyle = getStyle(vnode, true);
    for (name in oldStyle) {
        if (isUndef(newStyle[name])) {
            setProp(el, name, '');
        }
    }
    for (name in newStyle) {
        cur = newStyle[name];
        // ie9 setting to null has no effect, must use empty string
        setProp(el, name, cur == null ? '' : cur);
    }
}
var style = {
    create: updateStyle,
    update: updateStyle
};

var whitespaceRE = /\s+/;
/**
 * Add class with compatibility for SVG since classList is not supported on
 * SVG elements in IE
 */
function addClass(el, cls) {
    /* istanbul ignore if */
    if (!cls || !(cls = cls.trim())) {
        return;
    }
    /* istanbul ignore else */
    if (el.classList) {
        if (cls.indexOf(' ') > -1) {
            cls.split(whitespaceRE).forEach(function (c) { return el.classList.add(c); });
        }
        else {
            el.classList.add(cls);
        }
    }
    else {
        var cur = " ".concat(el.getAttribute('class') || '', " ");
        if (cur.indexOf(' ' + cls + ' ') < 0) {
            el.setAttribute('class', (cur + cls).trim());
        }
    }
}
/**
 * Remove class with compatibility for SVG since classList is not supported on
 * SVG elements in IE
 */
function removeClass(el, cls) {
    /* istanbul ignore if */
    if (!cls || !(cls = cls.trim())) {
        return;
    }
    /* istanbul ignore else */
    if (el.classList) {
        if (cls.indexOf(' ') > -1) {
            cls.split(whitespaceRE).forEach(function (c) { return el.classList.remove(c); });
        }
        else {
            el.classList.remove(cls);
        }
        if (!el.classList.length) {
            el.removeAttribute('class');
        }
    }
    else {
        var cur = " ".concat(el.getAttribute('class') || '', " ");
        var tar = ' ' + cls + ' ';
        while (cur.indexOf(tar) >= 0) {
            cur = cur.replace(tar, ' ');
        }
        cur = cur.trim();
        if (cur) {
            el.setAttribute('class', cur);
        }
        else {
            el.removeAttribute('class');
        }
    }
}

function resolveTransition(def) {
    if (!def) {
        return;
    }
    /* istanbul ignore else */
    if (typeof def === 'object') {
        var res = {};
        if (def.css !== false) {
            extend(res, autoCssTransition(def.name || 'v'));
        }
        extend(res, def);
        return res;
    }
    else if (typeof def === 'string') {
        return autoCssTransition(def);
    }
}
var autoCssTransition = cached(function (name) {
    return {
        enterClass: "".concat(name, "-enter"),
        enterToClass: "".concat(name, "-enter-to"),
        enterActiveClass: "".concat(name, "-enter-active"),
        leaveClass: "".concat(name, "-leave"),
        leaveToClass: "".concat(name, "-leave-to"),
        leaveActiveClass: "".concat(name, "-leave-active")
    };
});
var hasTransition = inBrowser && !isIE9;
var TRANSITION = 'transition';
var ANIMATION = 'animation';
// Transition property/event sniffing
var transitionProp = 'transition';
var transitionEndEvent = 'transitionend';
var animationProp = 'animation';
var animationEndEvent = 'animationend';
if (hasTransition) {
    /* istanbul ignore if */
    if (window.ontransitionend === undefined &&
        window.onwebkittransitionend !== undefined) {
        transitionProp = 'WebkitTransition';
        transitionEndEvent = 'webkitTransitionEnd';
    }
    if (window.onanimationend === undefined &&
        window.onwebkitanimationend !== undefined) {
        animationProp = 'WebkitAnimation';
        animationEndEvent = 'webkitAnimationEnd';
    }
}
// binding to window is necessary to make hot reload work in IE in strict mode
var raf = inBrowser
    ? window.requestAnimationFrame
        ? window.requestAnimationFrame.bind(window)
        : setTimeout
    : /* istanbul ignore next */ function (/* istanbul ignore next */ fn) { return fn(); };
function nextFrame(fn) {
    raf(function () {
        // @ts-expect-error
        raf(fn);
    });
}
function addTransitionClass(el, cls) {
    var transitionClasses = el._transitionClasses || (el._transitionClasses = []);
    if (transitionClasses.indexOf(cls) < 0) {
        transitionClasses.push(cls);
        addClass(el, cls);
    }
}
function removeTransitionClass(el, cls) {
    if (el._transitionClasses) {
        remove$2(el._transitionClasses, cls);
    }
    removeClass(el, cls);
}
function whenTransitionEnds(el, expectedType, cb) {
    var _a = getTransitionInfo(el, expectedType), type = _a.type, timeout = _a.timeout, propCount = _a.propCount;
    if (!type)
        return cb();
    var event = type === TRANSITION ? transitionEndEvent : animationEndEvent;
    var ended = 0;
    var end = function () {
        el.removeEventListener(event, onEnd);
        cb();
    };
    var onEnd = function (e) {
        if (e.target === el) {
            if (++ended >= propCount) {
                end();
            }
        }
    };
    setTimeout(function () {
        if (ended < propCount) {
            end();
        }
    }, timeout + 1);
    el.addEventListener(event, onEnd);
}
var transformRE = /\b(transform|all)(,|$)/;
function getTransitionInfo(el, expectedType) {
    var styles = window.getComputedStyle(el);
    // JSDOM may return undefined for transition properties
    var transitionDelays = (styles[transitionProp + 'Delay'] || '').split(', ');
    var transitionDurations = (styles[transitionProp + 'Duration'] || '').split(', ');
    var transitionTimeout = getTimeout(transitionDelays, transitionDurations);
    var animationDelays = (styles[animationProp + 'Delay'] || '').split(', ');
    var animationDurations = (styles[animationProp + 'Duration'] || '').split(', ');
    var animationTimeout = getTimeout(animationDelays, animationDurations);
    var type;
    var timeout = 0;
    var propCount = 0;
    /* istanbul ignore if */
    if (expectedType === TRANSITION) {
        if (transitionTimeout > 0) {
            type = TRANSITION;
            timeout = transitionTimeout;
            propCount = transitionDurations.length;
        }
    }
    else if (expectedType === ANIMATION) {
        if (animationTimeout > 0) {
            type = ANIMATION;
            timeout = animationTimeout;
            propCount = animationDurations.length;
        }
    }
    else {
        timeout = Math.max(transitionTimeout, animationTimeout);
        type =
            timeout > 0
                ? transitionTimeout > animationTimeout
                    ? TRANSITION
                    : ANIMATION
                : null;
        propCount = type
            ? type === TRANSITION
                ? transitionDurations.length
                : animationDurations.length
            : 0;
    }
    var hasTransform = type === TRANSITION && transformRE.test(styles[transitionProp + 'Property']);
    return {
        type: type,
        timeout: timeout,
        propCount: propCount,
        hasTransform: hasTransform
    };
}
function getTimeout(delays, durations) {
    /* istanbul ignore next */
    while (delays.length < durations.length) {
        delays = delays.concat(delays);
    }
    return Math.max.apply(null, durations.map(function (d, i) {
        return toMs(d) + toMs(delays[i]);
    }));
}
// Old versions of Chromium (below 61.0.3163.100) formats floating pointer numbers
// in a locale-dependent way, using a comma instead of a dot.
// If comma is not replaced with a dot, the input will be rounded down (i.e. acting
// as a floor function) causing unexpected behaviors
function toMs(s) {
    return Number(s.slice(0, -1).replace(',', '.')) * 1000;
}

function enter(vnode, toggleDisplay) {
    var el = vnode.elm;
    // call leave callback now
    if (isDef(el._leaveCb)) {
        el._leaveCb.cancelled = true;
        el._leaveCb();
    }
    var data = resolveTransition(vnode.data.transition);
    if (isUndef(data)) {
        return;
    }
    /* istanbul ignore if */
    if (isDef(el._enterCb) || el.nodeType !== 1) {
        return;
    }
    var css = data.css, type = data.type, enterClass = data.enterClass, enterToClass = data.enterToClass, enterActiveClass = data.enterActiveClass, appearClass = data.appearClass, appearToClass = data.appearToClass, appearActiveClass = data.appearActiveClass, beforeEnter = data.beforeEnter, enter = data.enter, afterEnter = data.afterEnter, enterCancelled = data.enterCancelled, beforeAppear = data.beforeAppear, appear = data.appear, afterAppear = data.afterAppear, appearCancelled = data.appearCancelled, duration = data.duration;
    // activeInstance will always be the <transition> component managing this
    // transition. One edge case to check is when the <transition> is placed
    // as the root node of a child component. In that case we need to check
    // <transition>'s parent for appear check.
    var context = activeInstance;
    var transitionNode = activeInstance.$vnode;
    while (transitionNode && transitionNode.parent) {
        context = transitionNode.context;
        transitionNode = transitionNode.parent;
    }
    var isAppear = !context._isMounted || !vnode.isRootInsert;
    if (isAppear && !appear && appear !== '') {
        return;
    }
    var startClass = isAppear && appearClass ? appearClass : enterClass;
    var activeClass = isAppear && appearActiveClass ? appearActiveClass : enterActiveClass;
    var toClass = isAppear && appearToClass ? appearToClass : enterToClass;
    var beforeEnterHook = isAppear ? beforeAppear || beforeEnter : beforeEnter;
    var enterHook = isAppear ? (isFunction(appear) ? appear : enter) : enter;
    var afterEnterHook = isAppear ? afterAppear || afterEnter : afterEnter;
    var enterCancelledHook = isAppear
        ? appearCancelled || enterCancelled
        : enterCancelled;
    var explicitEnterDuration = toNumber(isObject(duration) ? duration.enter : duration);
    if ( true && explicitEnterDuration != null) {
        checkDuration(explicitEnterDuration, 'enter', vnode);
    }
    var expectsCSS = css !== false && !isIE9;
    var userWantsControl = getHookArgumentsLength(enterHook);
    var cb = (el._enterCb = once(function () {
        if (expectsCSS) {
            removeTransitionClass(el, toClass);
            removeTransitionClass(el, activeClass);
        }
        // @ts-expect-error
        if (cb.cancelled) {
            if (expectsCSS) {
                removeTransitionClass(el, startClass);
            }
            enterCancelledHook && enterCancelledHook(el);
        }
        else {
            afterEnterHook && afterEnterHook(el);
        }
        el._enterCb = null;
    }));
    if (!vnode.data.show) {
        // remove pending leave element on enter by injecting an insert hook
        mergeVNodeHook(vnode, 'insert', function () {
            var parent = el.parentNode;
            var pendingNode = parent && parent._pending && parent._pending[vnode.key];
            if (pendingNode &&
                pendingNode.tag === vnode.tag &&
                pendingNode.elm._leaveCb) {
                pendingNode.elm._leaveCb();
            }
            enterHook && enterHook(el, cb);
        });
    }
    // start enter transition
    beforeEnterHook && beforeEnterHook(el);
    if (expectsCSS) {
        addTransitionClass(el, startClass);
        addTransitionClass(el, activeClass);
        nextFrame(function () {
            removeTransitionClass(el, startClass);
            // @ts-expect-error
            if (!cb.cancelled) {
                addTransitionClass(el, toClass);
                if (!userWantsControl) {
                    if (isValidDuration(explicitEnterDuration)) {
                        setTimeout(cb, explicitEnterDuration);
                    }
                    else {
                        whenTransitionEnds(el, type, cb);
                    }
                }
            }
        });
    }
    if (vnode.data.show) {
        toggleDisplay && toggleDisplay();
        enterHook && enterHook(el, cb);
    }
    if (!expectsCSS && !userWantsControl) {
        cb();
    }
}
function leave(vnode, rm) {
    var el = vnode.elm;
    // call enter callback now
    if (isDef(el._enterCb)) {
        el._enterCb.cancelled = true;
        el._enterCb();
    }
    var data = resolveTransition(vnode.data.transition);
    if (isUndef(data) || el.nodeType !== 1) {
        return rm();
    }
    /* istanbul ignore if */
    if (isDef(el._leaveCb)) {
        return;
    }
    var css = data.css, type = data.type, leaveClass = data.leaveClass, leaveToClass = data.leaveToClass, leaveActiveClass = data.leaveActiveClass, beforeLeave = data.beforeLeave, leave = data.leave, afterLeave = data.afterLeave, leaveCancelled = data.leaveCancelled, delayLeave = data.delayLeave, duration = data.duration;
    var expectsCSS = css !== false && !isIE9;
    var userWantsControl = getHookArgumentsLength(leave);
    var explicitLeaveDuration = toNumber(isObject(duration) ? duration.leave : duration);
    if ( true && isDef(explicitLeaveDuration)) {
        checkDuration(explicitLeaveDuration, 'leave', vnode);
    }
    var cb = (el._leaveCb = once(function () {
        if (el.parentNode && el.parentNode._pending) {
            el.parentNode._pending[vnode.key] = null;
        }
        if (expectsCSS) {
            removeTransitionClass(el, leaveToClass);
            removeTransitionClass(el, leaveActiveClass);
        }
        // @ts-expect-error
        if (cb.cancelled) {
            if (expectsCSS) {
                removeTransitionClass(el, leaveClass);
            }
            leaveCancelled && leaveCancelled(el);
        }
        else {
            rm();
            afterLeave && afterLeave(el);
        }
        el._leaveCb = null;
    }));
    if (delayLeave) {
        delayLeave(performLeave);
    }
    else {
        performLeave();
    }
    function performLeave() {
        // the delayed leave may have already been cancelled
        // @ts-expect-error
        if (cb.cancelled) {
            return;
        }
        // record leaving element
        if (!vnode.data.show && el.parentNode) {
            (el.parentNode._pending || (el.parentNode._pending = {}))[vnode.key] =
                vnode;
        }
        beforeLeave && beforeLeave(el);
        if (expectsCSS) {
            addTransitionClass(el, leaveClass);
            addTransitionClass(el, leaveActiveClass);
            nextFrame(function () {
                removeTransitionClass(el, leaveClass);
                // @ts-expect-error
                if (!cb.cancelled) {
                    addTransitionClass(el, leaveToClass);
                    if (!userWantsControl) {
                        if (isValidDuration(explicitLeaveDuration)) {
                            setTimeout(cb, explicitLeaveDuration);
                        }
                        else {
                            whenTransitionEnds(el, type, cb);
                        }
                    }
                }
            });
        }
        leave && leave(el, cb);
        if (!expectsCSS && !userWantsControl) {
            cb();
        }
    }
}
// only used in dev mode
function checkDuration(val, name, vnode) {
    if (typeof val !== 'number') {
        warn("<transition> explicit ".concat(name, " duration is not a valid number - ") +
            "got ".concat(JSON.stringify(val), "."), vnode.context);
    }
    else if (isNaN(val)) {
        warn("<transition> explicit ".concat(name, " duration is NaN - ") +
            'the duration expression might be incorrect.', vnode.context);
    }
}
function isValidDuration(val) {
    return typeof val === 'number' && !isNaN(val);
}
/**
 * Normalize a transition hook's argument length. The hook may be:
 * - a merged hook (invoker) with the original in .fns
 * - a wrapped component method (check ._length)
 * - a plain function (.length)
 */
function getHookArgumentsLength(fn) {
    if (isUndef(fn)) {
        return false;
    }
    // @ts-expect-error
    var invokerFns = fn.fns;
    if (isDef(invokerFns)) {
        // invoker
        return getHookArgumentsLength(Array.isArray(invokerFns) ? invokerFns[0] : invokerFns);
    }
    else {
        // @ts-expect-error
        return (fn._length || fn.length) > 1;
    }
}
function _enter(_, vnode) {
    if (vnode.data.show !== true) {
        enter(vnode);
    }
}
var transition = inBrowser
    ? {
        create: _enter,
        activate: _enter,
        remove: function (vnode, rm) {
            /* istanbul ignore else */
            if (vnode.data.show !== true) {
                // @ts-expect-error
                leave(vnode, rm);
            }
            else {
                rm();
            }
        }
    }
    : {};

var platformModules = [attrs, klass, events, domProps, style, transition];

// the directive module should be applied last, after all
// built-in modules have been applied.
var modules = platformModules.concat(baseModules);
var patch = createPatchFunction({ nodeOps: nodeOps, modules: modules });

/**
 * Not type checking this file because flow doesn't like attaching
 * properties to Elements.
 */
/* istanbul ignore if */
if (isIE9) {
    // http://www.matts411.com/post/internet-explorer-9-oninput/
    document.addEventListener('selectionchange', function () {
        var el = document.activeElement;
        // @ts-expect-error
        if (el && el.vmodel) {
            trigger(el, 'input');
        }
    });
}
var directive = {
    inserted: function (el, binding, vnode, oldVnode) {
        if (vnode.tag === 'select') {
            // #6903
            if (oldVnode.elm && !oldVnode.elm._vOptions) {
                mergeVNodeHook(vnode, 'postpatch', function () {
                    directive.componentUpdated(el, binding, vnode);
                });
            }
            else {
                setSelected(el, binding, vnode.context);
            }
            el._vOptions = [].map.call(el.options, getValue);
        }
        else if (vnode.tag === 'textarea' || isTextInputType(el.type)) {
            el._vModifiers = binding.modifiers;
            if (!binding.modifiers.lazy) {
                el.addEventListener('compositionstart', onCompositionStart);
                el.addEventListener('compositionend', onCompositionEnd);
                // Safari < 10.2 & UIWebView doesn't fire compositionend when
                // switching focus before confirming composition choice
                // this also fixes the issue where some browsers e.g. iOS Chrome
                // fires "change" instead of "input" on autocomplete.
                el.addEventListener('change', onCompositionEnd);
                /* istanbul ignore if */
                if (isIE9) {
                    el.vmodel = true;
                }
            }
        }
    },
    componentUpdated: function (el, binding, vnode) {
        if (vnode.tag === 'select') {
            setSelected(el, binding, vnode.context);
            // in case the options rendered by v-for have changed,
            // it's possible that the value is out-of-sync with the rendered options.
            // detect such cases and filter out values that no longer has a matching
            // option in the DOM.
            var prevOptions_1 = el._vOptions;
            var curOptions_1 = (el._vOptions = [].map.call(el.options, getValue));
            if (curOptions_1.some(function (o, i) { return !looseEqual(o, prevOptions_1[i]); })) {
                // trigger change event if
                // no matching option found for at least one value
                var needReset = el.multiple
                    ? binding.value.some(function (v) { return hasNoMatchingOption(v, curOptions_1); })
                    : binding.value !== binding.oldValue &&
                        hasNoMatchingOption(binding.value, curOptions_1);
                if (needReset) {
                    trigger(el, 'change');
                }
            }
        }
    }
};
function setSelected(el, binding, vm) {
    actuallySetSelected(el, binding, vm);
    /* istanbul ignore if */
    if (isIE || isEdge) {
        setTimeout(function () {
            actuallySetSelected(el, binding, vm);
        }, 0);
    }
}
function actuallySetSelected(el, binding, vm) {
    var value = binding.value;
    var isMultiple = el.multiple;
    if (isMultiple && !Array.isArray(value)) {
         true &&
            warn("<select multiple v-model=\"".concat(binding.expression, "\"> ") +
                "expects an Array value for its binding, but got ".concat(Object.prototype.toString
                    .call(value)
                    .slice(8, -1)), vm);
        return;
    }
    var selected, option;
    for (var i = 0, l = el.options.length; i < l; i++) {
        option = el.options[i];
        if (isMultiple) {
            selected = looseIndexOf(value, getValue(option)) > -1;
            if (option.selected !== selected) {
                option.selected = selected;
            }
        }
        else {
            if (looseEqual(getValue(option), value)) {
                if (el.selectedIndex !== i) {
                    el.selectedIndex = i;
                }
                return;
            }
        }
    }
    if (!isMultiple) {
        el.selectedIndex = -1;
    }
}
function hasNoMatchingOption(value, options) {
    return options.every(function (o) { return !looseEqual(o, value); });
}
function getValue(option) {
    return '_value' in option ? option._value : option.value;
}
function onCompositionStart(e) {
    e.target.composing = true;
}
function onCompositionEnd(e) {
    // prevent triggering an input event for no reason
    if (!e.target.composing)
        return;
    e.target.composing = false;
    trigger(e.target, 'input');
}
function trigger(el, type) {
    var e = document.createEvent('HTMLEvents');
    e.initEvent(type, true, true);
    el.dispatchEvent(e);
}

// recursively search for possible transition defined inside the component root
function locateNode(vnode) {
    // @ts-expect-error
    return vnode.componentInstance && (!vnode.data || !vnode.data.transition)
        ? locateNode(vnode.componentInstance._vnode)
        : vnode;
}
var show = {
    bind: function (el, _a, vnode) {
        var value = _a.value;
        vnode = locateNode(vnode);
        var transition = vnode.data && vnode.data.transition;
        var originalDisplay = (el.__vOriginalDisplay =
            el.style.display === 'none' ? '' : el.style.display);
        if (value && transition) {
            vnode.data.show = true;
            enter(vnode, function () {
                el.style.display = originalDisplay;
            });
        }
        else {
            el.style.display = value ? originalDisplay : 'none';
        }
    },
    update: function (el, _a, vnode) {
        var value = _a.value, oldValue = _a.oldValue;
        /* istanbul ignore if */
        if (!value === !oldValue)
            return;
        vnode = locateNode(vnode);
        var transition = vnode.data && vnode.data.transition;
        if (transition) {
            vnode.data.show = true;
            if (value) {
                enter(vnode, function () {
                    el.style.display = el.__vOriginalDisplay;
                });
            }
            else {
                leave(vnode, function () {
                    el.style.display = 'none';
                });
            }
        }
        else {
            el.style.display = value ? el.__vOriginalDisplay : 'none';
        }
    },
    unbind: function (el, binding, vnode, oldVnode, isDestroy) {
        if (!isDestroy) {
            el.style.display = el.__vOriginalDisplay;
        }
    }
};

var platformDirectives = {
    model: directive,
    show: show
};

// Provides transition support for a single element/component.
var transitionProps = {
    name: String,
    appear: Boolean,
    css: Boolean,
    mode: String,
    type: String,
    enterClass: String,
    leaveClass: String,
    enterToClass: String,
    leaveToClass: String,
    enterActiveClass: String,
    leaveActiveClass: String,
    appearClass: String,
    appearActiveClass: String,
    appearToClass: String,
    duration: [Number, String, Object]
};
// in case the child is also an abstract component, e.g. <keep-alive>
// we want to recursively retrieve the real component to be rendered
function getRealChild(vnode) {
    var compOptions = vnode && vnode.componentOptions;
    if (compOptions && compOptions.Ctor.options.abstract) {
        return getRealChild(getFirstComponentChild(compOptions.children));
    }
    else {
        return vnode;
    }
}
function extractTransitionData(comp) {
    var data = {};
    var options = comp.$options;
    // props
    for (var key in options.propsData) {
        data[key] = comp[key];
    }
    // events.
    // extract listeners and pass them directly to the transition methods
    var listeners = options._parentListeners;
    for (var key in listeners) {
        data[camelize(key)] = listeners[key];
    }
    return data;
}
function placeholder(h, rawChild) {
    // @ts-expect-error
    if (/\d-keep-alive$/.test(rawChild.tag)) {
        return h('keep-alive', {
            props: rawChild.componentOptions.propsData
        });
    }
}
function hasParentTransition(vnode) {
    while ((vnode = vnode.parent)) {
        if (vnode.data.transition) {
            return true;
        }
    }
}
function isSameChild(child, oldChild) {
    return oldChild.key === child.key && oldChild.tag === child.tag;
}
var isNotTextNode = function (c) { return c.tag || isAsyncPlaceholder(c); };
var isVShowDirective = function (d) { return d.name === 'show'; };
var Transition = {
    name: 'transition',
    props: transitionProps,
    abstract: true,
    render: function (h) {
        var _this = this;
        var children = this.$slots.default;
        if (!children) {
            return;
        }
        // filter out text nodes (possible whitespaces)
        children = children.filter(isNotTextNode);
        /* istanbul ignore if */
        if (!children.length) {
            return;
        }
        // warn multiple elements
        if ( true && children.length > 1) {
            warn('<transition> can only be used on a single element. Use ' +
                '<transition-group> for lists.', this.$parent);
        }
        var mode = this.mode;
        // warn invalid mode
        if ( true && mode && mode !== 'in-out' && mode !== 'out-in') {
            warn('invalid <transition> mode: ' + mode, this.$parent);
        }
        var rawChild = children[0];
        // if this is a component root node and the component's
        // parent container node also has transition, skip.
        if (hasParentTransition(this.$vnode)) {
            return rawChild;
        }
        // apply transition data to child
        // use getRealChild() to ignore abstract components e.g. keep-alive
        var child = getRealChild(rawChild);
        /* istanbul ignore if */
        if (!child) {
            return rawChild;
        }
        if (this._leaving) {
            return placeholder(h, rawChild);
        }
        // ensure a key that is unique to the vnode type and to this transition
        // component instance. This key will be used to remove pending leaving nodes
        // during entering.
        var id = "__transition-".concat(this._uid, "-");
        child.key =
            child.key == null
                ? child.isComment
                    ? id + 'comment'
                    : id + child.tag
                : isPrimitive(child.key)
                    ? String(child.key).indexOf(id) === 0
                        ? child.key
                        : id + child.key
                    : child.key;
        var data = ((child.data || (child.data = {})).transition =
            extractTransitionData(this));
        var oldRawChild = this._vnode;
        var oldChild = getRealChild(oldRawChild);
        // mark v-show
        // so that the transition module can hand over the control to the directive
        if (child.data.directives && child.data.directives.some(isVShowDirective)) {
            child.data.show = true;
        }
        if (oldChild &&
            oldChild.data &&
            !isSameChild(child, oldChild) &&
            !isAsyncPlaceholder(oldChild) &&
            // #6687 component root is a comment node
            !(oldChild.componentInstance &&
                oldChild.componentInstance._vnode.isComment)) {
            // replace old child transition data with fresh one
            // important for dynamic transitions!
            var oldData = (oldChild.data.transition = extend({}, data));
            // handle transition mode
            if (mode === 'out-in') {
                // return placeholder node and queue update when leave finishes
                this._leaving = true;
                mergeVNodeHook(oldData, 'afterLeave', function () {
                    _this._leaving = false;
                    _this.$forceUpdate();
                });
                return placeholder(h, rawChild);
            }
            else if (mode === 'in-out') {
                if (isAsyncPlaceholder(child)) {
                    return oldRawChild;
                }
                var delayedLeave_1;
                var performLeave = function () {
                    delayedLeave_1();
                };
                mergeVNodeHook(data, 'afterEnter', performLeave);
                mergeVNodeHook(data, 'enterCancelled', performLeave);
                mergeVNodeHook(oldData, 'delayLeave', function (leave) {
                    delayedLeave_1 = leave;
                });
            }
        }
        return rawChild;
    }
};

// Provides transition support for list items.
var props = extend({
    tag: String,
    moveClass: String
}, transitionProps);
delete props.mode;
var TransitionGroup = {
    props: props,
    beforeMount: function () {
        var _this = this;
        var update = this._update;
        this._update = function (vnode, hydrating) {
            var restoreActiveInstance = setActiveInstance(_this);
            // force removing pass
            _this.__patch__(_this._vnode, _this.kept, false, // hydrating
            true // removeOnly (!important, avoids unnecessary moves)
            );
            _this._vnode = _this.kept;
            restoreActiveInstance();
            update.call(_this, vnode, hydrating);
        };
    },
    render: function (h) {
        var tag = this.tag || this.$vnode.data.tag || 'span';
        var map = Object.create(null);
        var prevChildren = (this.prevChildren = this.children);
        var rawChildren = this.$slots.default || [];
        var children = (this.children = []);
        var transitionData = extractTransitionData(this);
        for (var i = 0; i < rawChildren.length; i++) {
            var c = rawChildren[i];
            if (c.tag) {
                if (c.key != null && String(c.key).indexOf('__vlist') !== 0) {
                    children.push(c);
                    map[c.key] = c;
                    (c.data || (c.data = {})).transition = transitionData;
                }
                else if (true) {
                    var opts = c.componentOptions;
                    var name_1 = opts
                        ? getComponentName(opts.Ctor.options) || opts.tag || ''
                        : c.tag;
                    warn("<transition-group> children must be keyed: <".concat(name_1, ">"));
                }
            }
        }
        if (prevChildren) {
            var kept = [];
            var removed = [];
            for (var i = 0; i < prevChildren.length; i++) {
                var c = prevChildren[i];
                c.data.transition = transitionData;
                // @ts-expect-error .getBoundingClientRect is not typed in Node
                c.data.pos = c.elm.getBoundingClientRect();
                if (map[c.key]) {
                    kept.push(c);
                }
                else {
                    removed.push(c);
                }
            }
            this.kept = h(tag, null, kept);
            this.removed = removed;
        }
        return h(tag, null, children);
    },
    updated: function () {
        var children = this.prevChildren;
        var moveClass = this.moveClass || (this.name || 'v') + '-move';
        if (!children.length || !this.hasMove(children[0].elm, moveClass)) {
            return;
        }
        // we divide the work into three loops to avoid mixing DOM reads and writes
        // in each iteration - which helps prevent layout thrashing.
        children.forEach(callPendingCbs);
        children.forEach(recordPosition);
        children.forEach(applyTranslation);
        // force reflow to put everything in position
        // assign to this to avoid being removed in tree-shaking
        // $flow-disable-line
        this._reflow = document.body.offsetHeight;
        children.forEach(function (c) {
            if (c.data.moved) {
                var el_1 = c.elm;
                var s = el_1.style;
                addTransitionClass(el_1, moveClass);
                s.transform = s.WebkitTransform = s.transitionDuration = '';
                el_1.addEventListener(transitionEndEvent, (el_1._moveCb = function cb(e) {
                    if (e && e.target !== el_1) {
                        return;
                    }
                    if (!e || /transform$/.test(e.propertyName)) {
                        el_1.removeEventListener(transitionEndEvent, cb);
                        el_1._moveCb = null;
                        removeTransitionClass(el_1, moveClass);
                    }
                }));
            }
        });
    },
    methods: {
        hasMove: function (el, moveClass) {
            /* istanbul ignore if */
            if (!hasTransition) {
                return false;
            }
            /* istanbul ignore if */
            if (this._hasMove) {
                return this._hasMove;
            }
            // Detect whether an element with the move class applied has
            // CSS transitions. Since the element may be inside an entering
            // transition at this very moment, we make a clone of it and remove
            // all other transition classes applied to ensure only the move class
            // is applied.
            var clone = el.cloneNode();
            if (el._transitionClasses) {
                el._transitionClasses.forEach(function (cls) {
                    removeClass(clone, cls);
                });
            }
            addClass(clone, moveClass);
            clone.style.display = 'none';
            this.$el.appendChild(clone);
            var info = getTransitionInfo(clone);
            this.$el.removeChild(clone);
            return (this._hasMove = info.hasTransform);
        }
    }
};
function callPendingCbs(c) {
    /* istanbul ignore if */
    if (c.elm._moveCb) {
        c.elm._moveCb();
    }
    /* istanbul ignore if */
    if (c.elm._enterCb) {
        c.elm._enterCb();
    }
}
function recordPosition(c) {
    c.data.newPos = c.elm.getBoundingClientRect();
}
function applyTranslation(c) {
    var oldPos = c.data.pos;
    var newPos = c.data.newPos;
    var dx = oldPos.left - newPos.left;
    var dy = oldPos.top - newPos.top;
    if (dx || dy) {
        c.data.moved = true;
        var s = c.elm.style;
        s.transform = s.WebkitTransform = "translate(".concat(dx, "px,").concat(dy, "px)");
        s.transitionDuration = '0s';
    }
}

var platformComponents = {
    Transition: Transition,
    TransitionGroup: TransitionGroup
};

// install platform specific utils
Vue.config.mustUseProp = mustUseProp;
Vue.config.isReservedTag = isReservedTag;
Vue.config.isReservedAttr = isReservedAttr;
Vue.config.getTagNamespace = getTagNamespace;
Vue.config.isUnknownElement = isUnknownElement;
// install platform runtime directives & components
extend(Vue.options.directives, platformDirectives);
extend(Vue.options.components, platformComponents);
// install platform patch function
Vue.prototype.__patch__ = inBrowser ? patch : noop;
// public mount method
Vue.prototype.$mount = function (el, hydrating) {
    el = el && inBrowser ? query(el) : undefined;
    return mountComponent(this, el, hydrating);
};
// devtools global hook
/* istanbul ignore next */
if (inBrowser) {
    setTimeout(function () {
        if (config.devtools) {
            if (devtools) {
                devtools.emit('init', Vue);
            }
            else if (true) {
                // @ts-expect-error
                console[console.info ? 'info' : 'log']('Download the Vue Devtools extension for a better development experience:\n' +
                    'https://github.com/vuejs/vue-devtools');
            }
        }
        if ( true &&
            config.productionTip !== false &&
            typeof console !== 'undefined') {
            // @ts-expect-error
            console[console.info ? 'info' : 'log']("You are running Vue in development mode.\n" +
                "Make sure to turn on production mode when deploying for production.\n" +
                "See more tips at https://vuejs.org/guide/deployment.html");
        }
    }, 0);
}




/***/ }),

/***/ "?9157":
/*!************************!*\
  !*** crypto (ignored) ***!
  \************************/
/***/ (() => {

/* (ignored) */

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	(() => {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = (module) => {
/******/ 			var getter = module && module.__esModule ?
/******/ 				() => (module['default']) :
/******/ 				() => (module);
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/global */
/******/ 	(() => {
/******/ 		__webpack_require__.g = (function() {
/******/ 			if (typeof globalThis === 'object') return globalThis;
/******/ 			try {
/******/ 				return this || new Function('return this')();
/******/ 			} catch (e) {
/******/ 				if (typeof window === 'object') return window;
/******/ 			}
/******/ 		})();
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
/******/ 	
/******/ 	// startup
/******/ 	// Load entry module and return exports
/******/ 	// This entry module is referenced by other modules so it can't be inlined
/******/ 	var __webpack_exports__ = __webpack_require__("./src/import.ts");
/******/ 	
/******/ })()
;
//# sourceMappingURL=import.js.map