/*
    @license
    crypto-js-wasm v1.1.1
    (c) 2022-2024 peteralfredlee
    https://github.com/originjs/crypto-js-wasm
    Released under the MulanPSL2 License.
*/
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('pako')) :
  typeof define === 'function' && define.amd ? define(['pako'], factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.CryptoJSWasm = factory(global.pako));
})(this, (function (pako) { 'use strict';

  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

  var pako__default = /*#__PURE__*/_interopDefaultLegacy(pako);

  /**
   * Latin1 encoding strategy.
   */

  const Latin1 = {
    /**
       * Converts a word array to a Latin1 string.
       *
       * @param {WordArray} wordArray The word array.
       *
       * @return {string} The Latin1 string.
       *
       * @static
       *
       * @example
       *
       *     const latin1String = CryptoJSW.enc.Latin1.stringify(wordArray);
       */
    stringify(wordArray) {
      // Shortcuts
      const {
        words,
        sigBytes
      } = wordArray; // Convert

      let latin1Chars = '';

      for (let i = 0; i < sigBytes; i++) {
        const byte = words[i >>> 2] >>> 24 - i % 4 * 8 & 0xff;
        latin1Chars += String.fromCharCode(byte);
      }

      return latin1Chars;
    },

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

      const words = [];
      let word = 0; // const words = new Array(latin1StrLength >>> 2);

      for (let i = 0; i < latin1StrLength - latin1StrLength % 4; i++) {
        word |= (latin1Str.charCodeAt(i) & 0xff) << 24 - i % 4 * 8;

        if (i % 4 == 3) {
          words[i >>> 2] = word;
          word = 0;
        }
      }

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

      return new WordArray(words, latin1StrLength);
    }

  };

  /**
  * UTF-8 encoding strategy.
  */

  const Utf8 = {
    /**
       * Converts a word array to a UTF-8 string.
       *
       * @param {WordArray} wordArray The word array.
       *
       * @return {string} The UTF-8 string.
       *
       * @static
       *
       * @example
       *
       *     const utf8String = CryptoJSW.enc.Utf8.stringify(wordArray);
       */
    stringify(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
       *
       *     const wordArray = CryptoJSW.enc.Utf8.parse(utf8String);
       */
    parse(utf8Str) {
      return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
    }

  };

  /**
   * Hex encoding strategy.
   */

  const Hex = {
    /**
       * Converts a word array to a hex string.
       *
       * @param {WordArray} wordArray The word array.
       *
       * @return {string} The hex string.
       *
       * @static
       *
       * @example
       *
       *     const hexString = CryptoJSW.enc.Hex.stringify(wordArray);
       */
    stringify(wordArray) {
      // Shortcuts
      const {
        words,
        sigBytes
      } = wordArray; // Convert

      const hexChars = [];

      for (let i = 0; i < sigBytes; i++) {
        const 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
       *
       *     const wordArray = CryptoJSW.enc.Hex.parse(hexString);
       */
    parse(hexStr) {
      // Shortcut
      const hexStrLength = hexStr.length; // Convert

      const words = [];

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

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

  };

  /**
   * Determine if a value is a String
   *
   * @param {Object} val The value to test
   * @returns {Boolean} True if value is a String, otherwise false
   */

  const isString = val => typeof val === 'string';
  /**
   * Check if the input parameter is valid
   *
   * @param parameter {any} input parameter
   * @param parameterDesc {string} description input parameter
   * @param validTypes {string|array} valid types of parameter
   * @param validValues {array} valid values of parameter
   * @throws if parameter is invalid
   */

  const parameterCheck = (parameter, parameterDesc, validTypes, ...validValues) => {
    let isValid = true;

    if (validTypes !== undefined) {
      if (typeof validTypes === 'string' && typeof parameter !== validTypes) {
        isValid = false;
      }

      if (validTypes.indexOf(typeof parameter) < 0) {
        isValid = false;
      }
    }

    if (validValues !== undefined && validValues.length > 0) {
      if (validValues.indexOf(parameter) < 0) {
        isValid = false;
      }
    }

    if (!isValid) {
      throw TypeError(`The input value ${parameter} of ${parameterDesc} is invalid! The type should be ${validTypes}, and the values should be ${validValues}.`);
    }
  };

  /* eslint-disable no-use-before-define */
  let 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
  // eslint-disable-next-line no-undef


  if (typeof globalThis !== 'undefined' && globalThis.crypto) {
    // eslint-disable-next-line no-undef
    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 global !== 'undefined' && global.crypto) {
    crypto = global.crypto;
  } // Native crypto import via require (NodeJS)


  if (!crypto && typeof require === 'function') {
    try {
      crypto = require('crypto'); // eslint-disable-next-line no-empty
    } catch (err) {}
  }

  const cryptoSecureRandomInt = () => {
    if (crypto) {
      // Use getRandomValues method (Browser)
      if (typeof crypto.getRandomValues === 'function') {
        try {
          return crypto.getRandomValues(new Uint32Array(1))[0]; // eslint-disable-next-line no-empty
        } catch (err) {}
      } // Use randomBytes method (NodeJS)


      if (typeof crypto.randomBytes === 'function') {
        try {
          return crypto.randomBytes(4).readInt32LE(); // eslint-disable-next-line no-empty
        } catch (err) {}
      }
    }

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

  class Base {
    /**
     * Copies properties into this object.
     *
     * @param {Object} properties The properties to mix in.
     *
     * @example
     *
     *     MyType.mixIn({
     *         field: 'value'
     *     });
     */
    mixIn(properties) {
      return Object.assign(this, properties);
    }
    /**
     * Creates a copy of this object.
     *
     * @return {Object} The clone.
     *
     * @example
     *
     *     let clone = instance.clone();
     */


    clone() {
      const clone = new this.constructor();
      Object.assign(clone, this);
      return clone;
    }
    /**
     * Get a new instance of this class.
     * Arguments to create() will be passed to constructor.
     *
     * @return {Object} The new object.
     *
     * @static
     *
     * @example
     *
     *     var instance = MyType.create();
     */


    static create(...args) {
      return new this(...args);
    }

  }
  /**
   * 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.
   */

  class WordArray extends Base {
    /**
     * 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
     *
     *     let wordArray = new WordArray();
     *     let wordArray = new WordArray([0x00010203, 0x04050607]);
     *     let wordArray = new WordArray([0x00010203, 0x04050607], 6);
     */
    constructor(words = [], sigBytes = words.length * 4) {
      super();
      let typedArray = words; // Convert buffers to uint8

      if (typedArray instanceof ArrayBuffer) {
        typedArray = new Uint8Array(typedArray);
      } // Convert other array views to uint8


      if (typedArray instanceof Int8Array || 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
        const typedArrayByteLength = typedArray.byteLength; // Extract bytes

        const _words = [];

        for (let i = 0; i < typedArrayByteLength; i++) {
          _words[i >>> 2] |= typedArray[i] << 24 - i % 4 * 8;
        } // Initialize this word array


        this.words = _words;
        this.sigBytes = typedArrayByteLength;
      } else {
        // Else call normal init
        this.words = words;
        this.sigBytes = sigBytes;
      }
    }
    /**
     * Creates and initializes a word array
     * A compatibility method for crypto-js
     *
     * @param {Array} words (Optional) An array of 32-bit words.
     * @param {number} sigBytes (Optional) The number of significant bytes in the words.
     */


    static create(words = [], sigBytes = words.length * 4) {
      return new WordArray(words, sigBytes);
    }
    /**
     * 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
     *
     *     const wordArray = CryptoJSW.lib.WordArray.random(16);
     */


    static random(nBytes) {
      const words = [];

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

      return new WordArray(words, nBytes);
    }
    /**
     * Converts this word array to a string.
     *
     * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJSW.enc.Hex
     *
     * @return {string} The stringified word array.
     *
     * @example
     *
     *     const string = wordArray + '';
     *     const string = wordArray.toString();
     *     const string = wordArray.toString(CryptoJSW.enc.Utf8);
     */


    toString(encoder = Hex) {
      return encoder.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(wordArray) {
      // Shortcuts
      const thisWords = this.words;
      const thatWords = wordArray.words;
      const thisSigBytes = this.sigBytes;
      const thatSigBytes = wordArray.sigBytes; // Clamp excess bits

      this.clamp(); // Concat

      if (thisSigBytes % 4) {
        // Copy one byte at a time
        for (let i = 0; i < thatSigBytes; i++) {
          const 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 (let i = 0; i < thatSigBytes; i += 4) {
          thisWords[thisSigBytes + i >>> 2] = thatWords[i >>> 2];
        }
      }

      this.sigBytes += thatSigBytes; // Chainable

      return this;
    }
    /**
     * Removes insignificant bits.
     *
     * @example
     *
     *     wordArray.clamp();
     */


    clamp() {
      // Shortcuts
      const {
        words,
        sigBytes
      } = this; // 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
     *
     *     let clone = wordArray.clone();
     */


    clone() {
      const clone = super.clone.call(this);
      clone.words = this.words.slice(0);
      return clone;
    }

  }
  /**
   * 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
   */

  class BufferedBlockAlgorithm extends Base {
    constructor() {
      super();
      this._minBufferSize = 0;
    }
    /**
     * Resets this block algorithm's data buffer to its initial state.
     *
     * @example
     *
     *     bufferedBlockAlgorithm.reset();
     */


    reset() {
      // Initial values
      this._data = new WordArray();
      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(data) {
      let m_data = data; // Convert string to WordArray, else assume WordArray already

      if (isString(m_data)) {
        m_data = Utf8.parse(m_data);
      } // Append


      this._data.concat(m_data);

      this._nDataBytes += m_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
     *
     *     let processedData = bufferedBlockAlgorithm._process();
     *     let processedData = bufferedBlockAlgorithm._process(!!'flush');
     */


    _process(doFlush) {
      let processedWords; // Shortcuts

      const {
        _data: data,
        blockSize
      } = this;
      const dataWords = data.words;
      const dataSigBytes = data.sigBytes;
      const blockSizeBytes = blockSize * 4; // Count blocks ready

      let 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


      const nWordsReady = nBlocksReady * blockSize; // Count bytes ready

      const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); // Process blocks

      if (nWordsReady) {
        for (let 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(processedWords, nBytesReady);
    }
    /**
     * Creates a copy of this object.
     *
     * @return {Object} The clone.
     *
     * @example
     *
     *     let clone = bufferedBlockAlgorithm.clone();
     */


    clone() {
      const clone = super.clone.call(this);
      clone._data = this._data.clone();
      return clone;
    }

  }

  /**
   * HMAC algorithm.
   */

  class HMAC extends Base {
    /**
     * Initializes a newly created HMAC.
     *
     * @param {Hasher} SubHasher The hash algorithm to use.
     * @param {WordArray|string} key The secret key.
     *
     * @example
     *
     *     const hmacHasher = new HMAC(CryptoJSW.algo.SHA256, key);
     */
    constructor(SubHasher, key) {
      super();
      const hasher = new SubHasher();
      this._hasher = hasher; // Convert string to WordArray, else assume WordArray already

      let _key = key;

      if (isString(_key)) {
        _key = Utf8.parse(_key);
      } // Shortcuts


      const hasherBlockSize = hasher.blockSize;
      const 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


      const oKey = _key.clone();

      this._oKey = oKey;

      const iKey = _key.clone();

      this._iKey = iKey; // Shortcuts

      const oKeyWords = oKey.words;
      const iKeyWords = iKey.words; // XOR keys with pad constants

      for (let i = 0; i < hasherBlockSize; i++) {
        oKeyWords[i] ^= 0x5c5c5c5c;
        iKeyWords[i] ^= 0x36363636;
      }

      oKey.sigBytes = hasherBlockSizeBytes;
      iKey.sigBytes = hasherBlockSizeBytes; // Set initial values

      this.reset();
    }
    /**
     * Resets this HMAC to its initial state.
     *
     * @example
     *
     *     hmacHasher.reset();
     */


    reset() {
      // Shortcut
      const 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(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
     *
     *     let hmac = hmacHasher.finalize();
     *     let hmac = hmacHasher.finalize('message');
     *     let hmac = hmacHasher.finalize(wordArray);
     */


    finalize(messageUpdate) {
      // Shortcut
      const hasher = this._hasher; // Compute HMAC

      const innerHash = hasher.finalize(messageUpdate);
      hasher.reset();
      const hmac = hasher.finalize(this._oKey.clone().concat(innerHash));
      return hmac;
    }

  }

  /**
   * Abstract hasher template.
   *
   * @property {number} blockSize
   *
   *     The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
   */

  class Hasher extends BufferedBlockAlgorithm {
    constructor(cfg) {
      super();
      this.blockSize = 512 / 32;
      /**
         * Configuration options.
         */

      this.cfg = Object.assign(new Base(), cfg); // Set initial values

      this.reset();
    }
    /**
       * Creates a shortcut function to a hasher's object interface.
       *
       * @param {Hasher} SubHasher The hasher to create a helper for.
       *
       * @return {Function} The shortcut function.
       *
       * @static
       *
       * @example
       *
       *     let SHA256 = CryptoJSW.lib.Hasher._createHelper(CryptoJSW.algo.SHA256);
       */


    static _createHelper(SubHasher) {
      let result = (message, cfg) => new SubHasher(cfg).finalize(message);

      result.loadWasm = async () => {
        if (!SubHasher.wasm) {
          await SubHasher.loadWasm();
        }
      };

      result.outputSize = SubHasher.outputSize;
      return result;
    }
    /**
       * Creates a shortcut function to the HMAC's object interface.
       *
       * @param {Hasher} SubHasher The hasher to use in this HMAC helper.
       *
       * @return {Function} The shortcut function.
       *
       * @static
       *
       * @example
       *
       *     const HmacSHA256 = CryptoJSW.lib.Hasher._createHmacHelper(CryptoJSW.algo.SHA256);
       */


    static _createHmacHelper(SubHasher) {
      let result = (message, key) => new HMAC(SubHasher, key).finalize(message);

      result.loadWasm = async () => {
        if (!SubHasher.wasm) {
          await SubHasher.loadWasm();
        }
      };

      return result;
    }
    /**
       * Resets this hasher to its initial state.
       *
       * @example
       *
       *     hasher.reset();
       */


    reset() {
      // Reset data buffer
      super.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(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
       *
       *     let hash = hasher.finalize();
       *     let hash = hasher.finalize('message');
       *     let hash = hasher.finalize(wordArray);
       */


    finalize(messageUpdate) {
      // Final message update
      if (messageUpdate) {
        this._append(messageUpdate);
      } // Perform concrete-hasher logic


      const hash = this._doFinalize();

      return hash;
    }

  }

  const X32WordArray = WordArray;
  /**
   * A 64-bit word.
   */

  class X64Word extends Base {
    /**
     * Initializes a newly created 64-bit word.
     *
     * @param {number} high The high 32 bits.
     * @param {number} low The low 32 bits.
     *
     * @example
     *
     *     let x64Word = new X64Word(0x00010203, 0x04050607);
     */
    constructor(high, low) {
      super();
      this.high = high;
      this.low = low;
    }

  }
  /**
   * An array of 64-bit words.
   *
   * @property {Array} words The array of CryptoJSW.x64.Word objects.
   * @property {number} sigBytes The number of significant bytes in this word array.
   */

  class X64WordArray extends Base {
    /**
     * Initializes a newly created word array.
     *
     * @param {Array} words (Optional) An array of CryptoJSW.x64.Word objects.
     * @param {number} sigBytes (Optional) The number of significant bytes in the words.
     *
     * @example
     *
     *     let wordArray = new X64WordArray();
     *
     *     let wordArray = new X64WordArray([
     *         new x64Word(0x00010203, 0x04050607),
     *         new x64Word(0x18191a1b, 0x1c1d1e1f)
     *     ]);
     *
     *     let wordArray = new X64WordArray([
     *         new x64Word(0x00010203, 0x04050607),
     *         new x64Word(0x18191a1b, 0x1c1d1e1f)
     *     ], 10);
     */
    constructor(words = [], sigBytes = words.length * 8) {
      super();
      this.words = words;
      this.sigBytes = sigBytes;
    }
    /**
     * Converts this 64-bit word array to a 32-bit word array.
     *
     * @return {CryptoJSW.lib.WordArray} This word array's data as a 32-bit word array.
     *
     * @example
     *
     *     let x32WordArray = x64WordArray.toX32();
     */


    toX32() {
      // Shortcuts
      const x64Words = this.words;
      const x64WordsLength = x64Words.length; // Convert

      const x32Words = [];

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

      return new X32WordArray(x32Words, this.sigBytes);
    }
    /**
     * Creates a copy of this word array.
     *
     * @return {X64WordArray} The clone.
     *
     * @example
     *
     *     let clone = x64WordArray.clone();
     */


    clone() {
      const clone = super.clone.call(this); // Clone "words" array

      clone.words = this.words.slice(0);
      const {
        words
      } = clone; // Clone each X64Word object

      const wordsLength = words.length;

      for (let i = 0; i < wordsLength; i++) {
        words[i] = words[i].clone();
      }

      return clone;
    }

  }

  function _defineProperty(obj, key, value) {
    if (key in obj) {
      Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
      });
    } else {
      obj[key] = value;
    }

    return obj;
  }

  const parseLoop = (base64Str, base64StrLength, reverseMap) => {
    const words = [];
    let nBytes = 0;

    for (let i = 0; i < base64StrLength; i++) {
      if (i % 4) {
        const bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << i % 4 * 2;
        const bits2 = reverseMap[base64Str.charCodeAt(i)] >>> 6 - i % 4 * 2;
        const bitsCombined = bits1 | bits2;
        words[nBytes >>> 2] |= bitsCombined << 24 - nBytes % 4 * 8;
        nBytes++;
      }
    }

    return new WordArray(words, nBytes);
  };
  /**
   * Base64 encoding strategy.
   */


  const Base64 = {
    /**
     * Converts a word array to a Base64 string.
     *
     * @param {WordArray} wordArray The word array.
     *
     * @return {string} The Base64 string.
     *
     * @static
     *
     * @example
     *
     *     const base64String = CryptoJSW.enc.Base64.stringify(wordArray);
     */
    stringify(wordArray) {
      // Shortcuts
      const {
        words,
        sigBytes
      } = wordArray;
      const map = this._map; // Clamp excess bits

      wordArray.clamp(); // Convert

      let base64 = ''; // the following implementation is referred from https://gist.github.com/jonleighton/958841

      const byteRemainder = sigBytes % 3;
      const mainLength = sigBytes - byteRemainder;
      let a, b, c, d;
      let chunk; // Main loop deals with bytes in chunks of 3

      for (let i = 0; i < mainLength; i = i + 3) {
        const byte1 = this.getByteByIndex(words, i);
        const byte2 = this.getByteByIndex(words, i + 1);
        const byte3 = this.getByteByIndex(words, i + 2); // Combine the three bytes into a single integer

        chunk = byte1 << 16 | byte2 << 8 | byte3; // Use bitmasks to extract 6-bit segments from the triplet

        a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18

        b = (chunk & 258048) >> 12; // 258048   = (2^6 - 1) << 12

        c = (chunk & 4032) >> 6; // 4032     = (2^6 - 1) << 6

        d = chunk & 63; // 63       = 2^6 - 1
        // Convert the raw binary segments to the appropriate ASCII encoding

        base64 += map[a] + map[b] + map[c] + map[d];
      } // Deal with the remaining bytes and padding


      if (byteRemainder == 1) {
        chunk = this.getByteByIndex(words, mainLength);
        a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2
        // Set the 4 least significant bits to zero

        b = (chunk & 3) << 4; // 3   = 2^2 - 1

        base64 += map[a] + map[b] + '==';
      } else if (byteRemainder == 2) {
        chunk = this.getByteByIndex(words, mainLength) << 8 | this.getByteByIndex(words, mainLength + 1);
        a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10

        b = (chunk & 1008) >> 4; // 1008  = (2^6 - 1) << 4
        // Set the 2 least significant bits to zero

        c = (chunk & 15) << 2; // 15    = 2^4 - 1

        base64 += map[a] + map[b] + map[c] + '=';
      }

      return base64;
    },

    getByteByIndex(words, index) {
      return words[index >>> 2] >>> 24 - index % 4 * 8 & 0xff;
    },

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

      if (!reverseMap) {
        this._reverseMap = [];
        reverseMap = this._reverseMap;

        for (let j = 0; j < map.length; j++) {
          reverseMap[map.charCodeAt(j)] = j;
        }
      } // Ignore padding


      const paddingChar = map.charAt(64);

      if (paddingChar) {
        const paddingIndex = base64Str.indexOf(paddingChar);

        if (paddingIndex !== -1) {
          base64StrLength = paddingIndex;
        }
      } // Convert


      return parseLoop(base64Str, base64StrLength, reverseMap);
    },

    _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
  };

  /**
   * Decode Base64 encoded .wasm bytes
   *
   * @param compressedBase64Bytes Base64-encoded pako-compressed .wasm bytes
   * @return {Uint8Array|*} .wasm bytes, this is intended to be used by WebAssembly.instantiate
   */

  const generateWasmBytes = function (compressedBase64Bytes) {
    function charCodeAt(c) {
      return c.charCodeAt(0);
    }

    let compressedBytes;

    if (typeof atob === 'function') {
      // Browser case
      compressedBytes = new Uint8Array(atob(compressedBase64Bytes).split('').map(charCodeAt));
    } else {
      compressedBytes = require('buffer').Buffer.from(compressedBase64Bytes, 'base64');
    }

    return pako__default["default"].inflate(compressedBytes);
  };
  /**
   * Load wasm bytes by WebAssembly.instantiate. Note this is async as WebAssembly.instantiate is async.
   * The async WebAssembly.instantiate is recommended instead of its sync variant WebAssembly.instance
   *
   * @param wasmBytes .wasm file bytes
   * @param imports configs for WebAssembly.instantiate, this is related to the generated glue code
   * @return {Promise<WebAssembly.Exports>} the generated WebAssembly target
   */

  const loadWasm = async function (wasmBytes, imports) {
    if (typeof WebAssembly !== 'object' || typeof WebAssembly.instantiate !== 'function') {
      throw new Error('WebAssembly is not supported.');
    }

    const loadResult = await WebAssembly.instantiate(wasmBytes, imports);
    return loadResult.instance.exports;
  };
  /**
   * An async function to load all existing WebAssembly modules. Please note that this only need to be called once.
   */

  const loadAllWasm = async function () {
    await Promise.allSettled(Object.values(index.algo).map(algo => {
      if (!algo.loadWasm) {
        return;
      }

      return algo.loadWasm();
    }));
  };

  const wasmBytes$b = generateWasmBytes('[encoded data, 10532 characters]');

  function md5Wasm(wasm) {
    let cachegetUint32Memory0 = null;

    function getUint32Memory0() {
      if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) {
        cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer);
      }

      return cachegetUint32Memory0;
    }

    let WASM_VECTOR_LEN = 0;

    function passArray32ToWasm0(arg, malloc) {
      const ptr = malloc(arg.length * 4);
      getUint32Memory0().set(arg, ptr / 4);
      WASM_VECTOR_LEN = arg.length;
      return ptr;
    }
    /**
     * @param {number} doFlush
     * @param {Uint32Array} hashWords
     * @param {Uint32Array} dataWords
     * @param {number} dataSigBytes
     * @param {number} blockSize
     * @param {number} minBufferSize
     * @returns {number}
     */


    function md5Process(doFlush, hashWords, dataWords, dataSigBytes, blockSize, minBufferSize) {
      try {
        var ptr0 = passArray32ToWasm0(hashWords, wasm.__wbindgen_malloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        var ret = wasm.md5Process(doFlush, ptr0, len0, ptr1, len1, dataSigBytes, blockSize, minBufferSize);
        return ret >>> 0;
      } finally {
        hashWords.set(getUint32Memory0().subarray(ptr0 / 4, ptr0 / 4 + len0));

        wasm.__wbindgen_free(ptr0, len0 * 4);
      }
    }

    return {
      md5Process: md5Process
    };
  }

  /**
   * MD5 hash algorithm.
   */

  class MD5Algo extends Hasher {
    static async loadWasm() {
      if (MD5Algo.wasm) {
        return MD5Algo.wasm;
      }

      MD5Algo.wasm = await loadWasm(wasmBytes$b);
      return MD5Algo.wasm;
    }

    async loadWasm() {
      return MD5Algo.loadWasm();
    }

    _doReset() {
      this._hash = new WordArray([0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476]);
    }

    _process(doFlush) {
      if (!MD5Algo.wasm) {
        throw new Error('WASM is not loaded yet. \'MD5Algo.loadWasm\' should be called first');
      } // Shortcuts


      const data = this._data;
      const dataWords = data.words;
      const dataSigBytes = data.sigBytes;
      const blockSize = this.blockSize;
      const H = this._hash.words;
      const H_array = new Uint32Array(4);
      H_array[0] = H[0];
      H_array[1] = H[1];
      H_array[2] = H[2];
      H_array[3] = H[3];
      const nWordsReady = md5Wasm(MD5Algo.wasm).md5Process(doFlush ? 1 : 0, H_array, dataWords, dataSigBytes, blockSize, this._minBufferSize); // Count bytes ready

      const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
      H[0] = H_array[0];
      H[1] = H_array[1];
      H[2] = H_array[2];
      H[3] = H_array[3];
      let processedWords;

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


      return new WordArray(processedWords, nBytesReady);
    }
    /* eslint-ensable no-param-reassign */


    _doFinalize() {
      // Shortcuts
      const data = this._data;
      const dataWords = data.words;
      const nBitsTotal = this._nDataBytes * 8;
      const nBitsLeft = data.sigBytes * 8; // Add padding

      dataWords[nBitsLeft >>> 5] |= 0x80 << 24 - nBitsLeft % 32;
      const nBitsTotalH = Math.floor(nBitsTotal / 0x100000000);
      const 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


      const hash = this._hash;
      const H = hash.words; // Swap endian

      for (let i = 0; i < 4; i++) {
        // Shortcut
        const 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() {
      const clone = super.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
   *
   *     const hash = CryptoJSW.MD5('message');
   *     const hash = CryptoJSW.MD5(wordArray);
   */

  _defineProperty(MD5Algo, "wasm", null);

  _defineProperty(MD5Algo, "outputSize", 128 / 8);

  const MD5 = Hasher._createHelper(MD5Algo);
  /**
   * 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
   *
   *     const hmac = CryptoJSW.HmacMD5(message, key);
   */

  const HmacMD5 = Hasher._createHmacHelper(MD5Algo);

  /**
   * This key derivation function is meant to conform with EVP_BytesToKey.
   * www.openssl.org/docs/crypto/EVP_BytesToKey.html
   */

  class EvpKDFAlgo extends Base {
    static async loadWasm() {
      return MD5Algo.loadWasm();
    }

    async loadWasm() {
      return EvpKDFAlgo.loadWasm();
    }
    /**
     * Initializes a newly created key derivation function.
     *
     * @param {Object} cfg (Optional) The configuration options to use for the derivation.
     *
     * @example
     *
     *     const kdf = new EvpKDF();
     *     const kdf = new EvpKDF({ keySize: 8 });
     *     const kdf = new EvpKDF({ keySize: 8, iterations: 1000 });
     */


    constructor(cfg) {
      super();
      /**
       * 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
       */

      this.cfg = Object.assign(new Base(), {
        keySize: 128 / 32,
        hasher: MD5Algo,
        iterations: 1
      }, 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
     *
     *     const key = kdf.compute(password, salt);
     */


    compute(password, salt) {
      let block; // Shortcut

      const {
        cfg
      } = this; // Init hasher

      const hasher = new cfg.hasher(); // Initial values

      const derivedKey = new WordArray(); // Shortcuts

      const derivedKeyWords = derivedKey.words;
      const {
        keySize,
        iterations
      } = cfg; // Generate key

      while (derivedKeyWords.length < keySize) {
        if (block) {
          hasher.update(block);
        }

        block = hasher.update(password).finalize(salt);
        hasher.reset(); // Iterations

        for (let 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
   *
   *     const key = CryptoJSW.EvpKDF(password, salt);
   *     const key = CryptoJSW.EvpKDF(password, salt, { keySize: 8 });
   *     const key = CryptoJSW.EvpKDF(password, salt, { keySize: 8, iterations: 1000 });
   */

  const EvpKDF = (password, salt, cfg) => new EvpKDFAlgo(cfg).compute(password, salt);

  EvpKDF.loadWasm = async function () {
    return EvpKDFAlgo.loadWasm();
  };

  /**
   * PKCS #5/7 padding strategy.
   */

  const 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
     *
     *     CryptoJSW.pad.Pkcs7.pad(wordArray, 4);
     */
    pad(data, blockSize) {
      // Shortcut
      const blockSizeBytes = blockSize * 4; // Count padding bytes

      const nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; // Create padding word

      const paddingWord = nPaddingBytes << 24 | nPaddingBytes << 16 | nPaddingBytes << 8 | nPaddingBytes; // Create padding

      const paddingWords = [];

      for (let i = 0; i < nPaddingBytes; i += 4) {
        paddingWords.push(paddingWord);
      }

      const padding = new WordArray(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
     *
     *     CryptoJSW.pad.Pkcs7.unpad(wordArray);
     */
    unpad(data) {
      const _data = data; // Get number of padding bytes from last byte

      const nPaddingBytes = _data.words[_data.sigBytes - 1 >>> 2] & 0xff; // Remove padding

      _data.sigBytes -= nPaddingBytes;
    }

  };

  /**
   * 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.
   */

  class Cipher extends BufferedBlockAlgorithm {
    static get _ENC_XFORM_MODE() {
      return 1;
    }

    static get _DEC_XFORM_MODE() {
      return 2;
    }

    static get keySize() {
      return 128 / 32;
    }

    static get ivSize() {
      return 128 / 32;
    }
    /**
     * 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
     *
     *     const cipher = new Cipher(
     *       CryptoJSW.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray }
     *     );
     */


    constructor(xformMode, key, cfg) {
      super();
      this._ENC_XFORM_MODE = 1;
      this._DEC_XFORM_MODE = 2;
      this.keySize = 128 / 32;
      this.ivSize = 128 / 32;
      /**
       * Configuration options.
       *
       * @property {WordArray} iv The IV to use for this operation.
       */

      this.cfg = Object.assign(new Base(), cfg); // Store transform mode and key

      this._xformMode = xformMode;
      this._key = key; // Set initial values

      this.reset();
    }
    /**
     * 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
     *
     *     const cipher = CryptoJSW.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray });
     */


    static createEncryptor(key, cfg) {
      return new this(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
     *
     *     const cipher = CryptoJSW.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray });
     */


    static createDecryptor(key, cfg) {
      return new this(this._DEC_XFORM_MODE, key, cfg);
    }
    /**
     * 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
     *
     *     const AES = CryptoJSW.lib.Cipher._createHelper(CryptoJSW.algo.AES);
     */


    static _createHelper(SubCipher) {
      const selectCipherStrategy = key => {
        if (isString(key)) {
          return PasswordBasedCipher;
        }

        return SerializableCipher;
      };

      return {
        async loadWasm() {
          if (!SubCipher.wasm) {
            await SubCipher.loadWasm();
          } // the default hasher for most algorithms is md5, so we should load it here


          if (!MD5Algo.wasm) {
            await MD5Algo.loadWasm();
          }
        },

        encrypt(message, key, cfg) {
          return selectCipherStrategy(key).encrypt(SubCipher, message, key, cfg);
        },

        decrypt(ciphertext, key, cfg) {
          return selectCipherStrategy(key).decrypt(SubCipher, ciphertext, key, cfg);
        }

      };
    }
    /**
     * Resets this cipher to its initial state.
     *
     * @example
     *
     *     cipher.reset();
     */


    reset() {
      // Reset data buffer
      super.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
     *
     *     const encrypted = cipher.process('data');
     *     const encrypted = cipher.process(wordArray);
     */


    process(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
     *
     *     const encrypted = cipher.finalize();
     *     const encrypted = cipher.finalize('data');
     *     const encrypted = cipher.finalize(wordArray);
     */


    finalize(dataUpdate) {
      // Final data update
      if (dataUpdate) {
        this._append(dataUpdate);
      } // Perform concrete-cipher logic


      const finalProcessedData = this._doFinalize();

      return finalProcessedData;
    }

  }
  /**
   * Abstract base stream cipher template.
   *
   * @property {number} blockSize
   *
   *     The number of 32-bit words this cipher operates on. Default: 1 (32 bits)
   */

  class StreamCipher extends Cipher {
    constructor(...args) {
      super(...args);
      this.blockSize = 1;
    }

    _doFinalize() {
      // Process partial blocks
      const finalProcessedBlocks = this._process(!!'flush');

      return finalProcessedBlocks;
    }

  }
  /**
   * Abstract base block cipher mode template.
   */

  class BlockCipherMode extends Base {
    /**
     * Initializes a newly created mode.
     *
     * @param {Cipher} cipher A block cipher instance.
     * @param {Array} iv The IV words.
     *
     * @example
     *
     *     const mode = new BlockCipherMode(cipher, iv.words);
     */
    constructor(cipher, iv) {
      super();
      this._cipher = cipher;
      this._iv = iv;
    }
    /**
     * Creates this mode for encryption.
     *
     * @param {Cipher} cipher A block cipher instance.
     * @param {Array} iv The IV words.
     *
     * @static
     *
     * @example
     *
     *     const mode = CryptoJSW.mode.CBC.createEncryptor(cipher, iv.words);
     */


    static createEncryptor(cipher, iv) {
      return new this.Encryptor(cipher, iv);
    }
    /**
     * Creates this mode for decryption.
     *
     * @param {Cipher} cipher A block cipher instance.
     * @param {Array} iv The IV words.
     *
     * @static
     *
     * @example
     *
     *     const mode = CryptoJSW.mode.CBC.createDecryptor(cipher, iv.words);
     */


    static createDecryptor(cipher, iv) {
      return new this.Decryptor(cipher, iv);
    }

  }

  function xorBlock(words, offset, blockSize) {
    const _words = words;
    let block; // Shortcut

    const 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 (let i = 0; i < blockSize; i++) {
      _words[offset + i] ^= block[i];
    }
  }
  /**
   * Cipher Block Chaining mode.
   */

  /**
   * Abstract base CBC mode.
   */


  class CBC extends BlockCipherMode {}
  /**
   * CBC encryptor.
   */

  _defineProperty(CBC, "_name", 'CBC');

  CBC.Encryptor = class extends CBC {
    /**
     * 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(words, offset) {
      // Shortcuts
      const cipher = this._cipher;
      const {
        blockSize
      } = cipher; // 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 = class extends CBC {
    /**
     * 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(words, offset) {
      // Shortcuts
      const cipher = this._cipher;
      const {
        blockSize
      } = cipher; // Remember this block to use with next block

      const 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;
    }

  };
  /**
   * Abstract base block cipher template.
   *
   * @property {number} blockSize
   *
   *    The number of 32-bit words this cipher operates on. Default: 4 (128 bits)
   */

  class BlockCipher extends Cipher {
    constructor(xformMode, key, cfg) {
      /**
       * Configuration options.
       *
       * @property {Mode} mode The block mode to use. Default: CBC
       * @property {Padding} padding The padding strategy to use. Default: Pkcs7
       */
      super(xformMode, key, Object.assign({
        mode: CBC,
        padding: Pkcs7
      }, cfg));
      this.blockSize = 128 / 32;
    }

    reset() {
      let modeCreator; // Reset cipher

      super.reset.call(this); // Shortcuts

      const {
        cfg
      } = this;
      const {
        iv,
        mode
      } = cfg; // Reset block mode

      if (this._xformMode === this.constructor._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;
        }

      this.modeProcessBlock = undefined;
      this._mode = modeCreator.call(mode, this, iv && iv.words);
      this._mode.__creator = modeCreator;
    }

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

    _doFinalize() {
      let finalProcessedBlocks; // Shortcut

      const {
        padding
      } = this.cfg; // Finalize

      if (this._xformMode === this.constructor._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;
    }

  }
  /**
   * 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.
   */

  class CipherParams extends Base {
    /**
     * Initializes a newly created cipher params object.
     *
     * @param {Object} cipherParams An object with any of the possible cipher parameters.
     *
     * @example
     *
     *     let cipherParams = new CipherParams({
     *         ciphertext: ciphertextWordArray,
     *         key: keyWordArray,
     *         iv: ivWordArray,
     *         salt: saltWordArray,
     *         algorithm: CryptoJSW.algo.AES,
     *         mode: CryptoJSW.mode.CBC,
     *         padding: CryptoJSW.pad.PKCS7,
     *         blockSize: 4,
     *         formatter: CryptoJSW.format.OpenSSL
     *     });
     */
    constructor(cipherParams) {
      super();
      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
     *
     *     let string = cipherParams + '';
     *     let string = cipherParams.toString();
     *     let string = cipherParams.toString(CryptoJSW.format.OpenSSL);
     */


    toString(formatter) {
      return (formatter || this.formatter).stringify(this);
    }

  }
  /**
   * OpenSSL formatting strategy.
   */

  const OpenSSLFormatter = {
    /**
     * 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
     *
     *     let openSSLString = CryptoJSW.format.OpenSSL.stringify(cipherParams);
     */
    stringify(cipherParams) {
      let wordArray; // Shortcuts

      const {
        ciphertext,
        salt
      } = cipherParams; // Format

      if (salt) {
        wordArray = new WordArray([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
     *
     *     let cipherParams = CryptoJSW.format.OpenSSL.parse(openSSLString);
     */
    parse(openSSLStr) {
      let salt; // Parse base64

      const ciphertext = Base64.parse(openSSLStr); // Shortcut

      const ciphertextWords = ciphertext.words; // Test for salt

      if (ciphertextWords[0] === 0x53616c74 && ciphertextWords[1] === 0x65645f5f) {
        // Extract salt
        salt = new WordArray(ciphertextWords.slice(2, 4)); // Remove salt from ciphertext

        ciphertextWords.splice(0, 4);
        ciphertext.sigBytes -= 16;
      }

      return new CipherParams({
        ciphertext,
        salt
      });
    }

  };
  /**
   * A cipher wrapper that returns ciphertext as a serializable cipher params object.
   */

  class SerializableCipher extends Base {
    /**
     * 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.
     * @param {Object} wasm The initialed wasm module
     *
     * @return {CipherParams} A cipher params object.
     *
     * @static
     *
     * @example
     *
     *     let ciphertextParams = CryptoJSW.lib.SerializableCipher
     *       .encrypt(CryptoJSW.algo.AES, message, key);
     *     let ciphertextParams = CryptoJSW.lib.SerializableCipher
     *       .encrypt(CryptoJSW.algo.AES, message, key, { iv: iv });
     *     let ciphertextParams = CryptoJSW.lib.SerializableCipher
     *       .encrypt(CryptoJSW.algo.AES, message, key, { iv: iv, format: CryptoJSW.format.OpenSSL });
     */
    static encrypt(cipher, message, key, cfg, wasm) {
      // Apply config defaults
      const _cfg = Object.assign(new Base(), this.cfg, cfg); // Encrypt


      const encryptor = cipher.createEncryptor(key, _cfg, wasm);
      const ciphertext = encryptor.finalize(message); // Shortcut

      const cipherCfg = encryptor.cfg; // Create and return serializable cipher params

      return new CipherParams({
        ciphertext,
        key,
        iv: cipherCfg.iv,
        algorithm: cipher,
        mode: cipherCfg.mode,
        padding: cipherCfg.padding,
        blockSize: encryptor.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
     *
     *     let plaintext = CryptoJSW.lib.SerializableCipher
     *       .decrypt(CryptoJSW.algo.AES, formattedCiphertext, key,
     *         { iv: iv, format: CryptoJSW.format.OpenSSL });
     *     let plaintext = CryptoJSW.lib.SerializableCipher
     *       .decrypt(CryptoJSW.algo.AES, ciphertextParams, key,
     *         { iv: iv, format: CryptoJSW.format.OpenSSL });
     */


    static decrypt(cipher, ciphertext, key, cfg) {
      let _ciphertext = ciphertext; // Apply config defaults

      const _cfg = Object.assign(new Base(), this.cfg, cfg); // Convert string to CipherParams


      _ciphertext = this._parse(_ciphertext, _cfg.format); // Decrypt

      const 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
     *
     *     let ciphertextParams = CryptoJSW.lib.SerializableCipher
     *       ._parse(ciphertextStringOrParams, format);
     */


    static _parse(ciphertext, format) {
      if (isString(ciphertext)) {
        return format.parse(ciphertext, this);
      }

      return ciphertext;
    }

  }
  /**
   * Configuration options.
   *
   * @property {Formatter} format
   *
   *    The formatting strategy to convert cipher param objects to and from a string.
   *    Default: OpenSSL
   */

  SerializableCipher.cfg = Object.assign(new Base(), {
    format: OpenSSLFormatter
  });
  /**
   * OpenSSL key derivation function.
   */

  const OpenSSLKdf = {
    async loadWasm() {
      // the default hasher for OpenSSLKdf is MD5
      return MD5Algo.loadWasm();
    },

    /**
     * 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
     *
     *     let derivedParams = CryptoJSW.kdf.OpenSSL.execute('Password', 256/32, 128/32);
     *     let derivedParams = CryptoJSW.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
     */
    execute(password, keySize, ivSize, salt, hasher) {
      let _salt = salt; // Generate random salt

      if (!_salt) {
        _salt = WordArray.random(64 / 8);
      } // Derive key and IV


      let key;

      if (!hasher) {
        key = new EvpKDFAlgo({
          keySize: keySize + ivSize
        }).compute(password, _salt);
      } else {
        key = new EvpKDFAlgo({
          keySize: keySize + ivSize,
          hasher: hasher
        }).compute(password, salt);
      } // Separate key and IV


      const iv = new WordArray(key.words.slice(keySize), ivSize * 4);
      key.sigBytes = keySize * 4; // Return params

      return new CipherParams({
        key,
        iv,
        salt: _salt
      });
    }

  };
  /**
   * A serializable cipher wrapper that derives the key from a password,
   * and returns ciphertext as a serializable cipher params object.
   */

  class PasswordBasedCipher extends SerializableCipher {
    static async loadWasm() {
      // the default hasher for kdf is MD5
      return MD5Algo.loadWasm();
    }

    async loadWasm() {
      return PasswordBasedCipher.loadWasm();
    }
    /**
     * 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
     *
     *     let ciphertextParams = CryptoJSW.lib.PasswordBasedCipher
     *       .encrypt(CryptoJSW.algo.AES, message, 'password');
     *     let ciphertextParams = CryptoJSW.lib.PasswordBasedCipher
     *       .encrypt(CryptoJSW.algo.AES, message, 'password', { format: CryptoJSW.format.OpenSSL });
     */


    static encrypt(cipher, message, password, cfg, wasm) {
      // Apply config defaults
      const _cfg = Object.assign(new Base(), this.cfg, cfg); // Derive key and other params


      const derivedParams = _cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, _cfg.salt, _cfg.hasher); // Add IV to config


      _cfg.iv = derivedParams.iv; // Encrypt

      const ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, _cfg, wasm); // 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
     *
     *     let plaintext = CryptoJSW.lib.PasswordBasedCipher
     *       .decrypt(CryptoJSW.algo.AES, formattedCiphertext, 'password',
     *         { format: CryptoJSW.format.OpenSSL });
     *     let plaintext = CryptoJSW.lib.PasswordBasedCipher
     *       .decrypt(CryptoJSW.algo.AES, ciphertextParams, 'password',
     *         { format: CryptoJSW.format.OpenSSL });
     */


    static decrypt(cipher, ciphertext, password, cfg) {
      let _ciphertext = ciphertext; // Apply config defaults

      const _cfg = Object.assign(new Base(), this.cfg, cfg); // Convert string to CipherParams


      _ciphertext = this._parse(_ciphertext, _cfg.format); // Derive key and other params

      const derivedParams = _cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, _ciphertext.salt, _cfg.hasher); // Add IV to config


      _cfg.iv = derivedParams.iv; // Decrypt

      const plaintext = SerializableCipher.decrypt.call(this, cipher, _ciphertext, derivedParams.key, _cfg);
      return plaintext;
    }

  }
  /**
   * Configuration options.
   *
   * @property {KDF} kdf
   *     The key derivation function to use to generate a key and IV from a password.
   *     Default: OpenSSL
   */

  PasswordBasedCipher.cfg = Object.assign(SerializableCipher.cfg, {
    kdf: OpenSSLKdf
  });

  const swapEndian = word => word << 8 & 0xff00ff00 | word >>> 8 & 0x00ff00ff;
  /**
   * UTF-16 BE encoding strategy.
   */


  const 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
     *
     *     const utf16String = CryptoJSW.enc.Utf16.stringify(wordArray);
     */
    stringify(wordArray) {
      // Shortcuts
      const {
        words,
        sigBytes
      } = wordArray; // Convert

      const utf16Chars = [];

      for (let i = 0; i < sigBytes; i += 2) {
        const 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
     *
     *     const wordArray = CryptoJSW.enc.Utf16.parse(utf16String);
     */
    parse(utf16Str) {
      // Shortcut
      const utf16StrLength = utf16Str.length; // Convert

      const words = [];

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

      return new WordArray(words, utf16StrLength * 2);
    }

  };
  const Utf16 = Utf16BE;
  /**
   * UTF-16 LE encoding strategy.
   */

  const 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
     *
     *     const utf16Str = CryptoJSW.enc.Utf16LE.stringify(wordArray);
     */
    stringify(wordArray) {
      // Shortcuts
      const {
        words,
        sigBytes
      } = wordArray; // Convert

      const utf16Chars = [];

      for (let i = 0; i < sigBytes; i += 2) {
        const 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
     *
     *     const wordArray = CryptoJSW.enc.Utf16LE.parse(utf16Str);
     */
    parse(utf16Str) {
      // Shortcut
      const utf16StrLength = utf16Str.length; // Convert

      const words = [];

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

      return new WordArray(words, utf16StrLength * 2);
    }

  };

  const wasmBytes$a = generateWasmBytes('[encoded data, 8704 characters]');

  function sha1Wasm(wasm) {
    let cachegetUint32Memory0 = null;

    function getUint32Memory0() {
      if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) {
        cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer);
      }

      return cachegetUint32Memory0;
    }

    let WASM_VECTOR_LEN = 0;

    function passArray32ToWasm0(arg, malloc) {
      const ptr = malloc(arg.length * 4);
      getUint32Memory0().set(arg, ptr / 4);
      WASM_VECTOR_LEN = arg.length;
      return ptr;
    }
    /**
     * @param {number} doFlush
     * @param {Uint32Array} hashWords
     * @param {Uint32Array} dataWords
     * @param {number} dataSigBytes
     * @param {number} blockSize
     * @param {number} minBufferSize
     * @returns {number}
     */


    function doCrypt(doFlush, hashWords, dataWords, dataSigBytes, blockSize, minBufferSize) {
      try {
        var ptr0 = passArray32ToWasm0(hashWords, wasm.__wbindgen_malloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        var ret = wasm.doCrypt(doFlush, ptr0, len0, ptr1, len1, dataSigBytes, blockSize, minBufferSize);
        return ret >>> 0;
      } finally {
        hashWords.set(getUint32Memory0().subarray(ptr0 / 4, ptr0 / 4 + len0));

        wasm.__wbindgen_free(ptr0, len0 * 4);
      }
    }

    return {
      doCrypt: doCrypt
    };
  }

  /**
   * SHA-1 hash algorithm.
   */

  class SHA1Algo extends Hasher {
    static async loadWasm() {
      if (SHA1Algo.wasm) {
        return SHA1Algo.wasm;
      }

      SHA1Algo.wasm = await loadWasm(wasmBytes$a);
      return SHA1Algo.wasm;
    }

    async loadWasm() {
      return SHA1Algo.loadWasm();
    }

    _doReset() {
      this._hash = new WordArray([0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]);
    }

    _process(doFlush) {
      if (!SHA1Algo.wasm) {
        throw new Error('WASM is not loaded yet. \'SHA1Algo.loadWasm\' should be called first');
      } // Shortcuts


      const data = this._data;
      const dataWords = data.words;
      const dataSigBytes = data.sigBytes;
      const blockSize = this.blockSize;
      const H = this._hash.words;
      const H_array = new Uint32Array(5);
      H_array[0] = H[0];
      H_array[1] = H[1];
      H_array[2] = H[2];
      H_array[3] = H[3];
      H_array[4] = H[4];
      const nWordsReady = sha1Wasm(SHA1Algo.wasm).doCrypt(doFlush ? 1 : 0, H_array, dataWords, dataSigBytes, blockSize, this._minBufferSize); // Count bytes ready

      const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
      H[0] = H_array[0];
      H[1] = H_array[1];
      H[2] = H_array[2];
      H[3] = H_array[3];
      H[4] = H_array[4];
      let processedWords;

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


      return new WordArray(processedWords, nBytesReady);
    }

    _doFinalize() {
      // Shortcuts
      const data = this._data;
      const dataWords = data.words;
      const nBitsTotal = this._nDataBytes * 8;
      const 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() {
      const clone = super.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
   *
   *     const hash = CryptoJSW.SHA1('message');
   *     const hash = CryptoJSW.SHA1(wordArray);
   */

  _defineProperty(SHA1Algo, "wasm", null);

  _defineProperty(SHA1Algo, "outputSize", 160 / 8);

  const SHA1 = Hasher._createHelper(SHA1Algo);
  /**
   * 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
   *
   *     const hmac = CryptoJSW.HmacSHA1(message, key);
   */

  const HmacSHA1 = Hasher._createHmacHelper(SHA1Algo);

  const wasmBytes$9 = generateWasmBytes('[encoded data, 9556 characters]');

  function sha256Wasm(wasm) {
    let cachegetUint32Memory0 = null;

    function getUint32Memory0() {
      if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) {
        cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer);
      }

      return cachegetUint32Memory0;
    }

    let WASM_VECTOR_LEN = 0;

    function passArray32ToWasm0(arg, malloc) {
      const ptr = malloc(arg.length * 4);
      getUint32Memory0().set(arg, ptr / 4);
      WASM_VECTOR_LEN = arg.length;
      return ptr;
    }
    /**
     * @param {number} doFlush
     * @param {Uint32Array} dataWords
     * @param {number} dataSigBytes
     * @param {number} blockSize
     * @param {Uint32Array} hash
     * @param {number} minBufferSize
     * @returns {number}
     */


    function doCrypt(doFlush, dataWords, dataSigBytes, blockSize, hash, minBufferSize) {
      try {
        var ptr0 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(hash, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        var ret = wasm.doCrypt(doFlush, ptr0, len0, dataSigBytes, blockSize, ptr1, len1, minBufferSize);
        return ret >>> 0;
      } finally {
        hash.set(getUint32Memory0().subarray(ptr1 / 4, ptr1 / 4 + len1));

        wasm.__wbindgen_free(ptr1, len1 * 4);
      }
    }

    return {
      doCrypt: doCrypt
    };
  }

  const H = [1779033703, -1150833019, 1013904242, -1521486534, 1359893119, -1694144372, 528734635, 1541459225];
  /**
   * SHA-256 hash algorithm.
   */

  class SHA256Algo extends Hasher {
    static async loadWasm() {
      if (SHA256Algo.wasm) {
        return SHA256Algo.wasm;
      }

      SHA256Algo.wasm = await loadWasm(wasmBytes$9);
      return SHA256Algo.wasm;
    }

    async loadWasm() {
      return SHA256Algo.loadWasm();
    }

    _doReset() {
      this._hash = new WordArray(H.slice(0));
    }

    _process(doFlush) {
      if (!SHA256Algo.wasm) {
        throw new Error('WASM is not loaded yet. \'SHA256Algo.loadWasm\' should be called first');
      } // Shortcuts


      const data = this._data;
      const dataWords = data.words;
      const dataSigBytes = data.sigBytes;
      const blockSize = this.blockSize;
      const H = this._hash.words;
      const H_array = new Uint32Array(8);

      for (let i = 0; i < 8; i++) {
        H_array[i] = H[i];
      }

      const nWordsReady = sha256Wasm(SHA256Algo.wasm).doCrypt(doFlush ? 1 : 0, dataWords, dataSigBytes, blockSize, H_array, this._minBufferSize); // Count bytes ready

      const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);

      for (let i = 0; i < 8; i++) {
        H[i] = H_array[i];
      }

      let processedWords;

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


      return new WordArray(processedWords, nBytesReady);
    }

    _doFinalize() {
      // Shortcuts
      const data = this._data;
      const dataWords = data.words;
      const nBitsTotal = this._nDataBytes * 8;
      const 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() {
      const clone = super.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
   *
   *     const hash = CryptoJSW.SHA256('message');
   *     const hash = CryptoJSW.SHA256(wordArray);
   */

  _defineProperty(SHA256Algo, "wasm", null);

  _defineProperty(SHA256Algo, "outputSize", 256 / 8);

  const SHA256 = Hasher._createHelper(SHA256Algo);
  /**
   * 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
   *
   *     const hmac = CryptoJSW.HmacSHA256(message, key);
   */

  const HmacSHA256 = Hasher._createHmacHelper(SHA256Algo);

  /**
   * SHA-224 hash algorithm.
   */

  class SHA224Algo extends SHA256Algo {
    static async loadWasm() {
      return SHA256Algo.loadWasm();
    }

    async loadWasm() {
      return SHA224Algo.loadWasm();
    }

    _doReset() {
      this._hash = new WordArray([0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4]);
    }

    _doFinalize() {
      const hash = super._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
   *
   *     const hash = CryptoJSW.SHA224('message');
   *     const hash = CryptoJSW.SHA224(wordArray);
   */

  _defineProperty(SHA224Algo, "outputSize", 224 / 8);

  const SHA224 = SHA256Algo._createHelper(SHA224Algo);
  /**
   * 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
   *
   *     const hmac = CryptoJSW.HmacSHA224(message, key);
   */

  const HmacSHA224 = SHA256Algo._createHmacHelper(SHA224Algo);

  const wasmBytes$8 = generateWasmBytes('[encoded data, 10520 characters]');

  function sha512Wasm(wasm) {
    let cachegetUint32Memory0 = null;

    function getUint32Memory0() {
      if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) {
        cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer);
      }

      return cachegetUint32Memory0;
    }

    let WASM_VECTOR_LEN = 0;

    function passArray32ToWasm0(arg, malloc) {
      const ptr = malloc(arg.length * 4);
      getUint32Memory0().set(arg, ptr / 4);
      WASM_VECTOR_LEN = arg.length;
      return ptr;
    }
    /**
     * @param {number} nWordsReady
     * @param {number} blockSize
     * @param {Uint32Array} dataWords
     * @param {Uint32Array} hash
     */


    function doCrypt(nWordsReady, blockSize, dataWords, hash) {
      try {
        var ptr0 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(hash, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        wasm.doCrypt(nWordsReady, blockSize, ptr0, len0, ptr1, len1);
      } finally {
        hash.set(getUint32Memory0().subarray(ptr1 / 4, ptr1 / 4 + len1));

        wasm.__wbindgen_free(ptr1, len1 * 4);
      }
    }

    return {
      doCrypt: doCrypt
    };
  }

  /**
   * SHA-512 hash algorithm.
   */

  class SHA512Algo extends Hasher {
    static async loadWasm() {
      if (SHA512Algo.wasm) {
        return SHA512Algo.wasm;
      }

      SHA512Algo.wasm = await loadWasm(wasmBytes$8);
      return SHA512Algo.wasm;
    }

    async loadWasm() {
      return SHA512Algo.loadWasm();
    }

    constructor() {
      super();
      this.blockSize = 1024 / 32;
    }

    _doReset() {
      this._hash = new X64WordArray([new X64Word(0x6a09e667, 0xf3bcc908), new X64Word(0xbb67ae85, 0x84caa73b), new X64Word(0x3c6ef372, 0xfe94f82b), new X64Word(0xa54ff53a, 0x5f1d36f1), new X64Word(0x510e527f, 0xade682d1), new X64Word(0x9b05688c, 0x2b3e6c1f), new X64Word(0x1f83d9ab, 0xfb41bd6b), new X64Word(0x5be0cd19, 0x137e2179)]);
    }

    _process(doFlush) {
      if (!SHA512Algo.wasm) {
        throw new Error('WASM is not loaded yet. \'SHA512Algo.loadWasm\' should be called first');
      }

      let processedWords; // Shortcuts

      const data = this._data;
      const dataWords = data.words;
      const dataSigBytes = data.sigBytes;
      const blockSize = this.blockSize;
      const blockSizeBytes = blockSize * 4; // Count blocks ready

      let 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


      const nWordsReady = nBlocksReady * blockSize; // Count bytes ready

      const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); // Process blocks

      if (nWordsReady) {
        const H = this._hash.words;
        const H_array = new Uint32Array(16);

        for (let i = 0; i < 8; i++) {
          H_array[i * 2] = H[i].high;
          H_array[i * 2 + 1] = H[i].low;
        } // Perform concrete-algorithm logic


        sha512Wasm(SHA512Algo.wasm).doCrypt(nWordsReady, blockSize, dataWords, H_array);

        for (let i = 0; i < 8; i++) {
          H[i].high = H_array[i * 2];
          H[i].low = H_array[i * 2 + 1];
        } // Remove processed words


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


      return new WordArray(processedWords, nBytesReady);
    }

    _doFinalize() {
      // Shortcuts
      const data = this._data;
      const dataWords = data.words;
      const nBitsTotal = this._nDataBytes * 8;
      const 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


      const hash = this._hash.toX32(); // Return final computed hash


      return hash;
    }

    clone() {
      const clone = super.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
   *
   *     const hash = CryptoJSW.SHA512('message');
   *     const hash = CryptoJSW.SHA512(wordArray);
   */

  _defineProperty(SHA512Algo, "wasm", null);

  _defineProperty(SHA512Algo, "outputSize", 512 / 8);

  const SHA512 = Hasher._createHelper(SHA512Algo);
  /**
   * 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
   *
   *     const hmac = CryptoJSW.HmacSHA512(message, key);
   */

  const HmacSHA512 = Hasher._createHmacHelper(SHA512Algo);

  /**
   * SHA-384 hash algorithm.
   */

  class SHA384Algo extends SHA512Algo {
    static async loadWasm() {
      return SHA512Algo.loadWasm();
    }

    async loadWasm() {
      return SHA384Algo.loadWasm();
    }

    _doReset() {
      this._hash = new X64WordArray([new X64Word(0xcbbb9d5d, 0xc1059ed8), new X64Word(0x629a292a, 0x367cd507), new X64Word(0x9159015a, 0x3070dd17), new X64Word(0x152fecd8, 0xf70e5939), new X64Word(0x67332667, 0xffc00b31), new X64Word(0x8eb44a87, 0x68581511), new X64Word(0xdb0c2e0d, 0x64f98fa7), new X64Word(0x47b5481d, 0xbefa4fa4)]);
    }

    _doFinalize() {
      const hash = super._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
   *
   *     const hash = CryptoJSW.SHA384('message');
   *     const hash = CryptoJSW.SHA384(wordArray);
   */

  _defineProperty(SHA384Algo, "outputSize", 384 / 8);

  const SHA384 = SHA512Algo._createHelper(SHA384Algo);
  /**
   * 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
   *
   *     const hmac = CryptoJSW.HmacSHA384(message, key);
   */

  const HmacSHA384 = SHA512Algo._createHmacHelper(SHA384Algo);

  const wasmBytes$7 = generateWasmBytes('[encoded data, 10492 characters]');

  function sha3Wasm(wasm) {
    let cachegetUint32Memory0 = null;

    function getUint32Memory0() {
      if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) {
        cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer);
      }

      return cachegetUint32Memory0;
    }

    let WASM_VECTOR_LEN = 0;

    function passArray32ToWasm0(arg, malloc) {
      const ptr = malloc(arg.length * 4);
      getUint32Memory0().set(arg, ptr / 4);
      WASM_VECTOR_LEN = arg.length;
      return ptr;
    }
    /**
     * @param {number} doFlush
     * @param {Uint32Array} dataWords
     * @param {number} dataSigBytes
     * @param {number} blockSize
     * @param {Uint32Array} stateData
     * @param {number} minBufferSize
     * @returns {number}
     */


    function doCrypt(doFlush, dataWords, dataSigBytes, blockSize, stateData, minBufferSize) {
      try {
        var ptr0 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(stateData, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        var ret = wasm.doCrypt(doFlush, ptr0, len0, dataSigBytes, blockSize, ptr1, len1, minBufferSize);
        return ret >>> 0;
      } finally {
        stateData.set(getUint32Memory0().subarray(ptr1 / 4, ptr1 / 4 + len1));

        wasm.__wbindgen_free(ptr1, len1 * 4);
      }
    }

    return {
      doCrypt: doCrypt
    };
  }

  /**
   * SHA-3 hash algorithm.
   */

  class SHA3Algo extends Hasher {
    static async loadWasm() {
      if (SHA3Algo.wasm) {
        return SHA3Algo.wasm;
      }

      SHA3Algo.wasm = await loadWasm(wasmBytes$7);
      return SHA3Algo.wasm;
    }

    async loadWasm() {
      return SHA3Algo.loadWasm();
    }

    constructor(cfg) {
      /**
       * Configuration options.
       *
       * @property {number} outputLength
       *   The desired number of bits in the output hash.
       *   Only values permitted are: 224, 256, 384, 512.
       *   Default: 512
       */
      super(Object.assign({
        outputLength: 512
      }, cfg));
    }

    _doReset() {
      this._state = [];
      const state = this._state;

      for (let i = 0; i < 25; i++) {
        state[i] = new X64Word();
      }

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

    _process(doFlush) {
      if (!SHA3Algo.wasm) {
        throw new Error('WASM is not loaded yet. \'SHA3Algo.loadWasm\' should be called first');
      } // Shortcuts


      const data = this._data;
      const dataWords = data.words;
      const dataSigBytes = data.sigBytes;
      const blockSize = this.blockSize;
      const stateData = new Uint32Array(50);

      for (let i = 0; i < 25; i++) {
        stateData[i * 2] = this._state[i].high;
        stateData[i * 2 + 1] = this._state[i].low;
      }

      for (let i = 0; i < dataWords.length; i++) {
        if (!dataWords[i]) {
          dataWords[i] = 0;
        }
      }

      const nWordsReady = sha3Wasm(SHA3Algo.wasm).doCrypt(doFlush ? 1 : 0, dataWords, dataSigBytes, blockSize, stateData, this._minBufferSize); // Count bytes ready

      const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);

      for (let i = 0; i < 25; i++) {
        this._state[i].high = stateData[i * 2];
        this._state[i].low = stateData[i * 2 + 1];
      }

      let processedWords;

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


      return new WordArray(processedWords, nBytesReady);
    }

    _doFinalize() {
      // Shortcuts
      const data = this._data;
      const dataWords = data.words;
      const nBitsLeft = data.sigBytes * 8;
      const 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


      const state = this._state;
      const outputLengthBytes = this.cfg.outputLength / 8;
      const outputLengthLanes = outputLengthBytes / 8; // Squeeze

      const hashWords = [];

      for (let i = 0; i < outputLengthLanes; i++) {
        // Shortcuts
        const lane = state[i];
        let laneMsw = lane.high;
        let 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(hashWords, outputLengthBytes);
    }

    clone() {
      const clone = super.clone.call(this);
      clone._state = this._state.slice(0);
      const state = clone._state;

      for (let 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
   *
   *     const hash = CryptoJSW.SHA3('message');
   *     const hash = CryptoJSW.SHA3(wordArray);
   */

  _defineProperty(SHA3Algo, "wasm", null);

  const SHA3 = Hasher._createHelper(SHA3Algo);
  /**
   * 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
   *
   *     const hmac = CryptoJSW.HmacSHA3(message, key);
   */

  const HmacSHA3 = Hasher._createHmacHelper(SHA3Algo);

  function ripemd160Wasm(wasm) {
    let cachegetUint32Memory0 = null;

    function getUint32Memory0() {
      if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) {
        cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer);
      }

      return cachegetUint32Memory0;
    }

    let WASM_VECTOR_LEN = 0;

    function passArray32ToWasm0(arg, malloc) {
      const ptr = malloc(arg.length * 4);
      getUint32Memory0().set(arg, ptr / 4);
      WASM_VECTOR_LEN = arg.length;
      return ptr;
    }
    /**
    * @param {number} nWordsReady
    * @param {number} blockSize
    * @param {Uint32Array} dataWords
    * @param {Uint32Array} H
    */


    function doProcess(nWordsReady, blockSize, dataWords, H) {
      try {
        var ptr0 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(H, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        wasm.doProcess(nWordsReady, blockSize, ptr0, len0, ptr1, len1);
      } finally {
        H.set(getUint32Memory0().subarray(ptr1 / 4, ptr1 / 4 + len1));

        wasm.__wbindgen_free(ptr1, len1 * 4);
      }
    }

    return {
      doProcess: doProcess
    };
  }

  const wasmBytes$6 = generateWasmBytes('[encoded data, 10032 characters]');

  /**
   * RIPEMD160 hash algorithm.
   */

  class RIPEMD160Algo extends Hasher {
    static async loadWasm() {
      if (RIPEMD160Algo.wasm) {
        return RIPEMD160Algo.wasm;
      }

      RIPEMD160Algo.wasm = await loadWasm(wasmBytes$6);
      return RIPEMD160Algo.wasm;
    }

    async loadWasm() {
      return RIPEMD160Algo.loadWasm();
    }

    _doReset() {
      this._hash = new WordArray([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]);
    }

    _process(doFlush) {
      if (!RIPEMD160Algo.wasm) {
        throw new Error('WASM is not loaded yet. \'RIPEMD160Algo.loadWasm\' should be called first');
      }

      let processedWords; // Shortcuts

      const data = this._data;
      let dataWords = data.words;
      const dataSigBytes = data.sigBytes;
      const blockSize = this.blockSize;
      const blockSizeBytes = blockSize * 4;
      let H = this._hash.words; // Count blocks ready

      let 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


      const nWordsReady = nBlocksReady * blockSize; // Count bytes ready

      const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); // Process blocks

      if (nWordsReady) {
        if (dataWords.length < nWordsReady) {
          for (let i = dataWords.length; i < nWordsReady; i++) {
            dataWords[i] = 0;
          }
        }

        const H_Array = new Uint32Array(H); // Perform concrete-algorithm logic

        ripemd160Wasm(RIPEMD160Algo.wasm).doProcess(nWordsReady, blockSize, dataWords, H_Array);
        this._hash.words = Array.from(H_Array); // Remove processed words

        processedWords = dataWords.splice(0, nWordsReady); // write data back to this._data

        this._data.words = dataWords;
        data.sigBytes -= nBytesReady;
      } // Return processed words


      return new WordArray(processedWords, nBytesReady);
    }

    _doFinalize() {
      // Shortcuts
      const data = this._data;
      const dataWords = data.words;
      const nBitsTotal = this._nDataBytes * 8;
      const 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


      const hash = this._hash;
      const H = hash.words; // Swap endian

      for (let i = 0; i < 5; i++) {
        // Shortcut
        const 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() {
      const clone = super.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
   *
   *     const hash = CryptoJSW.RIPEMD160('message');
   *     const hash = CryptoJSW.RIPEMD160(wordArray);
   */

  _defineProperty(RIPEMD160Algo, "wasm", null);

  _defineProperty(RIPEMD160Algo, "outputSize", 160 / 8);

  const RIPEMD160 = Hasher._createHelper(RIPEMD160Algo);
  /**
   * 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
   *
   *     const hmac = CryptoJSW.HmacRIPEMD160(message, key);
   */

  const HmacRIPEMD160 = Hasher._createHmacHelper(RIPEMD160Algo);

  /**
   * Password-Based Key Derivation Function 2 algorithm.
   */

  class PBKDF2Algo extends Base {
    /**
     * Initializes a newly created key derivation function.
     *
     * @param {Object} cfg (Optional) The configuration options to use for the derivation.
     *
     * @example
     *
     *     const kdf = new CryptoJSW.algo.PBKDF2();
     *     const kdf = new CryptoJSW.algo.PBKDF2({ keySize: 8 });
     *     const kdf = new CryptoJSW.algo.PBKDF2({ keySize: 8, iterations: 1000 });
     */
    constructor(cfg) {
      super();
      /**
       * 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
       */

      this.cfg = Object.assign(new Base(), {
        keySize: 128 / 32,
        hasher: SHA256Algo,
        iterations: 250000
      }, cfg);
    }
    /**
     * SHA256 is the default hasher of pbkdf2.
     * With another hasher configured, user should call the corresponding loadWasm of the configured hasher.
     *
     * @returns {Promise<null>}
     */


    static async loadWasm() {
      return SHA256Algo.loadWasm();
    }

    async loadWasm() {
      return PBKDF2Algo.loadWasm();
    }
    /**
     * 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
     *
     *     const key = kdf.compute(password, salt);
     */


    compute(password, salt) {
      // Shortcut
      const {
        cfg
      } = this; // Init HMAC

      const hmac = new HMAC(cfg.hasher, password); // Initial values

      const derivedKey = new WordArray();
      const blockIndex = new WordArray([0x00000001]); // Shortcuts

      const derivedKeyWords = derivedKey.words;
      const blockIndexWords = blockIndex.words;
      const {
        keySize,
        iterations
      } = cfg; // Generate key

      while (derivedKeyWords.length < keySize) {
        const block = hmac.update(salt).finalize(blockIndex);
        hmac.reset(); // Shortcuts

        const blockWords = block.words;
        const blockWordsLength = blockWords.length; // Iterations

        let intermediate = block;

        for (let i = 1; i < iterations; i++) {
          intermediate = hmac.finalize(intermediate);
          hmac.reset(); // Shortcut

          const intermediateWords = intermediate.words; // XOR intermediate with block

          for (let 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
   *
   *     const key = CryptoJSW.PBKDF2(password, salt);
   *     const key = CryptoJSW.PBKDF2(password, salt, { keySize: 8 });
   *     const key = CryptoJSW.PBKDF2(password, salt, { keySize: 8, iterations: 1000 });
   */

  const PBKDF2 = (password, salt, cfg) => new PBKDF2Algo(cfg).compute(password, salt);

  function aesWasm(wasm) {
    let cachegetUint32Memory0 = null;

    function getUint32Memory0() {
      if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) {
        cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer);
      }

      return cachegetUint32Memory0;
    }

    let WASM_VECTOR_LEN = 0;

    function passArray32ToWasm0(arg, malloc) {
      const ptr = malloc(arg.length * 4);
      getUint32Memory0().set(arg, ptr / 4);
      WASM_VECTOR_LEN = arg.length;
      return ptr;
    }

    let cachegetInt32Memory0 = null;

    function getInt32Memory0() {
      if (cachegetInt32Memory0 === null || cachegetInt32Memory0.buffer !== wasm.memory.buffer) {
        cachegetInt32Memory0 = new Int32Array(wasm.memory.buffer);
      }

      return cachegetInt32Memory0;
    }

    function getArrayU32FromWasm0(ptr, len) {
      return getUint32Memory0().subarray(ptr / 4, ptr / 4 + len);
    }
    /**
    * @param {number} keySize
    * @param {Uint32Array} keyWords
    * @returns {Uint32Array}
    */


    function getKeySchedule(keySize, keyWords) {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        var ptr0 = passArray32ToWasm0(keyWords, wasm.__wbindgen_malloc);
        var len0 = WASM_VECTOR_LEN;
        wasm.getKeySchedule(retptr, keySize, ptr0, len0);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v1 = getArrayU32FromWasm0(r0, r1).slice();

        wasm.__wbindgen_free(r0, r1 * 4);

        return v1;
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);
      }
    }
    /**
    * @param {number} keySize
    * @param {Uint32Array} keyWords
    * @returns {Uint32Array}
    */


    function getInvKeySchedule(keySize, keyWords) {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        var ptr0 = passArray32ToWasm0(keyWords, wasm.__wbindgen_malloc);
        var len0 = WASM_VECTOR_LEN;
        wasm.getInvKeySchedule(retptr, keySize, ptr0, len0);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v1 = getArrayU32FromWasm0(r0, r1).slice();

        wasm.__wbindgen_free(r0, r1 * 4);

        return v1;
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);
      }
    }

    let cachegetUint8Memory0 = null;

    function getUint8Memory0() {
      if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) {
        cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer);
      }

      return cachegetUint8Memory0;
    }

    const lTextEncoder = typeof TextEncoder === 'undefined' ? (0, module.require)('util').TextEncoder : TextEncoder;
    let cachedTextEncoder = new lTextEncoder('utf-8');
    const encodeString = typeof cachedTextEncoder.encodeInto === 'function' ? function (arg, view) {
      return cachedTextEncoder.encodeInto(arg, view);
    } : function (arg, view) {
      const buf = cachedTextEncoder.encode(arg);
      view.set(buf);
      return {
        read: arg.length,
        written: buf.length
      };
    };

    function passStringToWasm0(arg, malloc, realloc) {
      if (realloc === undefined) {
        const buf = cachedTextEncoder.encode(arg);
        const ptr = malloc(buf.length);
        getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
        WASM_VECTOR_LEN = buf.length;
        return ptr;
      }

      let len = arg.length;
      let ptr = malloc(len);
      const mem = getUint8Memory0();
      let offset = 0;

      for (; offset < len; offset++) {
        const code = arg.charCodeAt(offset);
        if (code > 0x7F) break;
        mem[ptr + offset] = code;
      }

      if (offset !== len) {
        if (offset !== 0) {
          arg = arg.slice(offset);
        }

        ptr = realloc(ptr, len, len = offset + arg.length * 3);
        const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
        const ret = encodeString(arg, view);
        offset += ret.written;
      }

      WASM_VECTOR_LEN = offset;
      return ptr;
    }
    /**
    * @param {string} mode
    * @param {number} nRounds
    * @param {number} nWordsReady
    * @param {number} blockSize
    * @param {Uint32Array} iv
    * @param {Uint32Array} dataWords
    * @param {Uint32Array} keySchedule
    * @returns {Uint32Array}
    */


    function doEncrypt(mode, nRounds, nWordsReady, blockSize, iv, dataWords, keySchedule) {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        var ptr0 = passStringToWasm0(mode, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(iv, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        var ptr2 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len2 = WASM_VECTOR_LEN;
        var ptr3 = passArray32ToWasm0(keySchedule, wasm.__wbindgen_malloc);
        var len3 = WASM_VECTOR_LEN;
        wasm.doEncrypt(retptr, ptr0, len0, nRounds, nWordsReady, blockSize, ptr1, len1, ptr2, len2, ptr3, len3);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v4 = getArrayU32FromWasm0(r0, r1).slice();

        wasm.__wbindgen_free(r0, r1 * 4);

        return v4;
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);

        dataWords.set(getUint32Memory0().subarray(ptr2 / 4, ptr2 / 4 + len2));

        wasm.__wbindgen_free(ptr2, len2 * 4);
      }
    }
    /**
    * @param {string} mode
    * @param {number} nRounds
    * @param {number} nWordsReady
    * @param {number} blockSize
    * @param {Uint32Array} iv
    * @param {Uint32Array} dataWords
    * @param {Uint32Array} keySchedule
    * @param {Uint32Array} invKeySchedule
    * @returns {Uint32Array}
    */


    function doDecrypt(mode, nRounds, nWordsReady, blockSize, iv, dataWords, keySchedule, invKeySchedule) {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        var ptr0 = passStringToWasm0(mode, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(iv, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        var ptr2 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len2 = WASM_VECTOR_LEN;
        var ptr3 = passArray32ToWasm0(keySchedule, wasm.__wbindgen_malloc);
        var len3 = WASM_VECTOR_LEN;
        var ptr4 = passArray32ToWasm0(invKeySchedule, wasm.__wbindgen_malloc);
        var len4 = WASM_VECTOR_LEN;
        wasm.doDecrypt(retptr, ptr0, len0, nRounds, nWordsReady, blockSize, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v5 = getArrayU32FromWasm0(r0, r1).slice();

        wasm.__wbindgen_free(r0, r1 * 4);

        return v5;
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);

        dataWords.set(getUint32Memory0().subarray(ptr2 / 4, ptr2 / 4 + len2));

        wasm.__wbindgen_free(ptr2, len2 * 4);
      }
    }

    return {
      getKeySchedule: getKeySchedule,
      getInvKeySchedule: getInvKeySchedule,
      doEncrypt: doEncrypt,
      doDecrypt: doDecrypt
    };
  }

  const wasmBytes$5 = generateWasmBytes('[encoded data, 61396 characters]');

  /**
   * AES block cipher algorithm.
   */

  class AESAlgo extends BlockCipher {
    static get keySize() {
      return 256 / 32;
    }

    constructor(...args) {
      super(...args);
      this.keySize = 256 / 32;
    }

    static async loadWasm() {
      if (AESAlgo.wasm) {
        return AESAlgo.wasm;
      }

      AESAlgo.wasm = await loadWasm(wasmBytes$5);
      return AESAlgo.wasm;
    }

    async loadWasm() {
      return AESAlgo.loadWasm();
    }

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


      const key = this._key;
      const keyWords = key.words;
      const keySize = key.sigBytes / 4; // Compute number of rounds

      this._nRounds = keySize + 6;
      this._keySchedule = aesWasm(AESAlgo.wasm).getKeySchedule(keySize, keyWords);
      this._invKeySchedule = aesWasm(AESAlgo.wasm).getInvKeySchedule(keySize, keyWords);
    } // eslint-disable-next-line no-dupe-class-members


    _process(doFlush) {
      if (!AESAlgo.wasm) {
        throw new Error('WASM is not loaded yet. \'AESAlgo.loadWasm\' should be called first');
      }

      let processedWords; // Shortcuts

      const data = this._data;
      let dataWords = data.words;
      const dataSigBytes = data.sigBytes;
      const blockSize = this.blockSize;
      const blockSizeBytes = blockSize * 4; // Count blocks ready

      let 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


      const nWordsReady = nBlocksReady * blockSize; // Count bytes ready

      const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); // Process blocks

      if (nWordsReady) {
        if (dataWords.length < nWordsReady) {
          for (let i = dataWords.length; i < nWordsReady; i++) {
            dataWords[i] = 0;
          }
        }

        const dataArray = new Uint32Array(dataWords);
        const ivWords = this.cfg.iv ? this.cfg.iv.words : ''; // Perform concrete-algorithm logic

        if (this._xformMode == this._ENC_XFORM_MODE) {
          if (this.modeProcessBlock != undefined) {
            this.modeProcessBlock = aesWasm(AESAlgo.wasm).doEncrypt(this.cfg.mode._name, this._nRounds, nWordsReady, blockSize, this.modeProcessBlock, dataArray, this._keySchedule);
          } else {
            this.modeProcessBlock = aesWasm(AESAlgo.wasm).doEncrypt(this.cfg.mode._name, this._nRounds, nWordsReady, blockSize, ivWords, dataArray, this._keySchedule);
          }
        } else
          /* if (this._xformMode == this._DEC_XFORM_MODE) */
          {
            if (this.modeProcessBlock != undefined) {
              this.modeProcessBlock = aesWasm(AESAlgo.wasm).doDecrypt(this.cfg.mode._name, this._nRounds, nWordsReady, blockSize, this.modeProcessBlock, dataArray, this._keySchedule, this._invKeySchedule);
            } else {
              this.modeProcessBlock = aesWasm(AESAlgo.wasm).doDecrypt(this.cfg.mode._name, this._nRounds, nWordsReady, blockSize, ivWords, dataArray, this._keySchedule, this._invKeySchedule);
            }
          }

        dataWords = Array.from(dataArray); // Remove processed words

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


      return new WordArray(processedWords, nBytesReady);
    }

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

  _defineProperty(AESAlgo, "wasm", null);

  const AES = BlockCipher._createHelper(AESAlgo);

  function blowfishWasm(wasm) {
    let cachegetUint32Memory0 = null;

    function getUint32Memory0() {
      if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) {
        cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer);
      }

      return cachegetUint32Memory0;
    }

    let WASM_VECTOR_LEN = 0;

    function passArray32ToWasm0(arg, malloc) {
      const ptr = malloc(arg.length * 4);
      getUint32Memory0().set(arg, ptr / 4);
      WASM_VECTOR_LEN = arg.length;
      return ptr;
    }

    let cachegetInt32Memory0 = null;

    function getInt32Memory0() {
      if (cachegetInt32Memory0 === null || cachegetInt32Memory0.buffer !== wasm.memory.buffer) {
        cachegetInt32Memory0 = new Int32Array(wasm.memory.buffer);
      }

      return cachegetInt32Memory0;
    }

    function getArrayU32FromWasm0(ptr, len) {
      return getUint32Memory0().subarray(ptr / 4, ptr / 4 + len);
    }
    /**
    * @param {Uint32Array} key
    * @param {number} keySize
    * @returns {Uint32Array}
    */


    function blowfishInit(key, keySize) {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        var ptr0 = passArray32ToWasm0(key, wasm.__wbindgen_malloc);
        var len0 = WASM_VECTOR_LEN;
        wasm.blowfishInit(retptr, ptr0, len0, keySize);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v1 = getArrayU32FromWasm0(r0, r1).slice();

        wasm.__wbindgen_free(r0, r1 * 4);

        return v1;
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);
      }
    }

    let cachegetUint8Memory0 = null;

    function getUint8Memory0() {
      if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) {
        cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer);
      }

      return cachegetUint8Memory0;
    }

    const lTextEncoder = typeof TextEncoder === 'undefined' ? (0, module.require)('util').TextEncoder : TextEncoder;
    let cachedTextEncoder = new lTextEncoder('utf-8');
    const encodeString = typeof cachedTextEncoder.encodeInto === 'function' ? function (arg, view) {
      return cachedTextEncoder.encodeInto(arg, view);
    } : function (arg, view) {
      const buf = cachedTextEncoder.encode(arg);
      view.set(buf);
      return {
        read: arg.length,
        written: buf.length
      };
    };

    function passStringToWasm0(arg, malloc, realloc) {
      if (realloc === undefined) {
        const buf = cachedTextEncoder.encode(arg);
        const ptr = malloc(buf.length);
        getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
        WASM_VECTOR_LEN = buf.length;
        return ptr;
      }

      let len = arg.length;
      let ptr = malloc(len);
      const mem = getUint8Memory0();
      let offset = 0;

      for (; offset < len; offset++) {
        const code = arg.charCodeAt(offset);
        if (code > 0x7F) break;
        mem[ptr + offset] = code;
      }

      if (offset !== len) {
        if (offset !== 0) {
          arg = arg.slice(offset);
        }

        ptr = realloc(ptr, len, len = offset + arg.length * 3);
        const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
        const ret = encodeString(arg, view);
        offset += ret.written;
      }

      WASM_VECTOR_LEN = offset;
      return ptr;
    }
    /**
    * @param {string} mode
    * @param {number} nWordsReady
    * @param {number} blockSize
    * @param {Uint32Array} iv
    * @param {Uint32Array} dataWords
    * @param {Uint32Array} P
    * @param {Uint32Array} S
    * @returns {Uint32Array}
    */


    function doEncrypt(mode, nWordsReady, blockSize, iv, dataWords, P, S) {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        var ptr0 = passStringToWasm0(mode, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(iv, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        var ptr2 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len2 = WASM_VECTOR_LEN;
        var ptr3 = passArray32ToWasm0(P, wasm.__wbindgen_malloc);
        var len3 = WASM_VECTOR_LEN;
        var ptr4 = passArray32ToWasm0(S, wasm.__wbindgen_malloc);
        var len4 = WASM_VECTOR_LEN;
        wasm.doEncrypt(retptr, ptr0, len0, nWordsReady, blockSize, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v5 = getArrayU32FromWasm0(r0, r1).slice();

        wasm.__wbindgen_free(r0, r1 * 4);

        return v5;
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);

        dataWords.set(getUint32Memory0().subarray(ptr2 / 4, ptr2 / 4 + len2));

        wasm.__wbindgen_free(ptr2, len2 * 4);
      }
    }
    /**
    * @param {string} mode
    * @param {number} nWordsReady
    * @param {number} blockSize
    * @param {Uint32Array} iv
    * @param {Uint32Array} dataWords
    * @param {Uint32Array} P
    * @param {Uint32Array} S
    * @returns {Uint32Array}
    */


    function doDecrypt(mode, nWordsReady, blockSize, iv, dataWords, P, S) {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        var ptr0 = passStringToWasm0(mode, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(iv, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        var ptr2 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len2 = WASM_VECTOR_LEN;
        var ptr3 = passArray32ToWasm0(P, wasm.__wbindgen_malloc);
        var len3 = WASM_VECTOR_LEN;
        var ptr4 = passArray32ToWasm0(S, wasm.__wbindgen_malloc);
        var len4 = WASM_VECTOR_LEN;
        wasm.doDecrypt(retptr, ptr0, len0, nWordsReady, blockSize, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v5 = getArrayU32FromWasm0(r0, r1).slice();

        wasm.__wbindgen_free(r0, r1 * 4);

        return v5;
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);

        dataWords.set(getUint32Memory0().subarray(ptr2 / 4, ptr2 / 4 + len2));

        wasm.__wbindgen_free(ptr2, len2 * 4);
      }
    }

    return {
      blowfishInit: blowfishInit,
      doEncrypt: doEncrypt,
      doDecrypt: doDecrypt
    };
  }

  const wasmBytes$4 = generateWasmBytes('[encoded data, 41856 characters]');

  /**
   * Blowfish block cipher algorithm.
   */

  class BlowfishAlgo extends BlockCipher {
    static get keySize() {
      return 128 / 32;
    }

    static get ivSize() {
      return 64 / 32;
    }

    static get blockSize() {
      return 64 / 32;
    }

    constructor(...args) {
      super(...args);
      this.keySize = 128 / 32;
      this.ivSize = 64 / 32;
      this.blockSize = 64 / 32;
    }

    static async loadWasm() {
      if (BlowfishAlgo.wasm) {
        return BlowfishAlgo.wasm;
      }

      BlowfishAlgo.wasm = await loadWasm(wasmBytes$4);
      return BlowfishAlgo.wasm;
    }

    async loadWasm() {
      return BlowfishAlgo.loadWasm();
    }

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


      const key = this._keyPriorReset = this._key;
      const keyWords = key.words;
      const keySize = key.sigBytes / 4; //Initialization pbox and sbox

      const ctx = Array.from(blowfishWasm(BlowfishAlgo.wasm).blowfishInit(keyWords, keySize));
      this.pbox = ctx.splice(0, 18);
      this.sbox = [];

      for (let i = 0; i < 4; i++) {
        this.sbox[i] = ctx.splice(0, 256);
      }
    }

    _process(doFlush) {
      if (!BlowfishAlgo.wasm) {
        throw new Error('WASM is not loaded yet. \'BlowfishAlgo.loadWasm\' should be called first');
      }

      let processedWords; // Shortcuts

      const data = this._data;
      let dataWords = data.words;
      const dataSigBytes = data.sigBytes;
      const blockSize = this.blockSize;
      const blockSizeBytes = blockSize * 4; // Count blocks ready

      let 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


      const nWordsReady = nBlocksReady * blockSize; // Count bytes ready

      const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); // Process blocks

      if (nWordsReady) {
        if (dataWords.length < nWordsReady) {
          for (let i = dataWords.length; i < nWordsReady; i++) {
            dataWords[i] = 0;
          }
        }

        const dataArray = new Uint32Array(dataWords);
        const ivWords = this.cfg.iv ? this.cfg.iv.words : '';
        let s = [];

        for (let i = 0; i < 4; i++) {
          s.push.apply(s, this.sbox[i]);
        } // Perform concrete-algorithm logic


        if (this._xformMode == this._ENC_XFORM_MODE) {
          if (this.modeProcessBlock != undefined) {
            this.modeProcessBlock = blowfishWasm(BlowfishAlgo.wasm).doEncrypt(this.cfg.mode._name, nWordsReady, blockSize, this.modeProcessBlock, dataArray, this.pbox, s);
          } else {
            this.modeProcessBlock = blowfishWasm(BlowfishAlgo.wasm).doEncrypt(this.cfg.mode._name, nWordsReady, blockSize, ivWords, dataArray, this.pbox, s);
          }
        } else
          /* if (this._xformMode == this._DEC_XFORM_MODE) */
          {
            if (this.modeProcessBlock != undefined) {
              this.modeProcessBlock = blowfishWasm(BlowfishAlgo.wasm).doDecrypt(this.cfg.mode._name, nWordsReady, blockSize, this.modeProcessBlock, dataArray, this.pbox, s);
            } else {
              this.modeProcessBlock = blowfishWasm(BlowfishAlgo.wasm).doDecrypt(this.cfg.mode._name, nWordsReady, blockSize, ivWords, dataArray, this.pbox, s);
            }
          }

        dataWords = Array.from(dataArray); // Remove processed words

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


      return new WordArray(processedWords, nBytesReady);
    }

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

  _defineProperty(BlowfishAlgo, "wasm", null);

  const Blowfish = BlockCipher._createHelper(BlowfishAlgo);

  function desWasm(wasm) {
    let WASM_VECTOR_LEN = 0;
    let cachegetUint8Memory0 = null;

    function getUint8Memory0() {
      if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) {
        cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer);
      }

      return cachegetUint8Memory0;
    }

    const lTextEncoder = typeof TextEncoder === 'undefined' ? (0, module.require)('util').TextEncoder : TextEncoder;
    let cachedTextEncoder = new lTextEncoder('utf-8');
    const encodeString = typeof cachedTextEncoder.encodeInto === 'function' ? function (arg, view) {
      return cachedTextEncoder.encodeInto(arg, view);
    } : function (arg, view) {
      const buf = cachedTextEncoder.encode(arg);
      view.set(buf);
      return {
        read: arg.length,
        written: buf.length
      };
    };

    function passStringToWasm0(arg, malloc, realloc) {
      if (realloc === undefined) {
        const buf = cachedTextEncoder.encode(arg);
        const ptr = malloc(buf.length);
        getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
        WASM_VECTOR_LEN = buf.length;
        return ptr;
      }

      let len = arg.length;
      let ptr = malloc(len);
      const mem = getUint8Memory0();
      let offset = 0;

      for (; offset < len; offset++) {
        const code = arg.charCodeAt(offset);
        if (code > 0x7F) break;
        mem[ptr + offset] = code;
      }

      if (offset !== len) {
        if (offset !== 0) {
          arg = arg.slice(offset);
        }

        ptr = realloc(ptr, len, len = offset + arg.length * 3);
        const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
        const ret = encodeString(arg, view);
        offset += ret.written;
      }

      WASM_VECTOR_LEN = offset;
      return ptr;
    }

    let cachegetUint32Memory0 = null;

    function getUint32Memory0() {
      if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) {
        cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer);
      }

      return cachegetUint32Memory0;
    }

    function passArray32ToWasm0(arg, malloc) {
      const ptr = malloc(arg.length * 4);
      getUint32Memory0().set(arg, ptr / 4);
      WASM_VECTOR_LEN = arg.length;
      return ptr;
    }

    let cachegetInt32Memory0 = null;

    function getInt32Memory0() {
      if (cachegetInt32Memory0 === null || cachegetInt32Memory0.buffer !== wasm.memory.buffer) {
        cachegetInt32Memory0 = new Int32Array(wasm.memory.buffer);
      }

      return cachegetInt32Memory0;
    }

    function getArrayU32FromWasm0(ptr, len) {
      return getUint32Memory0().subarray(ptr / 4, ptr / 4 + len);
    }
    /**
    * @param {string} mode
    * @param {number} nWordsReady
    * @param {number} blockSize
    * @param {Uint32Array} iv
    * @param {Uint32Array} dataWords
    * @param {Uint32Array} keyWords
    * @returns {Uint32Array}
    */


    function doEncrypt(mode, nWordsReady, blockSize, iv, dataWords, keyWords) {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        var ptr0 = passStringToWasm0(mode, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(iv, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        var ptr2 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len2 = WASM_VECTOR_LEN;
        var ptr3 = passArray32ToWasm0(keyWords, wasm.__wbindgen_malloc);
        var len3 = WASM_VECTOR_LEN;
        wasm.doEncrypt(retptr, ptr0, len0, nWordsReady, blockSize, ptr1, len1, ptr2, len2, ptr3, len3);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v4 = getArrayU32FromWasm0(r0, r1).slice();

        wasm.__wbindgen_free(r0, r1 * 4);

        return v4;
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);

        dataWords.set(getUint32Memory0().subarray(ptr2 / 4, ptr2 / 4 + len2));

        wasm.__wbindgen_free(ptr2, len2 * 4);
      }
    }
    /**
    * @param {string} mode
    * @param {number} nWordsReady
    * @param {number} blockSize
    * @param {Uint32Array} iv
    * @param {Uint32Array} dataWords
    * @param {Uint32Array} keyWords
    * @returns {Uint32Array}
    */


    function doDecrypt(mode, nWordsReady, blockSize, iv, dataWords, keyWords) {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        var ptr0 = passStringToWasm0(mode, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(iv, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        var ptr2 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len2 = WASM_VECTOR_LEN;
        var ptr3 = passArray32ToWasm0(keyWords, wasm.__wbindgen_malloc);
        var len3 = WASM_VECTOR_LEN;
        wasm.doDecrypt(retptr, ptr0, len0, nWordsReady, blockSize, ptr1, len1, ptr2, len2, ptr3, len3);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v4 = getArrayU32FromWasm0(r0, r1).slice();

        wasm.__wbindgen_free(r0, r1 * 4);

        return v4;
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);

        dataWords.set(getUint32Memory0().subarray(ptr2 / 4, ptr2 / 4 + len2));

        wasm.__wbindgen_free(ptr2, len2 * 4);
      }
    }
    /**
    * @param {string} mode
    * @param {number} nWordsReady
    * @param {number} blockSize
    * @param {Uint32Array} iv
    * @param {Uint32Array} dataWords
    * @param {Uint32Array} keyWords1
    * @param {Uint32Array} keyWords2
    * @param {Uint32Array} keyWords3
    * @returns {Uint32Array}
    */


    function tripleEncrypt(mode, nWordsReady, blockSize, iv, dataWords, keyWords1, keyWords2, keyWords3) {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        var ptr0 = passStringToWasm0(mode, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(iv, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        var ptr2 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len2 = WASM_VECTOR_LEN;
        var ptr3 = passArray32ToWasm0(keyWords1, wasm.__wbindgen_malloc);
        var len3 = WASM_VECTOR_LEN;
        var ptr4 = passArray32ToWasm0(keyWords2, wasm.__wbindgen_malloc);
        var len4 = WASM_VECTOR_LEN;
        var ptr5 = passArray32ToWasm0(keyWords3, wasm.__wbindgen_malloc);
        var len5 = WASM_VECTOR_LEN;
        wasm.tripleEncrypt(retptr, ptr0, len0, nWordsReady, blockSize, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4, ptr5, len5);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v6 = getArrayU32FromWasm0(r0, r1).slice();

        wasm.__wbindgen_free(r0, r1 * 4);

        return v6;
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);

        dataWords.set(getUint32Memory0().subarray(ptr2 / 4, ptr2 / 4 + len2));

        wasm.__wbindgen_free(ptr2, len2 * 4);
      }
    }
    /**
    * @param {string} mode
    * @param {number} nWordsReady
    * @param {number} blockSize
    * @param {Uint32Array} iv
    * @param {Uint32Array} dataWords
    * @param {Uint32Array} keyWords1
    * @param {Uint32Array} keyWords2
    * @param {Uint32Array} keyWords3
    * @returns {Uint32Array}
    */


    function tripleDecrypt(mode, nWordsReady, blockSize, iv, dataWords, keyWords1, keyWords2, keyWords3) {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        var ptr0 = passStringToWasm0(mode, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(iv, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        var ptr2 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len2 = WASM_VECTOR_LEN;
        var ptr3 = passArray32ToWasm0(keyWords1, wasm.__wbindgen_malloc);
        var len3 = WASM_VECTOR_LEN;
        var ptr4 = passArray32ToWasm0(keyWords2, wasm.__wbindgen_malloc);
        var len4 = WASM_VECTOR_LEN;
        var ptr5 = passArray32ToWasm0(keyWords3, wasm.__wbindgen_malloc);
        var len5 = WASM_VECTOR_LEN;
        wasm.tripleDecrypt(retptr, ptr0, len0, nWordsReady, blockSize, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4, ptr5, len5);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v6 = getArrayU32FromWasm0(r0, r1).slice();

        wasm.__wbindgen_free(r0, r1 * 4);

        return v6;
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);

        dataWords.set(getUint32Memory0().subarray(ptr2 / 4, ptr2 / 4 + len2));

        wasm.__wbindgen_free(ptr2, len2 * 4);
      }
    }

    return {
      doEncrypt: doEncrypt,
      doDecrypt: doDecrypt,
      tripleEncrypt: tripleEncrypt,
      tripleDecrypt: tripleDecrypt
    };
  }

  const wasmBytes$3 = generateWasmBytes('[encoded data, 43216 characters]');

  const 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

  const 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

  const BIT_SHIFTS = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28];
  /**
   * DES block cipher algorithm.
   */

  class DESAlgo extends BlockCipher {
    static get keySize() {
      return 64 / 32;
    }

    static get ivSize() {
      return 64 / 32;
    }

    static get blockSize() {
      return 64 / 32;
    }

    constructor(...args) {
      super(...args);
      this.keySize = 64 / 32;
      this.ivSize = 64 / 32;
      this.blockSize = 64 / 32;
    }

    static async loadWasm() {
      if (DESAlgo.wasm) {
        return DESAlgo.wasm;
      }

      DESAlgo.wasm = await loadWasm(wasmBytes$3);
      return DESAlgo.wasm;
    }

    async loadWasm() {
      return DESAlgo.loadWasm();
    }

    _doReset() {
      // Shortcuts
      const key = this._key;
      const keyWords = key.words; // Select 56 bits according to PC1

      const keyBits = [];

      for (let i = 0; i < 56; i++) {
        const keyBitPos = PC1[i] - 1;
        keyBits[i] = keyWords[keyBitPos >>> 5] >>> 31 - keyBitPos % 32 & 1;
      } // Assemble 16 subkeys


      this._subKeys = [];
      const subKeys = this._subKeys;

      for (let nSubKey = 0; nSubKey < 16; nSubKey++) {
        // Create subkey
        subKeys[nSubKey] = [];
        const subKey = subKeys[nSubKey]; // Shortcut

        const bitShift = BIT_SHIFTS[nSubKey]; // Select 48 bits according to PC2

        for (let 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 (let i = 1; i < 7; i++) {
          subKey[i] >>>= (i - 1) * 4 + 3;
        }

        subKey[7] = subKey[7] << 5 | subKey[7] >>> 27;
      } // Compute inverse subkeys


      this._invSubKeys = [];
      const invSubKeys = this._invSubKeys;

      for (let i = 0; i < 16; i++) {
        invSubKeys[i] = subKeys[15 - i];
      }
    }

    _process(doFlush) {
      if (!DESAlgo.wasm) {
        throw new Error('WASM is not loaded yet. \'DESAlgo.loadWasm\' should be called first');
      }

      let processedWords; // Shortcuts

      const data = this._data;
      let dataWords = data.words;
      const dataSigBytes = data.sigBytes;
      const blockSize = this.blockSize;
      const blockSizeBytes = blockSize * 4; // Count blocks ready

      let 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


      const nWordsReady = nBlocksReady * blockSize; // Count bytes ready

      const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); // Process blocks

      if (nWordsReady) {
        if (dataWords.length < nWordsReady) {
          for (let i = dataWords.length; i < nWordsReady; i++) {
            dataWords[i] = 0;
          }
        }

        const dataArray = new Uint32Array(dataWords);
        const ivWords = this.cfg.iv ? this.cfg.iv.words : ''; // Perform concrete-algorithm logic

        if (this._xformMode == this._ENC_XFORM_MODE) {
          if (this.modeProcessBlock != undefined) {
            this.modeProcessBlock = desWasm(DESAlgo.wasm).doEncrypt(this.cfg.mode._name, nWordsReady, blockSize, this.modeProcessBlock, dataArray, this._key.words);
          } else {
            this.modeProcessBlock = desWasm(DESAlgo.wasm).doEncrypt(this.cfg.mode._name, nWordsReady, blockSize, ivWords, dataArray, this._key.words);
          }
        } else
          /* if (this._xformMode == this._DEC_XFORM_MODE) */
          {
            if (this.modeProcessBlock != undefined) {
              this.modeProcessBlock = desWasm(DESAlgo.wasm).doDecrypt(this.cfg.mode._name, nWordsReady, blockSize, this.modeProcessBlock, dataArray, this._key.words);
            } else {
              this.modeProcessBlock = desWasm(DESAlgo.wasm).doDecrypt(this.cfg.mode._name, nWordsReady, blockSize, ivWords, dataArray, this._key.words);
            }
          }

        dataWords = Array.from(dataArray); // Remove processed words

        processedWords = dataWords.splice(0, nWordsReady); // write data back to this._data

        this._data.words = dataWords;
        data.sigBytes -= nBytesReady;
      } // Return processed words


      return new WordArray(processedWords, nBytesReady);
    }

  }
  /**
   * Shortcut functions to the cipher's object interface.
   *
   * @example
   *
   *     const ciphertext = CryptoJSW.DES.encrypt(message, key, cfg);
   *     const plaintext  = CryptoJSW.DES.decrypt(ciphertext, key, cfg);
   */

  _defineProperty(DESAlgo, "wasm", null);

  const DES = BlockCipher._createHelper(DESAlgo);
  /**
   * Triple-DES block cipher algorithm.
   */

  class TripleDESAlgo extends BlockCipher {
    static get keySize() {
      return 192 / 32;
    }

    static get ivSize() {
      return 64 / 32;
    }

    static get blockSize() {
      return 64 / 32;
    }

    static async loadWasm() {
      return DESAlgo.loadWasm();
    }

    async loadWasm() {
      return TripleDESAlgo.loadWasm();
    }

    constructor(...args) {
      super(...args);
      this.keySize = 192 / 32;
      this.ivSize = 64 / 32;
      this.blockSize = 64 / 32;
    }
    /**
     * do nothing
     * @private
     */


    _doReset() {}

    _process(doFlush) {
      if (!DESAlgo.wasm) {
        throw new Error('WASM is not loaded yet. \'TripleDESAlgo.loadWasm\' should be called first');
      }

      let processedWords; // Shortcuts

      const data = this._data;
      let dataWords = data.words;
      const dataSigBytes = data.sigBytes;
      const blockSize = this.blockSize;
      const blockSizeBytes = blockSize * 4;
      const key = this._key;
      const 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


      const key1 = keyWords.slice(0, 2);
      const key2 = keyWords.length < 4 ? keyWords.slice(0, 2) : keyWords.slice(2, 4);
      const key3 = keyWords.length < 6 ? keyWords.slice(0, 2) : keyWords.slice(4, 6); // Count blocks ready

      let 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


      const nWordsReady = nBlocksReady * blockSize; // Count bytes ready

      const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); // Process blocks

      if (nWordsReady) {
        const dataArray = new Uint32Array(dataWords);
        const ivWords = this.cfg.iv ? this.cfg.iv.words : ''; // Perform concrete-algorithm logic

        if (this._xformMode == this._ENC_XFORM_MODE) {
          if (this.modeProcessBlock != undefined) {
            this.modeProcessBlock = desWasm(DESAlgo.wasm).tripleEncrypt(this.cfg.mode._name, nWordsReady, blockSize, this.modeProcessBlock, dataArray, key1, key2, key3);
          } else {
            this.modeProcessBlock = desWasm(DESAlgo.wasm).tripleEncrypt(this.cfg.mode._name, nWordsReady, blockSize, ivWords, dataArray, key1, key2, key3);
          }
        } else
          /* if (this._xformMode == this._DEC_XFORM_MODE) */
          {
            if (this.modeProcessBlock != undefined) {
              this.modeProcessBlock = desWasm(DESAlgo.wasm).tripleDecrypt(this.cfg.mode._name, nWordsReady, blockSize, this.modeProcessBlock, dataArray, key1, key2, key3);
            } else {
              this.modeProcessBlock = desWasm(DESAlgo.wasm).tripleDecrypt(this.cfg.mode._name, nWordsReady, blockSize, ivWords, dataArray, key1, key2, key3);
            }
          }

        dataWords = Array.from(dataArray); // Remove processed words

        processedWords = dataWords.splice(0, nWordsReady); // write data back to this._data

        this._data.words = dataWords;
        data.sigBytes -= nBytesReady;
      } // Return processed words


      return new WordArray(processedWords, nBytesReady);
    }

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

  const TripleDES = BlockCipher._createHelper(TripleDESAlgo);

  function rabbitWasm(wasm) {
    let cachegetUint32Memory0 = null;

    function getUint32Memory0() {
      if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) {
        cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer);
      }

      return cachegetUint32Memory0;
    }

    let WASM_VECTOR_LEN = 0;

    function passArray32ToWasm0(arg, malloc) {
      const ptr = malloc(arg.length * 4);
      getUint32Memory0().set(arg, ptr / 4);
      WASM_VECTOR_LEN = arg.length;
      return ptr;
    }
    /**
    * @param {number} nWordsReady
    * @param {number} blockSize
    * @param {Uint32Array} dataWords
    * @param {Uint32Array} X
    * @param {Uint32Array} C
    * @param {number} b
    * @returns {number}
    */


    function doProcess(nWordsReady, blockSize, dataWords, X, C, b) {
      try {
        var ptr0 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(X, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        var ptr2 = passArray32ToWasm0(C, wasm.__wbindgen_malloc);
        var len2 = WASM_VECTOR_LEN;
        var ret = wasm.doProcess(nWordsReady, blockSize, ptr0, len0, ptr1, len1, ptr2, len2, b);
        return ret >>> 0;
      } finally {
        dataWords.set(getUint32Memory0().subarray(ptr0 / 4, ptr0 / 4 + len0));

        wasm.__wbindgen_free(ptr0, len0 * 4);

        X.set(getUint32Memory0().subarray(ptr1 / 4, ptr1 / 4 + len1));

        wasm.__wbindgen_free(ptr1, len1 * 4);

        C.set(getUint32Memory0().subarray(ptr2 / 4, ptr2 / 4 + len2));

        wasm.__wbindgen_free(ptr2, len2 * 4);
      }
    }

    return {
      doProcess: doProcess
    };
  }

  const wasmBytes$2 = generateWasmBytes('[encoded data, 8932 characters]');

  const C_$1 = [];
  const G$1 = [];

  function nextState$1() {
    // Shortcuts
    const X = this._X;
    const C = this._C; // Save old counter values

    for (let i = 0; i < 8; i++) {
      C_$1[i] = C[i];
    } // Calculate new counter values


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

    for (let i = 0; i < 8; i++) {
      const gx = X[i] + C[i]; // Construct high and low argument for squaring

      const ga = gx & 0xffff;
      const gb = gx >>> 16; // Calculate high and low result of squaring

      const gh = ((ga * ga >>> 17) + ga * gb >>> 15) + gb * gb;
      const gl = ((gx & 0xffff0000) * gx | 0) + ((gx & 0x0000ffff) * gx | 0); // High XOR low

      G$1[i] = gh ^ gl;
    } // Calculate new state values


    X[0] = G$1[0] + (G$1[7] << 16 | G$1[7] >>> 16) + (G$1[6] << 16 | G$1[6] >>> 16) | 0;
    X[1] = G$1[1] + (G$1[0] << 8 | G$1[0] >>> 24) + G$1[7] | 0;
    X[2] = G$1[2] + (G$1[1] << 16 | G$1[1] >>> 16) + (G$1[0] << 16 | G$1[0] >>> 16) | 0;
    X[3] = G$1[3] + (G$1[2] << 8 | G$1[2] >>> 24) + G$1[1] | 0;
    X[4] = G$1[4] + (G$1[3] << 16 | G$1[3] >>> 16) + (G$1[2] << 16 | G$1[2] >>> 16) | 0;
    X[5] = G$1[5] + (G$1[4] << 8 | G$1[4] >>> 24) + G$1[3] | 0;
    X[6] = G$1[6] + (G$1[5] << 16 | G$1[5] >>> 16) + (G$1[4] << 16 | G$1[4] >>> 16) | 0;
    X[7] = G$1[7] + (G$1[6] << 8 | G$1[6] >>> 24) + G$1[5] | 0;
  }
  /**
   * Rabbit stream cipher algorithm
   */


  class RabbitAlgo extends StreamCipher {
    static get blockSize() {
      return 128 / 32;
    }

    static get ivSize() {
      return 64 / 32;
    }

    constructor(...args) {
      super(...args);
      this.blockSize = 128 / 32;
      this.ivSize = 64 / 32;
    }

    static async loadWasm() {
      if (RabbitAlgo.wasm) {
        return RabbitAlgo.wasm;
      }

      RabbitAlgo.wasm = await loadWasm(wasmBytes$2);
      return RabbitAlgo.wasm;
    }

    async loadWasm() {
      return RabbitAlgo.loadWasm();
    }

    _doReset() {
      // Shortcuts
      const K = this._key.words;
      const {
        iv
      } = this.cfg; // Swap endian

      for (let 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


      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];
      const X = this._X; // Generate initial counter values

      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];
      const C = this._C; // Carry bit

      this._b = 0; // Iterate the system four times

      for (let i = 0; i < 4; i++) {
        nextState$1.call(this);
      } // Modify the counters


      for (let i = 0; i < 8; i++) {
        C[i] ^= X[i + 4 & 7];
      } // IV setup


      if (iv) {
        // Shortcuts
        const IV = iv.words;
        const IV_0 = IV[0];
        const IV_1 = IV[1]; // Generate four subvectors

        const i0 = (IV_0 << 8 | IV_0 >>> 24) & 0x00ff00ff | (IV_0 << 24 | IV_0 >>> 8) & 0xff00ff00;
        const i2 = (IV_1 << 8 | IV_1 >>> 24) & 0x00ff00ff | (IV_1 << 24 | IV_1 >>> 8) & 0xff00ff00;
        const i1 = i0 >>> 16 | i2 & 0xffff0000;
        const 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 (let i = 0; i < 4; i++) {
          nextState$1.call(this);
        }
      }
    }

    _process(doFlush) {
      if (!RabbitAlgo.wasm) {
        throw new Error('WASM is not loaded yet. \'RabbitAlgo.loadWasm\' should be called first');
      }

      let processedWords; // Shortcuts

      const data = this._data;
      let dataWords = data.words;
      const dataSigBytes = data.sigBytes;
      const blockSize = this.blockSize;
      const blockSizeBytes = blockSize * 4;
      const X = this._X;
      const C = this._C;
      const b = this._b; // Count blocks ready

      let 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


      const nWordsReady = nBlocksReady * blockSize; // Count bytes ready

      const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); // Process blocks

      if (nWordsReady) {
        if (dataWords.length < nWordsReady) {
          for (let i = dataWords.length; i < nWordsReady; i++) {
            dataWords[i] = 0;
          }
        }

        const dataArray = new Uint32Array(dataWords);
        const X_Array = new Uint32Array(X);
        const C_Array = new Uint32Array(C); // Perform concrete-algorithm logic

        this._b = rabbitWasm(RabbitAlgo.wasm).doProcess(nWordsReady, blockSize, dataArray, X_Array, C_Array, b);
        dataWords = Array.from(dataArray);
        this._X = Array.from(X_Array);
        this._C = Array.from(C_Array); // Remove processed words

        processedWords = dataWords.splice(0, nWordsReady); // write data back to this._data

        this._data.words = dataWords;
        data.sigBytes -= nBytesReady;
      } // Return processed words


      return new WordArray(processedWords, nBytesReady);
    }

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

  _defineProperty(RabbitAlgo, "wasm", null);

  const Rabbit = StreamCipher._createHelper(RabbitAlgo);

  const C_ = [];
  const G = [];

  function nextState() {
    // Shortcuts
    const X = this._X;
    const C = this._C; // Save old counter values

    for (let 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 (let i = 0; i < 8; i++) {
      const gx = X[i] + C[i]; // Construct high and low argument for squaring

      const ga = gx & 0xffff;
      const gb = gx >>> 16; // Calculate high and low result of squaring

      const gh = ((ga * ga >>> 17) + ga * gb >>> 15) + gb * gb;
      const 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;
  }
  /**
   * 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.
   */


  class RabbitLegacyAlgo extends StreamCipher {
    static get blockSize() {
      return 128 / 32;
    }

    static get ivSize() {
      return 64 / 32;
    }

    constructor(...args) {
      super(...args);
      this.blockSize = 128 / 32;
      this.ivSize = 64 / 32;
    }

    static async loadWasm() {
      if (RabbitLegacyAlgo.wasm) {
        return RabbitLegacyAlgo.wasm;
      }

      RabbitLegacyAlgo.wasm = await loadWasm(wasmBytes$2);
      return RabbitLegacyAlgo.wasm;
    }

    async loadWasm() {
      return RabbitLegacyAlgo.loadWasm();
    }

    _doReset() {
      // Shortcuts
      const K = this._key.words;
      const {
        iv
      } = this.cfg; // Generate initial state values

      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];
      const X = this._X; // Generate initial counter values

      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];
      const C = this._C; // Carry bit

      this._b = 0; // Iterate the system four times

      for (let i = 0; i < 4; i++) {
        nextState.call(this);
      } // Modify the counters


      for (let i = 0; i < 8; i++) {
        C[i] ^= X[i + 4 & 7];
      } // IV setup


      if (iv) {
        // Shortcuts
        const IV = iv.words;
        const IV_0 = IV[0];
        const IV_1 = IV[1]; // Generate four subvectors

        const i0 = (IV_0 << 8 | IV_0 >>> 24) & 0x00ff00ff | (IV_0 << 24 | IV_0 >>> 8) & 0xff00ff00;
        const i2 = (IV_1 << 8 | IV_1 >>> 24) & 0x00ff00ff | (IV_1 << 24 | IV_1 >>> 8) & 0xff00ff00;
        const i1 = i0 >>> 16 | i2 & 0xffff0000;
        const 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 (let i = 0; i < 4; i++) {
          nextState.call(this);
        }
      }
    }

    _process(doFlush) {
      if (!RabbitLegacyAlgo.wasm) {
        throw new Error('WASM is not loaded yet. \'RabbitLegacyAlgo.loadWasm\' should be called first');
      }

      let processedWords; // Shortcuts

      const data = this._data;
      let dataWords = data.words;
      const dataSigBytes = data.sigBytes;
      const blockSize = this.blockSize;
      const blockSizeBytes = blockSize * 4;
      const X = this._X;
      const C = this._C;
      const b = this._b; // Count blocks ready

      let 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


      const nWordsReady = nBlocksReady * blockSize; // Count bytes ready

      const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); // Process blocks

      if (nWordsReady) {
        if (dataWords.length < nWordsReady) {
          for (let i = dataWords.length; i < nWordsReady; i++) {
            dataWords[i] = 0;
          }
        }

        const dataArray = new Uint32Array(dataWords);
        const X_Array = new Uint32Array(X);
        const C_Array = new Uint32Array(C); // Perform concrete-algorithm logic

        this._b = rabbitWasm(RabbitLegacyAlgo.wasm).doProcess(nWordsReady, blockSize, dataArray, X_Array, C_Array, b);
        dataWords = Array.from(dataArray);
        this._X = Array.from(X_Array);
        this._C = Array.from(C_Array); // Remove processed words

        processedWords = dataWords.splice(0, nWordsReady); // write data back to this._data

        this._data.words = dataWords;
        data.sigBytes -= nBytesReady;
      } // Return processed words


      return new WordArray(processedWords, nBytesReady);
    }

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

  _defineProperty(RabbitLegacyAlgo, "wasm", null);

  const RabbitLegacy = StreamCipher._createHelper(RabbitLegacyAlgo);

  function rc4Wasm(wasm) {
    let cachegetUint32Memory0 = null;

    function getUint32Memory0() {
      if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) {
        cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer);
      }

      return cachegetUint32Memory0;
    }

    let WASM_VECTOR_LEN = 0;

    function passArray32ToWasm0(arg, malloc) {
      const ptr = malloc(arg.length * 4);
      getUint32Memory0().set(arg, ptr / 4);
      WASM_VECTOR_LEN = arg.length;
      return ptr;
    }
    /**
    * @param {number} nWordsReady
    * @param {number} blockSize
    * @param {Uint32Array} dataWords
    * @param {Uint32Array} S
    */


    function doProcess(nWordsReady, blockSize, dataWords, S) {
      try {
        var ptr0 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc);
        var len0 = WASM_VECTOR_LEN;
        var ptr1 = passArray32ToWasm0(S, wasm.__wbindgen_malloc);
        var len1 = WASM_VECTOR_LEN;
        wasm.doProcess(nWordsReady, blockSize, ptr0, len0, ptr1, len1);
      } finally {
        dataWords.set(getUint32Memory0().subarray(ptr0 / 4, ptr0 / 4 + len0));

        wasm.__wbindgen_free(ptr0, len0 * 4);

        S.set(getUint32Memory0().subarray(ptr1 / 4, ptr1 / 4 + len1));

        wasm.__wbindgen_free(ptr1, len1 * 4);
      }
    }

    return {
      doProcess: doProcess
    };
  }

  const wasmBytes$1 = generateWasmBytes('[encoded data, 8292 characters]');

  function generateKeystreamWord() {
    // Shortcuts
    const S = this._S;
    let i = this._i;
    let j = this._j; // Generate keystream word

    let keystreamWord = 0;

    for (let n = 0; n < 4; n++) {
      i = (i + 1) % 256;
      j = (j + S[i]) % 256; // Swap

      const 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;
  }
  /**
   * RC4 stream cipher algorithm.
   */


  class RC4Algo extends StreamCipher {
    static get keySize() {
      return 256 / 32;
    }

    static get ivSize() {
      return 0;
    }

    constructor(...args) {
      super(...args);
      this.keySize = 256 / 32;
      this.ivSize = 0;
    }

    static async loadWasm() {
      if (RC4Algo.wasm) {
        return RC4Algo.wasm;
      }

      RC4Algo.wasm = await loadWasm(wasmBytes$1);
      return RC4Algo.wasm;
    }

    async loadWasm() {
      return RC4Algo.loadWasm();
    }

    _doReset() {
      // Shortcuts
      const key = this._key;
      const keyWords = key.words;
      const keySigBytes = key.sigBytes; // Init sbox

      this._S = [];
      const S = this._S;

      for (let i = 0; i < 256; i++) {
        S[i] = i;
      } // Key setup


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

        const t = S[i];
        S[i] = S[j];
        S[j] = t;
      } // Counters


      this._j = 0;
      this._i = this._j;
    }

    _process(doFlush) {
      if (!RC4Algo.wasm) {
        throw new Error('WASM is not loaded yet. \'RC4Algo.loadWasm\' should be called first');
      }

      let processedWords; // Shortcuts

      const data = this._data;
      let dataWords = data.words;
      const dataSigBytes = data.sigBytes;
      const blockSize = this.blockSize;
      const blockSizeBytes = blockSize * 4; // Count blocks ready

      let 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


      const nWordsReady = nBlocksReady * blockSize; // Count bytes ready

      const nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); // Process blocks

      if (nWordsReady) {
        if (dataWords.length < nWordsReady) {
          for (let i = dataWords.length; i < nWordsReady; i++) {
            dataWords[i] = 0;
          }
        }

        const dataArray = new Uint32Array(dataWords);
        let S = this._S;
        S[256] = this._i;
        S[257] = this._j;
        const S_Array = new Uint32Array(S); // Perform concrete-algorithm logic

        rc4Wasm(RC4Algo.wasm).doProcess(nWordsReady, blockSize, dataArray, S_Array);
        dataWords = Array.from(dataArray);
        S = Array.from(S_Array);
        this._S = S.slice(0, 256);
        this._i = S[256];
        this._j = S[257]; // Remove processed words

        processedWords = dataWords.splice(0, nWordsReady); // write data back to this._data

        this._data.words = dataWords;
        data.sigBytes -= nBytesReady;
      } // Return processed words


      return new WordArray(processedWords, nBytesReady);
    }

  }
  /**
   * Shortcut functions to the cipher's object interface.
   *
   * @example
   *
   *     const ciphertext = CryptoJSW.RC4.encrypt(message, key, cfg);
   *     const plaintext  = CryptoJSW.RC4.decrypt(ciphertext, key, cfg);
   */

  _defineProperty(RC4Algo, "wasm", null);

  const RC4 = StreamCipher._createHelper(RC4Algo);
  /**
   * Modified RC4 stream cipher algorithm.
   */

  class RC4DropAlgo extends RC4Algo {
    constructor(...args) {
      super(...args);
      /**
       * Configuration options.
       *
       * @property {number} drop The number of keystream words to drop. Default 192
       */

      if (!this.cfg.drop) {
        Object.assign(this.cfg, {
          drop: 192
        });
      }
    }

    _doReset() {
      super._doReset.call(this); // Drop


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

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

  const RC4Drop = StreamCipher._createHelper(RC4DropAlgo);

  const wasmBytes = generateWasmBytes('[encoded data, 197488 characters]');

  let wasm;
  let globalThis$1;
  const heap = new Array(32).fill(undefined);
  heap.push(undefined, null, true, false);

  function getObject(idx) {
    return heap[idx];
  }

  let heap_next = heap.length;

  function dropObject(idx) {
    if (idx < 36) return;
    heap[idx] = heap_next;
    heap_next = idx;
  }

  function takeObject(idx) {
    const ret = getObject(idx);
    dropObject(idx);
    return ret;
  }

  const cachedTextDecoder = new TextDecoder('utf-8', {
    ignoreBOM: true,
    //fatal: true
  });
  cachedTextDecoder.decode();
  let cachedUint8Memory0 = new Uint8Array();

  function getUint8Memory0() {
    if (cachedUint8Memory0.byteLength === 0) {
      cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
    }

    return cachedUint8Memory0;
  }

  function getStringFromWasm0(ptr, len) {
    return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
  }

  function addHeapObject(obj) {
    if (heap_next === heap.length) heap.push(heap.length + 1);
    const idx = heap_next;
    heap_next = heap[idx];
    heap[idx] = obj;
    return idx;
  }

  function debugString(val) {
    // primitive types
    const type = typeof val;

    if (type == 'number' || type == 'boolean' || val == null) {
      return `${val}`;
    }

    if (type == 'string') {
      return `"${val}"`;
    }

    if (type == 'symbol') {
      const description = val.description;

      if (description == null) {
        return 'Symbol';
      } else {
        return `Symbol(${description})`;
      }
    }

    if (type == 'function') {
      const name = val.name;

      if (typeof name == 'string' && name.length > 0) {
        return `Function(${name})`;
      } else {
        return 'Function';
      }
    } // objects


    if (Array.isArray(val)) {
      const length = val.length;
      let debug = '[';

      if (length > 0) {
        debug += debugString(val[0]);
      }

      for (let i = 1; i < length; i++) {
        debug += ', ' + debugString(val[i]);
      }

      debug += ']';
      return debug;
    } // Test for built-in


    const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
    let className;

    if (builtInMatches.length > 1) {
      className = builtInMatches[1];
    } else {
      // Failed to match the standard '[object ClassName]'
      return toString.call(val);
    }

    if (className == 'Object') {
      // we're a user defined class or Object
      // JSON.stringify avoids problems with cycles, and is generally much
      // easier than looping through ownProperties of `val`.
      try {
        return 'Object(' + JSON.stringify(val) + ')';
      } catch (_) {
        return 'Object';
      }
    } // errors


    if (val instanceof Error) {
      return `${val.name}: ${val.message}\n${val.stack}`;
    } // TODO we could test for more things here, like `Set`s and `Map`s.


    return className;
  }

  let WASM_VECTOR_LEN = 0;
  const cachedTextEncoder = new TextEncoder('utf-8');
  const encodeString = typeof cachedTextEncoder.encodeInto === 'function' ? function (arg, view) {
    return cachedTextEncoder.encodeInto(arg, view);
  } : function (arg, view) {
    const buf = cachedTextEncoder.encode(arg);
    view.set(buf);
    return {
      read: arg.length,
      written: buf.length
    };
  };

  function passStringToWasm0(arg, malloc, realloc) {
    if (realloc === undefined) {
      const buf = cachedTextEncoder.encode(arg);
      const ptr = malloc(buf.length);
      getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
      WASM_VECTOR_LEN = buf.length;
      return ptr;
    }

    let len = arg.length;
    let ptr = malloc(len);
    const mem = getUint8Memory0();
    let offset = 0;

    for (; offset < len; offset++) {
      const code = arg.charCodeAt(offset);
      if (code > 0x7F) break;
      mem[ptr + offset] = code;
    }

    if (offset !== len) {
      if (offset !== 0) {
        arg = arg.slice(offset);
      }

      ptr = realloc(ptr, len, len = offset + arg.length * 3);
      const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
      const ret = encodeString(arg, view);
      offset += ret.written;
    }

    WASM_VECTOR_LEN = offset;
    return ptr;
  }

  let cachedInt32Memory0 = new Int32Array();

  function getInt32Memory0() {
    if (cachedInt32Memory0.byteLength === 0) {
      cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
    }

    return cachedInt32Memory0;
  }

  function isLikeNone(x) {
    return x === undefined || x === null;
  }

  function passArray8ToWasm0(arg, malloc) {
    const ptr = malloc(arg.length * 1);
    getUint8Memory0().set(arg, ptr / 1);
    WASM_VECTOR_LEN = arg.length;
    return ptr;
  }

  function getArrayU8FromWasm0(ptr, len) {
    return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
  }

  function handleError(f, args) {
    try {
      return f.apply(this, args);
    } catch (e) {
      wasm.__wbindgen_exn_store(addHeapObject(e));
    }
  }
  /**
   */


  class RsaPrivate {
    static __wrap(ptr) {
      const obj = Object.create(RsaPrivate.prototype);
      obj.ptr = ptr;
      return obj;
    }

    __destroy_into_raw() {
      const ptr = this.ptr;
      this.ptr = 0;
      return ptr;
    }

    free() {
      const ptr = this.__destroy_into_raw();

      wasm.__wbg_rsaprivate_free(ptr);
    }
    /**
     * @param {number | undefined} bits
     * @param {string | undefined} input_key_pem
     */


    constructor(bits, input_key_pem) {
      var ptr0 = isLikeNone(input_key_pem) ? 0 : passStringToWasm0(input_key_pem, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
      var len0 = WASM_VECTOR_LEN;
      const ret = wasm.rsaprivate_new(!isLikeNone(bits), isLikeNone(bits) ? 0 : bits, ptr0, len0);
      return RsaPrivate.__wrap(ret);
    }
    /**
     * @param {Uint8Array} ciphertext
     * @param {string} padding_scheme
     * @param {string} hash_function
     * @returns {Uint8Array}
     */


    decrypt(ciphertext, padding_scheme, hash_function) {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        const ptr0 = passArray8ToWasm0(ciphertext, wasm.__wbindgen_malloc);
        const len0 = WASM_VECTOR_LEN;
        const ptr1 = passStringToWasm0(padding_scheme, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
        const len1 = WASM_VECTOR_LEN;
        const ptr2 = passStringToWasm0(hash_function, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
        const len2 = WASM_VECTOR_LEN;
        wasm.rsaprivate_decrypt(retptr, this.ptr, ptr0, len0, ptr1, len1, ptr2, len2);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v3 = getArrayU8FromWasm0(r0, r1).slice();

        wasm.__wbindgen_free(r0, r1 * 1);

        return v3;
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);
      }
    }
    /**
     * @param {Uint8Array} digest
     * @param {string} padding_scheme
     * @param {string} hash_function
     * @returns {Uint8Array}
     */


    sign(digest, padding_scheme, hash_function) {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        const ptr0 = passArray8ToWasm0(digest, wasm.__wbindgen_malloc);
        const len0 = WASM_VECTOR_LEN;
        const ptr1 = passStringToWasm0(padding_scheme, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
        const len1 = WASM_VECTOR_LEN;
        const ptr2 = passStringToWasm0(hash_function, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
        const len2 = WASM_VECTOR_LEN;
        wasm.rsaprivate_sign(retptr, this.ptr, ptr0, len0, ptr1, len1, ptr2, len2);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v3 = getArrayU8FromWasm0(r0, r1).slice();

        wasm.__wbindgen_free(r0, r1 * 1);

        return v3;
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);
      }
    }
    /**
     * @param {string} fmt
     * @returns {any}
     */


    getPrivateKeyContent(fmt) {
      const ptr0 = passStringToWasm0(fmt, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
      const len0 = WASM_VECTOR_LEN;
      const ret = wasm.rsaprivate_getPrivateKeyContent(this.ptr, ptr0, len0);
      return takeObject(ret);
    }
    /**
     * @returns {string}
     */


    getPublicKeyPem() {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        wasm.rsaprivate_getPublicKeyPem(retptr, this.ptr);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        return getStringFromWasm0(r0, r1);
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);

        wasm.__wbindgen_free(r0, r1);
      }
    }

  }
  /**
   */

  class RsaPublic {
    static __wrap(ptr) {
      const obj = Object.create(RsaPublic.prototype);
      obj.ptr = ptr;
      return obj;
    }

    __destroy_into_raw() {
      const ptr = this.ptr;
      this.ptr = 0;
      return ptr;
    }

    free() {
      const ptr = this.__destroy_into_raw();

      wasm.__wbg_rsapublic_free(ptr);
    }
    /**
     * @param {string} input_key_pem
     */


    constructor(input_key_pem) {
      const ptr0 = passStringToWasm0(input_key_pem, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
      const len0 = WASM_VECTOR_LEN;
      const ret = wasm.rsapublic_new(ptr0, len0);
      return RsaPublic.__wrap(ret);
    }
    /**
     * @param {Uint8Array} msg
     * @param {string} padding_scheme
     * @param {string} hash_function
     * @returns {Uint8Array}
     */


    encrypt(msg, padding_scheme, hash_function) {
      try {
        const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);

        const ptr0 = passArray8ToWasm0(msg, wasm.__wbindgen_malloc);
        const len0 = WASM_VECTOR_LEN;
        const ptr1 = passStringToWasm0(padding_scheme, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
        const len1 = WASM_VECTOR_LEN;
        const ptr2 = passStringToWasm0(hash_function, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
        const len2 = WASM_VECTOR_LEN;
        wasm.rsapublic_encrypt(retptr, this.ptr, ptr0, len0, ptr1, len1, ptr2, len2);
        var r0 = getInt32Memory0()[retptr / 4 + 0];
        var r1 = getInt32Memory0()[retptr / 4 + 1];
        var v3 = getArrayU8FromWasm0(r0, r1).slice();

        wasm.__wbindgen_free(r0, r1 * 1);

        return v3;
      } finally {
        wasm.__wbindgen_add_to_stack_pointer(16);
      }
    }
    /**
     * @param {Uint8Array} digest
     * @param {Uint8Array} sig
     * @param {string} padding_scheme
     * @param {string} hash_function
     * @returns {boolean}
     */


    verify(digest, sig, padding_scheme, hash_function) {
      const ptr0 = passArray8ToWasm0(digest, wasm.__wbindgen_malloc);
      const len0 = WASM_VECTOR_LEN;
      const ptr1 = passArray8ToWasm0(sig, wasm.__wbindgen_malloc);
      const len1 = WASM_VECTOR_LEN;
      const ptr2 = passStringToWasm0(padding_scheme, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
      const len2 = WASM_VECTOR_LEN;
      const ptr3 = passStringToWasm0(hash_function, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
      const len3 = WASM_VECTOR_LEN;
      const ret = wasm.rsapublic_verify(this.ptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3);
      return ret !== 0;
    }
    /**
     * @returns {number}
     */


    getKeySize() {
      const ret = wasm.rsapublic_getKeySize(this.ptr);
      return ret >>> 0;
    }
    /**
     * @param {string} fmt
     * @returns {any}
     */


    getPublicKeyContent(fmt) {
      const ptr0 = passStringToWasm0(fmt, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
      const len0 = WASM_VECTOR_LEN;
      const ret = wasm.rsapublic_getPublicKeyContent(this.ptr, ptr0, len0);
      return takeObject(ret);
    }

  }

  function getImports() {
    const imports = {};
    imports.wbg = {};

    imports.wbg.__wbindgen_object_drop_ref = function (arg0) {
      takeObject(arg0);
    };

    imports.wbg.__wbindgen_string_new = function (arg0, arg1) {
      const ret = getStringFromWasm0(arg0, arg1);
      return addHeapObject(ret);
    };

    imports.wbg.__wbg_new_693216e109162396 = function () {
      const ret = new Error();
      return addHeapObject(ret);
    };

    imports.wbg.__wbg_stack_0ddaca5d1abfb52f = function (arg0, arg1) {
      const ret = getObject(arg1).stack;
      const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
      const len0 = WASM_VECTOR_LEN;
      getInt32Memory0()[arg0 / 4 + 1] = len0;
      getInt32Memory0()[arg0 / 4 + 0] = ptr0;
    };

    imports.wbg.__wbg_error_09919627ac0992f5 = function (arg0, arg1) {
      try {
        console.error(getStringFromWasm0(arg0, arg1));
      } finally {
        wasm.__wbindgen_free(arg0, arg1);
      }
    };

    imports.wbg.__wbindgen_number_new = function (arg0) {
      const ret = arg0;
      return addHeapObject(ret);
    };

    imports.wbg.__wbindgen_object_clone_ref = function (arg0) {
      const ret = getObject(arg0);
      return addHeapObject(ret);
    };

    imports.wbg.__wbindgen_is_undefined = function (arg0) {
      const ret = getObject(arg0) === undefined;
      return ret;
    };

    imports.wbg.__wbindgen_is_object = function (arg0) {
      const val = getObject(arg0);
      const ret = typeof val === 'object' && val !== null;
      return ret;
    };

    imports.wbg.__wbg_randomFillSync_91e2b39becca6147 = function () {
      return handleError(function (arg0, arg1, arg2) {
        getObject(arg0).randomFillSync(getArrayU8FromWasm0(arg1, arg2));
      }, arguments);
    };

    imports.wbg.__wbg_getRandomValues_b14734aa289bc356 = function () {
      return handleError(function (arg0, arg1) {
        getObject(arg0).getRandomValues(getObject(arg1));
      }, arguments);
    };

    imports.wbg.__wbg_process_e56fd54cf6319b6c = function (arg0) {
      const ret = getObject(arg0).process;
      return addHeapObject(ret);
    };

    imports.wbg.__wbg_versions_77e21455908dad33 = function (arg0) {
      const ret = getObject(arg0).versions;
      return addHeapObject(ret);
    };

    imports.wbg.__wbg_node_0dd25d832e4785d5 = function (arg0) {
      const ret = getObject(arg0).node;
      return addHeapObject(ret);
    };

    imports.wbg.__wbindgen_is_string = function (arg0) {
      const ret = typeof getObject(arg0) === 'string';
      return ret;
    };

    imports.wbg.__wbg_static_accessor_NODE_MODULE_26b231378c1be7dd = function () {
      const ret = module;
      return addHeapObject(ret);
    };

    imports.wbg.__wbg_require_0db1598d9ccecb30 = function () {
      return handleError(function (arg0, arg1, arg2) {
        const ret = getObject(arg0).require(getStringFromWasm0(arg1, arg2));

        return addHeapObject(ret);
      }, arguments);
    };

    imports.wbg.__wbg_crypto_b95d7173266618a9 = function (arg0) {
      const ret = getObject(arg0).crypto;
      return addHeapObject(ret);
    };

    imports.wbg.__wbg_msCrypto_5a86d77a66230f81 = function (arg0) {
      const ret = getObject(arg0).msCrypto;
      return addHeapObject(ret);
    };

    imports.wbg.__wbg_new_ee1a3da85465d621 = function () {
      const ret = new Array();
      return addHeapObject(ret);
    };

    imports.wbg.__wbg_newnoargs_971e9a5abe185139 = function (arg0, arg1) {
      const ret = new Function(getStringFromWasm0(arg0, arg1));
      return addHeapObject(ret);
    };

    imports.wbg.__wbg_call_33d7bcddbbfa394a = function () {
      return handleError(function (arg0, arg1) {
        const ret = getObject(arg0).call(getObject(arg1));
        return addHeapObject(ret);
      }, arguments);
    };

    imports.wbg.__wbg_self_fd00a1ef86d1b2ed = function () {
      return handleError(function () {
        const ret = self.self;
        return addHeapObject(ret);
      }, arguments);
    };

    imports.wbg.__wbg_window_6f6e346d8bbd61d7 = function () {
      return handleError(function () {
        const ret = window.window;
        return addHeapObject(ret);
      }, arguments);
    };

    imports.wbg.__wbg_globalThis_3348936ac49df00a = function () {
      return handleError(function () {
        const ret = globalThis$1.globalThis;
        return addHeapObject(ret);
      }, arguments);
    };

    imports.wbg.__wbg_global_67175caf56f55ca9 = function () {
      return handleError(function () {
        const ret = global.global;
        return addHeapObject(ret);
      }, arguments);
    };

    imports.wbg.__wbg_set_64cc39858b2ec3f1 = function (arg0, arg1, arg2) {
      getObject(arg0)[arg1 >>> 0] = takeObject(arg2);
    };

    imports.wbg.__wbg_buffer_34f5ec9f8a838ba0 = function (arg0) {
      const ret = getObject(arg0).buffer;
      return addHeapObject(ret);
    };

    imports.wbg.__wbg_new_cda198d9dbc6d7ea = function (arg0) {
      const ret = new Uint8Array(getObject(arg0));
      return addHeapObject(ret);
    };

    imports.wbg.__wbg_set_1a930cfcda1a8067 = function (arg0, arg1, arg2) {
      getObject(arg0).set(getObject(arg1), arg2 >>> 0);
    };

    imports.wbg.__wbg_length_51f19f73d6d9eff3 = function (arg0) {
      const ret = getObject(arg0).length;
      return ret;
    };

    imports.wbg.__wbg_newwithlength_66e5530e7079ea1b = function (arg0) {
      const ret = new Uint8Array(arg0 >>> 0);
      return addHeapObject(ret);
    };

    imports.wbg.__wbg_subarray_270ff8dd5582c1ac = function (arg0, arg1, arg2) {
      const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);
      return addHeapObject(ret);
    };

    imports.wbg.__wbindgen_debug_string = function (arg0, arg1) {
      const ret = debugString(getObject(arg1));
      const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
      const len0 = WASM_VECTOR_LEN;
      getInt32Memory0()[arg0 / 4 + 1] = len0;
      getInt32Memory0()[arg0 / 4 + 0] = ptr0;
    };

    imports.wbg.__wbindgen_throw = function (arg0, arg1) {
      throw new Error(getStringFromWasm0(arg0, arg1));
    };

    imports.wbg.__wbindgen_memory = function () {
      const ret = wasm.memory;
      return addHeapObject(ret);
    };

    return imports;
  }

  async function init() {
    await WebAssembly.instantiate(wasmBytes, getImports()).then(wasmInstance => {
      wasm = wasmInstance.instance.exports;
    });
    cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
    cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
  }

  const RSA_PADDING_OAEP = 'OAEP';
  const RSA_PADDING_PSS = 'PSS';
  const RSA_PADDING_PKCS1V15 = 'PKCS1V15';
  const RSA_PRIVATE_KEY_START = '-----BEGIN PRIVATE KEY-----';
  const RSA_PUBLIC_KEY_START = '-----BEGIN PUBLIC KEY-----';
  const DEFAULT_RSA_KEY_SIZE = 2048;
  const DEFAULT_IS_PUBLIC_KEY = false;
  const DEFAULT_RSA_ENCRYPT_PADDING = RSA_PADDING_OAEP;
  const DEFAULT_RSA_SIGN_PADDING = RSA_PADDING_PSS;
  const DEFAULT_RSA_HASH_ALGO = 'SHA256'; // TODO: what if a new hasher is added?

  const RSA_HASH_ALGOS = new Map([['MD5', MD5], ['SHA1', SHA1], ['SHA224', SHA224], ['SHA256', SHA256], ['SHA384', SHA384], ['SHA512', SHA512], ['RIPEMD160', RIPEMD160]]); // TODO: should extend AsymmetricCipher(class not created yet)

  class RSAAlgo {
    /**
     * Update the key of RSA. The input can be a path to the private/public key file, or the key size in bits
     *
     * @param keyFilePathOrKeySize {string | number} the key file path or key size in bytes, set as 2048 bits as default
     * @param isPublicKey true if the input key file is a public key file
     */
    updateRsaKey(keyFilePathOrKeySize = DEFAULT_RSA_KEY_SIZE, isPublicKey = DEFAULT_IS_PUBLIC_KEY) {
      parameterCheck(keyFilePathOrKeySize, 'RSA keyFilePathOrKeySize', ['number', 'string']);

      if (keyFilePathOrKeySize === RSAAlgo.keyFilePathOrKeySize && isPublicKey == RSAAlgo.isPublicKey) {
        // do not update keys if nothing changed
        return;
      }

      RSAAlgo.keyFilePathOrKeySize = keyFilePathOrKeySize;
      RSAAlgo.isPublicKey = isPublicKey;
      RSAAlgo.keyChanged = true;
    }

    static async loadWasm() {
      if (RSAAlgo.wasm) {
        return RSAAlgo.wasm;
      } // load wasm of available hashers


      [...RSA_HASH_ALGOS.values()].map(async hash => await hash.loadWasm());
      await init();
      RSAAlgo.wasm = true;
      return RSAAlgo.wasm;
    }

    async loadWasm() {
      return RSAAlgo.loadWasm();
    }
    /**
     * Constructor of RSAAlgo
     *
     * @param keyFilePathOrKeySize {string | number} the key file path or key size in bytes, set as 2048 bits as default
     * @param cfg {object} the config for rsa
     */


    constructor(keyFilePathOrKeySize, cfg) {
      this.resetConfig();
      this.updateRsaKey(keyFilePathOrKeySize);
      this.updateConfig(cfg);
    }
    /**
     * Reset configs to default values
     */


    resetConfig() {
      this.updateRsaKey(DEFAULT_RSA_KEY_SIZE, DEFAULT_IS_PUBLIC_KEY);
      this.updateEncryptPadding(DEFAULT_RSA_ENCRYPT_PADDING);
      this.updateSignPadding(DEFAULT_RSA_SIGN_PADDING);
      this.updateHashAlgo(DEFAULT_RSA_HASH_ALGO);
    }
    /**
     * Update the config for rsa. The configs of RSA are:
     * encryptPadding: encrypt padding mode, values may be 'OAEP'(default)/'PKCS1V15'
     * signPadding: sign padding mode, values may be 'PSS'(default)/'PKCS1V15'
     * hashAlgo: hasher for encryption and sign, values may be 'sha256'(default)/'md5'/'sha1'/'sha224'/'sha384'/'sha512'/'ripemd160'
     * key: can be path to the RSA key file(string), the content of RSA key(string), or the size of the RSA key(number)
     * isPublicKey: true if the cfg.key is the RSA public key
     *
     * @param cfg {object} the config for rsa
     */


    updateConfig(cfg) {
      if (cfg !== undefined) {
        if (cfg.encryptPadding !== undefined && typeof cfg.encryptPadding === 'string') {
          this.updateEncryptPadding(cfg.encryptPadding.toUpperCase());
        }

        if (cfg.signPadding !== undefined && typeof cfg.signPadding === 'string') {
          this.updateSignPadding(cfg.signPadding.toUpperCase());
        }

        if (cfg.hashAlgo !== undefined && typeof cfg.hashAlgo === 'string') {
          this.updateHashAlgo(cfg.hashAlgo.toUpperCase());
        }

        if (cfg.key !== undefined) {
          this.updateRsaKey(cfg.key, cfg.isPublicKey);
        }
      }
    }
    /**
     * init keys from key file or key size
     */


    initKeys() {
      if (!RSAAlgo.wasm) {
        throw new Error('WASM is not loaded yet. \'RSAAlgo.loadWasm\' should be called first');
      } // only update keys if key has been changed, and private/public key is specified


      if (!RSAAlgo.keyChanged && (this.RsaPrivate !== undefined || this.RsaPublic != undefined)) {
        return;
      }

      if (RSAAlgo.keyFilePathOrKeySize === undefined) {
        this.initFromKeySize(DEFAULT_RSA_KEY_SIZE);
        RSAAlgo.keyChanged = false;
        return;
      }

      if (typeof RSAAlgo.keyFilePathOrKeySize === 'number') {
        this.initFromKeySize(RSAAlgo.keyFilePathOrKeySize);
        RSAAlgo.keyChanged = false;
        return;
      }

      if (typeof RSAAlgo.keyFilePathOrKeySize === 'string') {
        if (this.isRsaKeyContent(RSAAlgo.keyFilePathOrKeySize)) {
          this.initFromKeyContent(RSAAlgo.keyFilePathOrKeySize, RSAAlgo.isPublicKey);
        } else {
          this.initFromKeyFile(RSAAlgo.keyFilePathOrKeySize, RSAAlgo.isPublicKey);
        }

        RSAAlgo.keyChanged = false;
        return;
      } // set the key size to default value


      this.initFromKeySize(DEFAULT_RSA_KEY_SIZE);
      RSAAlgo.keyChanged = false;
    }
    /**
     * Return true if the given string is a rsa key content
     *
     * @param content the input content
     * @returns {boolean} true if the given string is a rsa key content
     */


    isRsaKeyContent(content) {
      if (content.startsWith(RSA_PRIVATE_KEY_START) || content.startsWith(RSA_PUBLIC_KEY_START)) {
        return true;
      }

      return false;
    }
    /**
     * Init rsa keys with given key content
     *
     * @param keyContent the input key content
     * @param isPublicKey true if the input content is a public content
     */


    initFromKeyContent(keyContent, isPublicKey = DEFAULT_IS_PUBLIC_KEY) {
      isPublicKey ? this.initWithPublicKey(new RsaPublic(keyContent)) : this.initWithPrivateKey(new RsaPrivate(null, keyContent));
    }
    /**
     * Init rsa keys with given key file
     * @param path the input key file path
     * @param isPublicKey true if the input key file is a public key file
     */


    initFromKeyFile(path, isPublicKey = DEFAULT_IS_PUBLIC_KEY) {
      this.errorIfInBrowser();

      if (!RSAAlgo.wasm) {
        throw new Error('WASM is not loaded yet. \'RSAAlgo.loadWasm\' should be called first');
      }

      const fs = require('fs');

      if (!fs.existsSync(path)) {
        throw new Error('Can not find the key file in path :\n' + path);
      }

      const keyContent = fs.readFileSync(path, {
        encoding: 'utf-8',
        flag: 'r'
      });
      this.initFromKeyContent(keyContent, isPublicKey);
    }
    /**
     * Init rsa keys with given key size
     * @param bits key size in bytes
     */


    initFromKeySize(bits) {
      if (!RSAAlgo.wasm) {
        throw new Error('WASM is not loaded yet. \'RSAAlgo.loadWasm\' should be called first');
      }

      this.initWithPrivateKey(new RsaPrivate(bits));
    }
    /**
     * Update encrypt padding of RSA.
     * Valid values are 'OAEP', 'PKCS1V15'
     *
     * @param encryptPadding new padding mode of RSA encrypt
     */


    updateEncryptPadding(encryptPadding) {
      parameterCheck(encryptPadding, 'RSA encryption padding mode', 'string', RSA_PADDING_OAEP, RSA_PADDING_PKCS1V15);
      this.encryptPadding = encryptPadding;
    }
    /**
     * Update sign padding of RSA.
     * Valid values are 'PSS', 'PKCS1V15'
     *
     * @param signPadding new padding mode of RSA sign
     */


    updateSignPadding(signPadding) {
      parameterCheck(signPadding, 'RSA sign padding mode', 'string', RSA_PADDING_PSS, RSA_PADDING_PKCS1V15);
      this.signPadding = signPadding;
    }
    /**
     * Update hash algorithm of RSA.
     * Valid values are 'MD5', 'SHA1', 'SHA224', 'SHA256', 'SHA384', 'SHA512', 'RIPEMD160'
     *
     * @param hashAlgo new hash algorithm of RSA
     */


    updateHashAlgo(hashAlgo) {
      parameterCheck(hashAlgo, 'RSA hasher', 'string', 'MD5', 'SHA1', 'SHA224', 'SHA256', 'SHA384', 'SHA512', 'RIPEMD160');
      this.hashAlgo = hashAlgo;
    }
    /**
     * Initial RSA keys using public key
     *
     * @param publicKey the pointer to the new RSA public key
     */


    initWithPublicKey(publicKey) {
      if (!RSAAlgo.wasm) {
        throw new Error('WASM is not loaded yet. \'RSAAlgo.loadWasm\' should be called first');
      }

      this.RsaPublic = publicKey;
      this.RsaPrivate = null;
    }
    /**
     * Initial RSA keys using private key
     *
     * @param publicKey the pointer to the new RSA private key
     */


    initWithPrivateKey(privateKey) {
      if (!RSAAlgo.wasm) {
        throw new Error('WASM is not loaded yet. \'RSAAlgo.loadWasm\' should be called first');
      }

      if (privateKey === undefined) {
        // create a new DEFAULT_RSA_KEY_SIZE bit RSA key pair if no parameter is specified
        privateKey = new RsaPrivate(DEFAULT_RSA_KEY_SIZE);
      }

      const publicKey = new RsaPublic(privateKey.getPublicKeyPem());
      this.RsaPrivate = privateKey;
      this.RsaPublic = publicKey;
    }
    /**
     * Encrypt the given message
     *
     * @param {string | Uint8Array} msg the original message
     * @param {object} cfg RSA configurations
     * @returns {Uint8Array} the encrypted message
     */


    encrypt(msg, cfg) {
      this.updateConfig(cfg);
      this.initKeys();
      const msgInBytes = this.strToBytes(msg);
      this.errorIfExceedSizeLimit(msgInBytes, 'encrypt');
      return this.RsaPublic.encrypt(msgInBytes, this.encryptPadding, this.hashAlgo);
    }
    /**
     * Decrypt the given message
     *
     * @param {Uint8Array} msgEncrypted the encrypted message
     * @param {object} cfg RSA configurations
     * @returns {Uint8Array} the decrypted message
     */


    decrypt(msgEncrypted, cfg) {
      this.updateConfig(cfg);
      this.errorIfNoPrivateInstance();
      this.initKeys();
      let result;

      try {
        result = this.RsaPrivate.decrypt(msgEncrypted, this.encryptPadding, this.hashAlgo);
      } catch (e) {
        console.error('Error occurred when decrypting: ', e);
        return null;
      }

      return result;
    }
    /**
     * Generate the digest of the input message according to the specified hash algorithm
     *
     * @param {string} msg input message
     * @param {object} cfg RSA configurations
     * @returns {Uint8Array} the digest of input message
     */


    digest(msg, cfg) {
      this.updateConfig(cfg);
      let digestAlgo = RSA_HASH_ALGOS.get(this.hashAlgo);
      const digestWords = digestAlgo(msg);
      const digestUint32Array = new Uint32Array(digestWords.words).slice(0, digestWords.sigBytes / 4);
      const digest = new Uint8Array(digestUint32Array.buffer);
      return digest;
    }
    /**
     * RSA sign
     *
     * @param {string | Uint8Array} digest the digest of the message
     * @param {object} cfg RSA configurations
     * @returns {Uint8Array} the rsa signature
     */


    sign(digest, cfg) {
      this.updateConfig(cfg);
      this.initKeys();
      const digestInBytes = this.strToBytes(digest);
      this.errorIfNoPrivateInstance(digestInBytes, 'sign');
      return this.RsaPrivate.sign(digestInBytes, this.signPadding, this.hashAlgo);
    }
    /**
     * Verify the given RSA signature
     *
     * @param {Uint8Array} digest the digest of the message
     * @param {Uint8Array} signature the signature signed using private key
     * @param {object} cfg RSA configurations
     * @returns {boolean} true if signature is valid
     */


    verify(digest, signature, cfg) {
      this.updateConfig(cfg);
      this.initKeys();
      return this.RsaPublic.verify(digest, signature, this.signPadding, this.hashAlgo);
    }
    /**
     * generate the key file in specific directory
     *
     * @param {string} keyType valid values are 'pairs', 'private', 'public'. Default to be 'pairs'
     * @param {string} fileFmt file type of the generated key file. Valid values are 'pem', 'der'. Default to be 'pem'
     * @param {string} fileName the name of the generated key file
     * @param {string} dir the dir of the generated key file
     */


    generateKeyFile(keyType = 'pairs', fileFmt = 'pem', fileName = 'key', dir = './keys') {
      this.initKeys();
      this.errorIfInBrowser(); // key type and file fmt should be case insensitive

      keyType = keyType.toLowerCase();
      fileFmt = fileFmt.toLowerCase();

      switch (keyType) {
        case 'pairs':
          this.generateKeyFile('private', fileFmt, fileName + '_private', dir);
          this.generateKeyFile('public', fileFmt, fileName + '_public', dir);
          return;

        case 'private':
          this.errorIfNoPrivateInstance();
          break;

        case 'public':
          // no operations
          break;

        default:
          throw TypeError('wrong key type provided. Should be \'pairs\', \'private\' or \'public\'');
      }

      let keyPath = `${dir}/${fileName}.${fileFmt}`; // get key content based on fileFmt

      let keyContent = this.getKeyContent(keyType, fileFmt); // TODO: .der file cannot be verified by openssl
      // TODO: .der file key content is not TypedArray now

      const fs = require('fs'); // create dir if not existed


      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir);
      } // write key file


      fs.writeFileSync(keyPath, keyContent);
    }
    /**
     * Get current key type
     * @returns {string} key type, may be 'public' or 'private'
     */


    getKeyType() {
      this.initKeys();
      return this.RsaPrivate ? 'private' : 'public';
    }
    /**
     * Get current key size
     *
     * @returns {number} key size in bytes, e.g. 128 for key pair of 1024 bits
     */


    getKeySize() {
      this.initKeys();
      return this.RsaPublic.getKeySize();
    }
    /**
     * Get key content based on key type
     *
     * @param keyType the type of key files. Should be "private" or "public"
     * @param keyFmt the encoding scheme. Should be "pem" or "der"
     * @returns {string} the key content
     */


    getKeyContent(keyType, keyFmt = 'pem') {
      this.initKeys();

      if (keyType == 'private') {
        this.errorIfNoPrivateInstance();
        return this.RsaPrivate.getPrivateKeyContent(keyFmt);
      }

      if (keyType == 'public') {
        return this.RsaPublic.getPublicKeyContent(keyFmt);
      }

      throw TypeError('Key type should be private or public');
    } // TODO: should be moved to utils

    /**
     * String to Uint8Array
     * @param val
     * @returns {Uint8Array|*}
     */


    strToBytes(val) {
      if (typeof val === 'string') {
        let encoder = new TextEncoder();
        return encoder.encode(val);
      }

      return val;
    }
    /**
     * Throws if the input (message/digest) length exceed the limit decided by key size and padding scheme
     *
     * @param input the input message/digest
     * @param op the operation mode. Should be 'encrypt' or 'sign'
     */


    errorIfExceedSizeLimit(input, op = 'encrypt') {
      const keySize = this.getKeySize(); // 256 by default

      const hashAlgoOutputSize = RSA_HASH_ALGOS.get(this.hashAlgo).outputSize; // 32 by default

      let inputLimit;

      switch (op) {
        case 'encrypt':
          if (this.encryptPadding === RSA_PADDING_OAEP) {
            inputLimit = keySize - 2 * hashAlgoOutputSize - 2; // 190 by default
          } else {
            // PKCS1V15
            inputLimit = keySize - 11;
          }

          if (input.length > inputLimit) {
            throw new Error(`The input message is too long (${input.length} bytes). The maximum length is ${inputLimit}`);
          }

          break;

        case 'sign':
          if (this.signPadding === RSA_PADDING_PSS) {
            inputLimit = Math.floor((keySize * 8 - 9) / 2 / 8); // 127 by default
          } else {
            // PKCS1V15
            inputLimit = keySize - 11;
          }

          if (input.length > inputLimit) {
            throw new Error(`The input message is too long (${input.length} bytes). The maximum length is ${inputLimit}`);
          }

          break;

        default:
          throw new Error('op should be \'encrypt\' or \'sign\'');
      }
    }
    /**
     * Throws if private key is not instantiated
     */


    errorIfNoPrivateInstance() {
      if (this.getKeyType() === 'public') {
        throw TypeError('Private key or public key has not been instantiated');
      }
    }
    /**
     * Throws if node-only function is called in browser
     */


    errorIfInBrowser() {
      if (typeof window !== 'undefined' && typeof window.document !== 'undefined') {
        throw Error('This function is not supported in browser');
      }
    }

  }
  /**
   * Shortcut of RSAAlgo with an instantiated 2048 bits key pair
   * @name RSA
   * @type {RSAAlgo}
   *
   * @example
   *  // encrypt/decrypt
   *  const msg = "Secret";
   *  const msgEnc = C.RSA.encrypt(msg);
   *  const msgDec = C.RSA.decrypt(msgEnc);
   *
   *  // sign/verify
   *  const digest = C.RSA.digest(msg);
   *  const signature = RSA.sign(dig);
   *  const isVerified = RSA.verify(digest, signature);
   */

  _defineProperty(RSAAlgo, "wasm", null);

  _defineProperty(RSAAlgo, "keyFilePathOrKeySize", null);

  _defineProperty(RSAAlgo, "isPublicKey", false);

  _defineProperty(RSAAlgo, "keyChanged", false);

  const RSA = {
    // TODO: extract this into a helper class
    rsa: new RSAAlgo(),

    async loadWasm() {
      await RSAAlgo.loadWasm();
    },

    resetConfig() {
      this.rsa.resetConfig();
    },

    updateConfig(cfg) {
      this.rsa.updateConfig(cfg);
    },

    updateRsaKey(keyFilePathOrKeySize, isPublicKey) {
      this.rsa.updateRsaKey(keyFilePathOrKeySize, isPublicKey);
    },

    encrypt(message, cfg) {
      return this.rsa.encrypt(message, cfg);
    },

    decrypt(ciphertext, cfg) {
      return this.rsa.decrypt(ciphertext, cfg);
    },

    digest(message, cfg) {
      return this.rsa.digest(message, cfg);
    },

    sign(digest, cfg) {
      return this.rsa.sign(digest, cfg);
    },

    verify(digest, signature, cfg) {
      return this.rsa.verify(digest, signature, cfg);
    },

    generateKeyFile(keyType, fileFmt, fileName, dir) {
      return this.rsa.generateKeyFile(keyType, fileFmt, fileName, dir);
    },

    getKeyType() {
      return this.rsa.getKeyType();
    },

    getKeySize() {
      return this.rsa.getKeySize();
    },

    getKeyContent(keyType, keyFmt) {
      return this.rsa.getKeyContent(keyType, keyFmt);
    }

  };

  function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) {
    const _words = words;
    let keystream; // Shortcut

    const 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 (let i = 0; i < blockSize; i++) {
      _words[offset + i] ^= keystream[i];
    }
  }
  /**
   * Cipher Feedback block mode.
   */


  class CFB extends BlockCipherMode {
    static Encryptor() {}

  }

  _defineProperty(CFB, "_name", 'CFB');

  CFB.Encryptor = class extends CFB {
    processBlock(words, offset) {
      // Shortcuts
      const cipher = this._cipher;
      const {
        blockSize
      } = cipher;
      generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); // Remember this block to use with next block

      this._prevBlock = words.slice(offset, offset + blockSize);
    }

  };
  CFB.Decryptor = class extends CFB {
    processBlock(words, offset) {
      // Shortcuts
      const cipher = this._cipher;
      const {
        blockSize
      } = cipher; // Remember this block to use with next block

      const thisBlock = words.slice(offset, offset + blockSize);
      generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); // This block becomes the previous block

      this._prevBlock = thisBlock;
    }

  };

  class CTR extends BlockCipherMode {}

  _defineProperty(CTR, "_name", 'CTR');

  CTR.Encryptor = class extends CTR {
    processBlock(words, offset) {
      const _words = words; // Shortcuts

      const cipher = this._cipher;
      const {
        blockSize
      } = cipher;
      const iv = this._iv;
      let counter = this._counter; // Generate keystream

      if (iv) {
        this._counter = iv.slice(0);
        counter = this._counter; // Remove IV for subsequent blocks

        this._iv = undefined;
      }

      const keystream = counter.slice(0);
      cipher.encryptBlock(keystream, 0); // Increment counter

      counter[blockSize - 1] = counter[blockSize - 1] + 1 | 0; // Encrypt

      for (let i = 0; i < blockSize; i++) {
        _words[offset + i] ^= keystream[i];
      }
    }

  };
  CTR.Decryptor = CTR.Encryptor;

  const incWord = word => {
    let _word = word;

    if ((word >> 24 & 0xff) === 0xff) {
      // overflow
      let b1 = word >> 16 & 0xff;
      let b2 = word >> 8 & 0xff;
      let 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;
  };

  const incCounter = counter => {
    const _counter = counter;
    _counter[0] = incWord(_counter[0]);

    if (_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;
  };
  /** @preserve
   * Counter block mode compatible with  Dr Brian Gladman fileenc.c
   * derived from CryptoJS.mode.CTR
   * Jan Hruby jhruby.web@gmail.com
   */


  class CTRGladman extends BlockCipherMode {}

  _defineProperty(CTRGladman, "_name", 'CTRGladman');

  CTRGladman.Encryptor = class extends CTRGladman {
    processBlock(words, offset) {
      const _words = words; // Shortcuts

      const cipher = this._cipher;
      const {
        blockSize
      } = cipher;
      const iv = this._iv;
      let counter = this._counter; // Generate keystream

      if (iv) {
        this._counter = iv.slice(0);
        counter = this._counter; // Remove IV for subsequent blocks

        this._iv = undefined;
      }

      incCounter(counter);
      const keystream = counter.slice(0);
      cipher.encryptBlock(keystream, 0); // Encrypt

      for (let i = 0; i < blockSize; i++) {
        _words[offset + i] ^= keystream[i];
      }
    }

  };
  CTRGladman.Decryptor = CTRGladman.Encryptor;

  class ECB extends BlockCipherMode {}

  _defineProperty(ECB, "_name", 'ECB');

  ECB.Encryptor = class extends ECB {
    processBlock(words, offset) {
      this._cipher.encryptBlock(words, offset);
    }

  };
  ECB.Decryptor = class extends ECB {
    processBlock(words, offset) {
      this._cipher.decryptBlock(words, offset);
    }

  };

  class OFB extends BlockCipherMode {}

  _defineProperty(OFB, "_name", 'OFB');

  OFB.Encryptor = class extends OFB {
    processBlock(words, offset) {
      const _words = words; // Shortcuts

      const cipher = this._cipher;
      const {
        blockSize
      } = cipher;
      const iv = this._iv;
      let keystream = this._keystream; // Generate keystream

      if (iv) {
        this._keystream = iv.slice(0);
        keystream = this._keystream; // Remove IV for subsequent blocks

        this._iv = undefined;
      }

      cipher.encryptBlock(keystream, 0); // Encrypt

      for (let i = 0; i < blockSize; i++) {
        _words[offset + i] ^= keystream[i];
      }
    }

  };
  OFB.Decryptor = OFB.Encryptor;

  /**
   * ANSI X.923 padding strategy.
   */
  const AnsiX923 = {
    pad(data, blockSize) {
      const _data = data; // Shortcuts

      const dataSigBytes = _data.sigBytes;
      const blockSizeBytes = blockSize * 4; // Count padding bytes

      const nPaddingBytes = blockSizeBytes - dataSigBytes % blockSizeBytes; // Compute last byte position

      const lastBytePos = dataSigBytes + nPaddingBytes - 1; // Pad

      _data.clamp();

      _data.words[lastBytePos >>> 2] |= nPaddingBytes << 24 - lastBytePos % 4 * 8;
      _data.sigBytes += nPaddingBytes;
    },

    unpad(data) {
      const _data = data; // Get number of padding bytes from last byte

      const nPaddingBytes = _data.words[_data.sigBytes - 1 >>> 2] & 0xff; // Remove padding

      _data.sigBytes -= nPaddingBytes;
    }

  };

  /**
   * ISO 10126 padding strategy.
   */

  const Iso10126 = {
    pad(data, blockSize) {
      // Shortcut
      const blockSizeBytes = blockSize * 4; // Count padding bytes

      const nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; // Pad

      data.concat(WordArray.random(nPaddingBytes - 1)).concat(new WordArray([nPaddingBytes << 24], 1));
    },

    unpad(data) {
      const _data = data; // Get number of padding bytes from last byte

      const nPaddingBytes = _data.words[_data.sigBytes - 1 >>> 2] & 0xff; // Remove padding

      _data.sigBytes -= nPaddingBytes;
    }

  };

  /**
   * Zero padding strategy.
   */
  const ZeroPadding = {
    pad(data, blockSize) {
      const _data = data; // Shortcut

      const blockSizeBytes = blockSize * 4; // Pad

      _data.clamp();

      _data.sigBytes += blockSizeBytes - (data.sigBytes % blockSizeBytes || blockSizeBytes);
    },

    unpad(data) {
      const _data = data; // Shortcut

      const dataWords = _data.words; // Unpad

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

  };

  /**
   * ISO/IEC 9797-1 Padding Method 2.
   */

  const Iso97971 = {
    pad(data, blockSize) {
      // Add 0x80 byte
      data.concat(new WordArray([0x80000000], 1)); // Zero pad the rest

      ZeroPadding.pad(data, blockSize);
    },

    unpad(data) {
      const _data = data; // Remove zero padding

      ZeroPadding.unpad(_data); // Remove one more byte -- the 0x80 byte

      _data.sigBytes--;
    }

  };

  /**
   * A noop padding strategy.
   */
  const NoPadding = {
    pad() {},

    unpad() {}

  };

  const HexFormatter = {
    /**
     * 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
     *
     *     const hexString = CryptoJSW.format.Hex.stringify(cipherParams);
     */
    stringify(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
     *
     *     const cipherParams = CryptoJSW.format.Hex.parse(hexString);
     */
    parse(input) {
      const ciphertext = Hex.parse(input);
      return new CipherParams({
        ciphertext
      });
    }

  };

  var index = {
    lib: {
      Base,
      WordArray,
      BufferedBlockAlgorithm,
      Hasher,
      Cipher,
      StreamCipher,
      BlockCipherMode,
      BlockCipher,
      CipherParams,
      SerializableCipher,
      PasswordBasedCipher
    },
    x64: {
      Word: X64Word,
      WordArray: X64WordArray
    },
    enc: {
      Hex,
      Latin1,
      Utf8,
      Utf16,
      Utf16BE,
      Utf16LE,
      Base64
    },
    algo: {
      HMAC,
      MD5: MD5Algo,
      SHA1: SHA1Algo,
      SHA224: SHA224Algo,
      SHA256: SHA256Algo,
      SHA384: SHA384Algo,
      SHA512: SHA512Algo,
      SHA3: SHA3Algo,
      RIPEMD160: RIPEMD160Algo,
      PBKDF2: PBKDF2Algo,
      EvpKDF: EvpKDFAlgo,
      AES: AESAlgo,
      Blowfish: BlowfishAlgo,
      DES: DESAlgo,
      TripleDES: TripleDESAlgo,
      Rabbit: RabbitAlgo,
      RabbitLegacy: RabbitLegacyAlgo,
      RC4: RC4Algo,
      RC4Drop: RC4DropAlgo,
      RSA: RSAAlgo
    },
    mode: {
      CBC,
      CFB,
      CTR,
      CTRGladman,
      ECB,
      OFB
    },
    pad: {
      Pkcs7,
      AnsiX923,
      Iso10126,
      Iso97971,
      NoPadding,
      ZeroPadding
    },
    format: {
      OpenSSL: OpenSSLFormatter,
      Hex: HexFormatter
    },
    kdf: {
      OpenSSL: OpenSSLKdf
    },
    loadAllWasm,
    MD5,
    HmacMD5,
    SHA1,
    HmacSHA1,
    SHA224,
    HmacSHA224,
    SHA256,
    HmacSHA256,
    SHA384,
    HmacSHA384,
    SHA512,
    HmacSHA512,
    SHA3,
    HmacSHA3,
    RIPEMD160,
    HmacRIPEMD160,
    PBKDF2,
    EvpKDF,
    AES,
    Blowfish,
    DES,
    TripleDES,
    Rabbit,
    RabbitLegacy,
    RC4,
    RC4Drop,
    RSA
  };

  return index;

}));
