export = CryptoJS;

type WordArray = CryptoJS.lib.WordArray;
type CipherParams = CryptoJS.lib.CipherParams;
type X64Word = CryptoJS.x64.Word;

/**
 * Encoding strategy.
 */
interface Encoder {
  /**
   * Converts a word array to a hex string.
   *
   * @param wordArray The word array.
   *
   * @return The hex string.
   *
   * @example
   *
   *     var hexString = CryptoJS.enc.Hex.stringify(wordArray);
   */
  stringify(wordArray: WordArray): string;
  /**
   * Converts a hex string to a word array.
   *
   * @param hexStr The hex string.
   *
   * @return The word array.
   *
   * @example
   *
   *     var wordArray = CryptoJS.enc.Hex.parse(hexString);
   */
  parse(str: string): WordArray;
}

/**
 * Abstract buffered block algorithm template.
 *
 * The property blockSize must be implemented in a concrete subtype.
 */
interface BufferedBlockAlgorithm {
  /**
   * The number of blocks that should be kept unprocessed in the buffer. Default: 0
   */
  _minBufferSize: number;
  /**
   * Resets this block algorithm's data buffer to its initial state.
   *
   * @example
   *
   *     bufferedBlockAlgorithm.reset();
   */
  reset(): void;
  /**
   * Adds new data to this block algorithm's buffer.
   *
   * @param data The data to append. Strings are converted to a WordArray using UTF-8.
   *
   * @example
   *
   *     bufferedBlockAlgorithm._append('data');
   *     bufferedBlockAlgorithm._append(wordArray);
   */
  _append(data: WordArray | string): void;
  /**
   * Processes available data blocks.
   *
   * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
   *
   * @param doFlush Whether all blocks and partial blocks should be processed.
   *
   * @return The processed data.
   *
   * @example
   *
   *     var processedData = bufferedBlockAlgorithm._process();
   *     var processedData = bufferedBlockAlgorithm._process(!!'flush');
   */
  _process(doFlush?: boolean): WordArray;
  /**
   * Creates a copy of this object.
   *
   * @return The clone.
   *
   * @example
   *
   *     var clone = bufferedBlockAlgorithm.clone();
   */
  clone(): BufferedBlockAlgorithm;
}

/**
 * Abstract hasher template.
 */
interface Hasher {
  /**
   * The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
   */
  blockSize: number;
  /**
   * Resets this hasher to its initial state.
   *
   * @example
   *
   *     hasher.reset();
   */
  reset(): void;
  /**
   * Updates this hasher with a message.
   *
   * @param messageUpdate The message to append.
   *
   * @return This hasher.
   *
   * @example
   *
   *     hasher.update('message');
   *     hasher.update(wordArray);
   */
  update(messageUpdate: WordArray | string): this;
  /**
   * Finalizes the hash computation.
   * Note that the finalize operation is effectively a destructive, read-once operation.
   *
   * @param messageUpdate (Optional) A final message update.
   *
   * @return The hash.
   *
   * @example
   *
   *     var hash = hasher.finalize();
   *     var hash = hasher.finalize('message');
   *     var hash = hasher.finalize(wordArray);
   */
  finalize(messageUpdate?: WordArray | string): WordArray;
}

interface HasherStatic {
  /**
   * Initializes a newly created hasher.
   *
   * @param cfg (Optional) The configuration options to use for this hash computation.
   *
   * @example
   *
   *     var hasher = CryptoJS.algo.SHA256.create();
   */
  create(cfg?: object): Hasher;
}

interface HasherHelper {
  (message: WordArray | string, cfg?: object): WordArray;
}

interface HmacHasherHelper {
  (message: WordArray | string, key: WordArray | string): WordArray;
}

/**
 * Abstract base cipher template.
 */
interface Cipher {
  /**
   * This cipher's key size. Default: 4 (128 bits)
   */
  keySize: number;
  /**
   * This cipher's IV size. Default: 4 (128 bits)
   */
  ivSize: number;
  /**
   * A constant representing encryption mode.
   */
  readonly _ENC_XFORM_MODE: number;
  /**
   * A constant representing decryption mode.
   */
  readonly _DEV_XFORM_MODE: number;

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

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

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

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

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

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

interface CipherHelper {
  encrypt(
    message: WordArray | string,
    key: WordArray | string,
    cfg?: CipherOption
  ): CipherParams;
  decrypt(
    ciphertext: CipherParams | string,
    key: WordArray | string,
    cfg?: CipherOption
  ): WordArray;
}

/**
 * Configuration options.
 */
interface CipherOption {
  /**
   * The IV to use for this operation.
   */
  iv?: WordArray | undefined;
  format?: Format | undefined;
  [key: string]: any;
}

interface Mode {
  /**
   * Processes the data block at offset.
   *
   * @param words The data words to operate on.
   * @param offset The offset where the block starts.
   *
   * @example
   *
   *     mode.processBlock(data.words, offset);
   */
  processBlock(words: number[], offset: number): void;
}

interface ModeStatic {
  /**
   * Initializes a newly created mode.
   *
   * @param cipher A block cipher instance.
   * @param iv The IV words.
   *
   * @example
   *
   *     var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words);
   */
  create(cipher: Cipher, iv: number[]): Mode;
}

/**
 * Abstract base block cipher mode template.
 */
interface BlockCipherMode {
  Encryptor: ModeStatic;
  Decryptor: ModeStatic;
  /**
   * Creates this mode for encryption.
   *
   * @param cipher A block cipher instance.
   * @param iv The IV words.
   *
   * @example
   *
   *     var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words);
   */
  createEncryptor(cipher: Cipher, iv: number[]): Mode;

  /**
   * Creates this mode for decryption.
   *
   * @param cipher A block cipher instance.
   * @param iv The IV words.
   *
   * @example
   *
   *     var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words);
   */
  createDecryptor(cipher: Cipher, iv: number[]): Mode;
}

/**
 * Abstract base block cipher mode template.
 */
interface BlockCipherMode {
  /**
   * Creates this mode for encryption.
   *
   * @param cipher A block cipher instance.
   * @param iv The IV words.
   *
   * @example
   *
   *     var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words);
   */
  createEncryptor(cipher: Cipher): Mode;
}

/**
 * Padding strategy.
 */
interface Padding {
  /**
   * Pads data using the algorithm defined in PKCS #5/7.
   *
   * @param data The data to pad.
   * @param blockSize The multiple that the data should be padded to.
   *
   * @example
   *
   *     CryptoJS.pad.Pkcs7.pad(wordArray, 4);
   */
  pad(data: WordArray, blockSize: number): void;

  /**
   * Unpads data that had been padded using the algorithm defined in PKCS #5/7.
   *
   * @param data The data to unpad.
   *
   * @example
   *
   *     CryptoJS.pad.Pkcs7.unpad(wordArray);
   */
  unpad(data: WordArray): void;
}

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

/**
 * Configuration options.
 */
interface BlockCipherOption {
  /**
   * The block mode to use. Default: CBC
   */
  mode: Mode;
  /**
   * The padding strategy to use. Default: Pkcs7
   */
  padding: Padding;
}
/**
 * Formatting strategy.
 */
interface Format {
  /**
   * Converts a cipher params object to an OpenSSL-compatible string.
   *
   * @param cipherParams The cipher params object.
   *
   * @return The OpenSSL-compatible string.
   *
   * @example
   *
   *     var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams);
   */
  stringify(cipherParams: CipherParams): string;

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

/**
 * An array of 64-bit words.
 */
interface X64WordArray {
  /**
   * The array of CryptoJS.x64.Word objects.
   */
  words: number[];
  /**
   * The number of significant bytes in this word array.
   */
  sigBytes: number;

  /**
   * Converts this 64-bit word array to a 32-bit word array.
   *
   * @return This word array's data as a 32-bit word array.
   *
   * @example
   *
   *     var x32WordArray = x64WordArray.toX32();
   */
  toX32(): WordArray;

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

/**
 * Base object for prototypal inheritance.
 */
interface Base {
  /**
   * Creates a copy of this object.
   *
   * @return The clone.
   *
   * @example
   *
   *     var clone = instance.clone();
   */
  clone(): this;
}

/**
 * Configuration options.
 */
interface KDFOption {
  /**
   * The key size in words to generate.
   */
  keySize?: number | undefined;
  /**
   * The hasher to use.
   */
  hasher?: HasherStatic | undefined;
  /**
   * The number of iterations to perform.
   */
  iterations?: number | undefined;
}

declare global {
  namespace CryptoJS {
    /**
     * Library namespace.
     */
    export namespace lib {
      /**
       * Base object for prototypal inheritance.
       */
      const Base: {
        /**
         * Creates a new object that inherits from this object.
         *
         * @param overrides Properties to copy into the new object.
         *
         * @return The new object.
         *
         * @example
         *
         *     var MyType = CryptoJS.lib.Base.extend({
         *         field: 'value',
         *
         *         method: function () {
         *         }
         *     });
         */
        extend(overrides: object): any;

        /**
         * Extends this object and runs the init method.
         * Arguments to create() will be passed to init().
         *
         * @return The new object.
         *
         * @example
         *
         *     var instance = MyType.create();
         */
        create(...args: any[]): any;

        /**
         * Copies properties into this object.
         *
         * @param properties The properties to mix in.
         *
         * @example
         *
         *     MyType.mixIn({
         *         field: 'value'
         *     });
         */
        mixIn(properties: object): any;
      };

      /**
       * An array of 32-bit words.
       */
      interface WordArray {
        /**
         * The array of 32-bit words.
         */
        words: number[];
        /**
         * The number of significant bytes in this word array.
         */
        sigBytes: number;
        /**
         * Converts this word array to a string.
         *
         * @param encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
         *
         * @return The stringified word array.
         *
         * @example
         *
         *     var string = wordArray + '';
         *     var string = wordArray.toString();
         *     var string = wordArray.toString(CryptoJS.enc.Utf8);
         */
        toString(encoder?: Encoder): string;

        /**
         * Concatenates a word array to this word array.
         *
         * @param wordArray The word array to append.
         *
         * @return This word array.
         *
         * @example
         *
         *     wordArray1.concat(wordArray2);
         */
        concat(wordArray: WordArray): this;

        /**
         * Removes insignificant bits.
         *
         * @example
         *
         *     wordArray.clamp();
         */
        clamp(): void;

        /**
         * Creates a copy of this word array.
         *
         * @return The clone.
         *
         * @example
         *
         *     var clone = wordArray.clone();
         */
        clone(): WordArray;
      }
      const WordArray: {
        /**
         * Initializes a newly created word array.
         *
         * @param words (Optional) An array of 32-bit words.
         * @param sigBytes (Optional) The number of significant bytes in the words.
         *
         * @example
         *
         *     var wordArray = CryptoJS.lib.WordArray.create();
         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
         */
        create(
          words?:
            | number[]
            | ArrayBuffer
            | Uint8Array
            | Int8Array
            | Uint8ClampedArray
            | Int16Array
            | Uint16Array
            | Int32Array
            | Uint32Array
            | Float32Array
            | Float64Array,
          sigBytes?: number
        ): WordArray;
        /**
         * Creates a word array filled with random bytes.
         *
         * @param nBytes The number of random bytes to generate.
         *
         * @return The random word array.
         *
         * @example
         *
         *     var wordArray = CryptoJS.lib.WordArray.random(16);
         */
        random(nBytes: number): WordArray;
      };

      const BufferedBlockAlgorithm: any;

      const Hasher: {
        /**
         * Creates a shortcut function to a hasher's object interface.
         *
         * @param hasher The hasher to create a helper for.
         *
         * @return The shortcut function.
         *
         * @example
         *
         *     var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
         */
        _createHelper(hasher: HasherStatic): HasherHelper;
        /**
         * Creates a shortcut function to the HMAC's object interface.
         *
         * @param hasher The hasher to use in this HMAC helper.
         *
         * @return The shortcut function.
         *
         * @example
         *
         *     var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
         */
        _createHmacHelper(hasher: HasherStatic): HmacHasherHelper;
      };

      const Cipher: {
        /**
         * Creates shortcut functions to a cipher's object interface.
         *
         * @param cipher The cipher to create a helper for.
         *
         * @return An object with encrypt and decrypt shortcut functions.
         *
         * @example
         *
         *     var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES);
         */
        _createHelper(cipher: Cipher): CipherHelper;
      };

      /**
       * A collection of cipher parameters.
       */
      interface CipherParams {
        /**
         * The raw ciphertext.
         */
        ciphertext: WordArray;
        /**
         * The key to this ciphertext.
         */
        key: WordArray;
        /**
         * The IV used in the ciphering operation.
         */
        iv: WordArray;
        /**
         * The salt used with a key derivation function.
         */
        salt: WordArray;
        /**
         * The cipher algorithm.
         */
        algorithm: CipherStatic;
        /**
         * The block mode used in the ciphering operation.
         */
        mode: Mode;
        /**
         * The padding scheme used in the ciphering operation.
         */
        padding: Padding;
        /**
         * The block size of the cipher.
         */
        blockSize: number;
        /**
         * The default formatting strategy to convert this cipher params object to a string.
         */
        formatter: Format;
        /**
         * Converts this cipher params object to a string.
         *
         * @param formatter (Optional) The formatting strategy to use.
         *
         * @return The stringified cipher params.
         *
         * @throws Error If neither the formatter nor the default formatter is set.
         *
         * @example
         *
         *     var string = cipherParams + '';
         *     var string = cipherParams.toString();
         *     var string = cipherParams.toString(CryptoJS.format.OpenSSL);
         */
        toString(formatter?: Format): string;
      }
      const CipherParams: {
        /**
         * Initializes a newly created cipher params object.
         *
         * @param cipherParams An object with any of the possible cipher parameters.
         *
         * @example
         *
         *     var cipherParams = CryptoJS.lib.CipherParams.create({
         *         ciphertext: ciphertextWordArray,
         *         key: keyWordArray,
         *         iv: ivWordArray,
         *         salt: saltWordArray,
         *         algorithm: CryptoJS.algo.AES,
         *         mode: CryptoJS.mode.CBC,
         *         padding: CryptoJS.pad.PKCS7,
         *         blockSize: 4,
         *         formatter: CryptoJS.format.OpenSSL
         *     });
         */
        create(cipherParams: Partial<CipherParams>): CipherParams;
      };

      /**
       * Abstract base stream cipher template.
       */
      interface StreamCipher extends Cipher {
        /**
         * The number of 32-bit words this cipher operates on. Default: 1 (32 bits)
         */
        blockSize: number;
      }

      /**
       * Abstract base block cipher mode template.
       */
      const BlockCipherMode: any;

      /**
       * A cipher wrapper that returns ciphertext as a serializable cipher params object.
       */
      const SerializableCipher: {
        /**
         * Encrypts a message.
         *
         * @param cipher The cipher algorithm to use.
         * @param message The message to encrypt.
         * @param key The key.
         * @param cfg (Optional) The configuration options to use for this operation.
         *
         * @return A cipher params object.
         *
         * @example
         *
         *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key);
         *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv });
         *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL });
         */
        encrypt(
          cipher: CipherStatic,
          message: WordArray | string,
          key: WordArray,
          cfg?: CipherOption
        ): CipherParams;

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

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

      /**
       * A serializable cipher wrapper that derives the key from a password,
       * and returns ciphertext as a serializable cipher params object.
       */
      const PasswordBasedCipher: {
        /**
         * Encrypts a message using a password.
         *
         * @param cipher The cipher algorithm to use.
         * @param message The message to encrypt.
         * @param password The password.
         * @param cfg (Optional) The configuration options to use for this operation.
         *
         * @return A cipher params object.
         *
         * @example
         *
         *     var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password');
         *     var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL });
         */
        encrypt(
          cipher: CipherStatic,
          message: WordArray | string,
          password: string,
          cfg?: CipherOption
        ): CipherParams;

        /**
         * Decrypts serialized ciphertext using a password.
         *
         * @param cipher The cipher algorithm to use.
         * @param ciphertext The ciphertext to decrypt.
         * @param password The password.
         * @param cfg (Optional) The configuration options to use for this operation.
         *
         * @return The plaintext.
         *
         * @example
         *
         *     var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL });
         *     var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL });
         */
        decrypt(
          cipher: CipherStatic,
          ciphertext: CipherParams | string,
          password: string,
          cfg?: CipherOption
        ): WordArray;
      };
    }
    /**
     * Padding namespace.
     */
    export namespace pad {
      /**
       * PKCS #5/7 padding strategy.
       */
      const Pkcs7: Padding;

      /**
       * ANSI X.923 padding strategy.
       */
      const AnsiX923: Padding;

      /**
       * ISO 10126 padding strategy.
       */
      const Iso10126: Padding;

      /**
       * ISO/IEC 9797-1 Padding Method 2.
       */
      const Iso97971: Padding;

      /**
       * Zero padding strategy.
       */
      const ZeroPadding: Padding;

      /**
       * A noop padding strategy.
       */
      const NoPadding: Padding;
    }

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

    /**
     * Mode namespace.
     */
    export namespace mode {
      /**
       * Cipher Block Chaining mode.
       */
      const CBC: BlockCipherMode;

      /**
       * Cipher Feedback block mode.
       */
      const CFB: BlockCipherMode;
      /**
       * Counter block mode.
       */
      const CTR: BlockCipherMode;
      /**
       * @preserve
       * Counter block mode compatible with  Dr Brian Gladman fileenc.c
       * derived from CryptoJS.mode.CTR
       * Jan Hruby jhruby.web@gmail.com
       */
      const CTRGladman: BlockCipherMode;
      /**
       * Output Feedback block mode.
       */
      const OFB: BlockCipherMode;

      /**
       * Electronic Codebook block mode.
       */
      const ECB: BlockCipherMode;
    }

    /**
     * Format namespace.
     */
    export namespace format {
      /**
       * OpenSSL formatting strategy.
       */
      const OpenSSL: Format;
      const Hex: Format;
    }

    /**
     * Encoder namespace.
     */
    export namespace enc {
      /**
       * Hex encoding strategy.
       */
      const Hex: Encoder;
      /**
       * Latin1 encoding strategy.
       */
      const Latin1: Encoder;
      /**
       * UTF-8 encoding strategy.
       */
      const Utf8: Encoder;
      /**
       * UTF-16 BE encoding strategy.
       */
      const Utf16: Encoder;
      const Utf16BE: Encoder;

      /**
       * UTF-16 LE encoding strategy.
       */
      const Utf16LE: Encoder;
      /**
       * Base64 encoding strategy.
       */
      const Base64: Encoder;
      /**
       * Base64url encoding strategy.
       */
      const Base64url: Encoder;
    }

    /**
     * Algorithm namespace.
     */
    export namespace algo {
      /**
       * MD5 hash algorithm.
       */
      const MD5: HasherStatic;

      /**
       * SHA-1 hash algorithm.
       */
      const SHA1: HasherStatic;

      /**
       * SHA-256 hash algorithm.
       */
      const SHA256: HasherStatic;
      /**
       * SHA-224 hash algorithm.
       */
      const SHA224: HasherStatic;
      /**
       * SHA-512 hash algorithm.
       */
      const SHA512: HasherStatic;

      /**
       * SHA-384 hash algorithm.
       */
      const SHA384: HasherStatic;
      /**
       * SHA-3 hash algorithm.
       */
      const SHA3: HasherStatic;
      /**
       * RIPEMD160 hash algorithm.
       */
      const RIPEMD160: HasherStatic;
      /**
       * HMAC algorithm.
       */
      abstract class HMAC {
        /**
         * Initializes a newly created HMAC.
         *
         * @param hasher The hash algorithm to use.
         * @param key The secret key.
         *
         * @example
         *
         *     var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
         */
        static create(hasher: HasherStatic, key: WordArray | string): HMAC;
        /**
         * Resets this HMAC to its initial state.
         *
         * @example
         *
         *     hmacHasher.reset();
         */
        reset(): void;

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

        /**
         * Finalizes the HMAC computation.
         * Note that the finalize operation is effectively a destructive, read-once operation.
         *
         * @param messageUpdate (Optional) A final message update.
         *
         * @return The HMAC.
         *
         * @example
         *
         *     var hmac = hmacHasher.finalize();
         *     var hmac = hmacHasher.finalize('message');
         *     var hmac = hmacHasher.finalize(wordArray);
         */
        finalize(messageUpdate?: WordArray | string): WordArray;
      }
      /**
       * Password-Based Key Derivation Function 2 algorithm.
       */
      abstract class PBKDF2 {
        /**
         * Initializes a newly created key derivation function.
         *
         * @param cfg (Optional) The configuration options to use for the derivation.
         *
         * @example
         *
         *     var kdf = CryptoJS.algo.PBKDF2.create();
         *     var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 });
         *     var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 });
         */
        static create(cfg?: KDFOption): PBKDF2;

        /**
         * Computes the Password-Based Key Derivation Function 2.
         *
         * @param password The password.
         * @param salt A salt.
         *
         * @return The derived key.
         *
         * @example
         *
         *     var key = kdf.compute(password, salt);
         */
        compute(password: WordArray | string, salt: WordArray): WordArray;
      }
      /**
       * This key derivation function is meant to conform with EVP_BytesToKey.
       * www.openssl.org/docs/crypto/EVP_BytesToKey.html
       */
      abstract class EvpKDF {
        /**
         * Initializes a newly created key derivation function.
         *
         * @param cfg (Optional) The configuration options to use for the derivation.
         *
         * @example
         *
         *     var kdf = CryptoJS.algo.EvpKDF.create();
         *     var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 });
         *     var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 });
         */
        static create(cfg?: {
          keySize: number;
          hasher?: HasherStatic | undefined;
          iterations: number;
        }): EvpKDF;

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

      /**
       * AES block cipher algorithm.
       */
      const AES: CipherStatic;

      /**
       * SEED block cipher algorithm.
       */
      const SEED: CipherStatic;

      /**
       * DES block cipher algorithm.
       */
      const DES: CipherStatic;

      /**
       * Triple-DES block cipher algorithm.
       */
      const TripleDES: CipherStatic;

      /**
       * RC4 stream cipher algorithm.
       */
      const RC4: CipherStatic;

      /**
       * Modified RC4 stream cipher algorithm.
       */
      const RC4Drop: CipherStatic;

      /**
       * Rabbit stream cipher algorithm
       */
      const Rabbit: CipherStatic;

      /**
       * 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.
       */
      const RabbitLegacy: CipherStatic;
    }

    /**
     * x64 namespace.
     */
    export namespace x64 {
      /**
       * A 64-bit word.
       */
      interface Word {
        /**
         * Bitwise NOTs this word.
         *
         * @return A new x64-Word object after negating.
         *
         * @example
         *
         *     var negated = x64Word.not();
         */
        not(): X64Word;
        /**
         * Bitwise ANDs this word with the passed word.
         *
         * @param word The x64-Word to AND with this word.
         *
         * @return A new x64-Word object after ANDing.
         *
         * @example
         *
         *     var anded = x64Word.and(anotherX64Word);
         */
        and(word: X64Word): X64Word;

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

        /**
         * Bitwise XORs this word with the passed word.
         *
         * @param word The x64-Word to XOR with this word.
         *
         * @return A new x64-Word object after XORing.
         *
         * @example
         *
         *     var xored = x64Word.xor(anotherX64Word);
         */
        xor(word: X64Word): X64Word;
        /**
         * Shifts this word n bits to the left.
         *
         * @param n The number of bits to shift.
         *
         * @return A new x64-Word object after shifting.
         *
         * @example
         *
         *     var shifted = x64Word.shiftL(25);
         */
        shiftL(n: number): X64Word;
        /**
         * Shifts this word n bits to the right.
         *
         * @param n The number of bits to shift.
         *
         * @return A new x64-Word object after shifting.
         *
         * @example
         *
         *     var shifted = x64Word.shiftR(7);
         */
        shiftR(n: number): X64Word;
        /**
         * Rotates this word n bits to the left.
         *
         * @param n The number of bits to rotate.
         *
         * @return A new x64-Word object after rotating.
         *
         * @example
         *
         *     var rotated = x64Word.rotL(25);
         */
        rotL(n: number): X64Word;

        /**
         * Rotates this word n bits to the right.
         *
         * @param n The number of bits to rotate.
         *
         * @return A new x64-Word object after rotating.
         *
         * @example
         *
         *     var rotated = x64Word.rotR(7);
         */
        rotR(n: number): X64Word;
        /**
         * Adds this word with the passed word.
         *
         * @param word The x64-Word to add with this word.
         *
         * @return A new x64-Word object after adding.
         *
         * @example
         *
         *     var added = x64Word.add(anotherX64Word);
         */
        add(word: X64Word): X64Word;
      }

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

      /**
       * Initializes a newly created word array.
       *
       * @param words (Optional) An array of CryptoJS.x64.Word objects.
       * @param sigBytes (Optional) The number of significant bytes in the words.
       *
       * @example
       *
       *     var wordArray = CryptoJS.x64.WordArray.create();
       *
       *     var wordArray = CryptoJS.x64.WordArray.create([
       *         CryptoJS.x64.Word.create(0x00010203, 0x04050607),
       *         CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f)
       *     ]);
       *
       *     var wordArray = CryptoJS.x64.WordArray.create([
       *         CryptoJS.x64.Word.create(0x00010203, 0x04050607),
       *         CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f)
       *     ], 10);
       */
      const WordArray: {
        create(words?: X64WordArray[], sigBytes?: number): X64WordArray;
      };
    }

    /**
     * Shortcut function to the hasher's object interface.
     *
     * @param message The message to hash.
     *
     * @return The hash.
     *
     * @example
     *
     *     var hash = CryptoJS.MD5('message');
     *     var hash = CryptoJS.MD5(wordArray);
     */
    export const MD5: HasherHelper;
    /**
     * Shortcut function to the HMAC's object interface.
     *
     * @param message The message to hash.
     * @param key The secret key.
     *
     * @return The HMA'C.
     *
     * @example
     *
     *     var hmac = CryptoJS.HmacMD5(message, key);
     */
    export const HmacMD5: HmacHasherHelper;
    /**
     * Shortcut function to the hasher's object interface.
     *
     * @param message The message to hash.
     *
     * @return The hash.
     *
     * @example
     *
     *     var hash = CryptoJS.SHA1('message');
     *     var hash = CryptoJS.SHA1(wordArray);
     */
    export const SHA1: HasherHelper;
    /**
     * Shortcut function to the HMAC's object interface.
     *
     * @param message The message to hash.
     * @param key The secret key.
     *
     * @return The HMAC.
     *
     * @example
     *
     *     var hmac = CryptoJS.HmacSHA1(message, key);
     */
    export const HmacSHA1: HmacHasherHelper;

    /**
     * Shortcut function to the hasher's object interface.
     *
     * @param message The message to hash.
     *
     * @return The hash.
     *
     * @example
     *
     *     var hash = CryptoJS.SHA256('message');
     *     var hash = CryptoJS.SHA256(wordArray);
     */
    export const SHA256: HasherHelper;
    /**
     * Shortcut function to the HMAC's object interface.
     *
     * @param message The message to hash.
     * @param key The secret key.
     *
     * @return The HMAC.
     *
     * @example
     *
     *     var hmac = CryptoJS.HmacSHA256(message, key);
     */
    export const HmacSHA256: HmacHasherHelper;
    /**
     * Shortcut function to the hasher's object interface.
     *
     * @param message The message to hash.
     *
     * @return The hash.
     *
     * @example
     *
     *     var hash = CryptoJS.SHA224('message');
     *     var hash = CryptoJS.SHA224(wordArray);
     */
    export const SHA224: HasherHelper;
    /**
     * Shortcut function to the HMAC's object interface.
     *
     * @param message The message to hash.
     * @param key The secret key.
     *
     * @return The HMAC.
     *
     * @example
     *
     *     var hmac = CryptoJS.HmacSHA224(message, key);
     */
    export const HmacSHA224: HmacHasherHelper;
    /**
     * Shortcut function to the hasher's object interface.
     *
     * @param message The message to hash.
     *
     * @return The hash.
     *
     * @example
     *
     *     var hash = CryptoJS.SHA512('message');
     *     var hash = CryptoJS.SHA512(wordArray);
     */
    export const SHA512: HasherHelper;
    /**
     * Shortcut function to the HMAC's object interface.
     *
     * @param message The message to hash.
     * @param key The secret key.
     *
     * @return The HMAC.
     *
     * @example
     *
     *     var hmac = CryptoJS.HmacSHA512(message, key);
     */
    export const HmacSHA512: HmacHasherHelper;
    /**
     * Shortcut function to the hasher's object interface.
     *
     * @param message The message to hash.
     *
     * @return The hash.
     *
     * @example
     *
     *     var hash = CryptoJS.SHA384('message');
     *     var hash = CryptoJS.SHA384(wordArray);
     */
    export const SHA384: HasherHelper;
    /**
     * Shortcut function to the HMAC's object interface.
     *
     * @param message The message to hash.
     * @param key The secret key.
     *
     * @return The HMAC.
     *
     * @example
     *
     *     var hmac = CryptoJS.HmacSHA384(message, key);
     */
    export const HmacSHA384: HmacHasherHelper;

    /**
     * Shortcut function to the hasher's object interface.
     *
     * @param message The message to hash.
     *
     * @return The hash.
     *
     * @example
     *
     *     var hash = CryptoJS.SHA3('message');
     *     var hash = CryptoJS.SHA3(wordArray);
     */
    export const SHA3: HasherHelper;
    /**
     * Shortcut function to the HMAC's object interface.
     *
     * @param message The message to hash.
     * @param key The secret key.
     *
     * @return The HMAC.
     *
     * @example
     *
     *     var hmac = CryptoJS.HmacSHA3(message, key);
     */
    export const HmacSHA3: HmacHasherHelper;

    /**
     * Shortcut function to the hasher's object interface.
     *
     * @param message The message to hash.
     *
     * @return The hash.
     *
     * @example
     *
     *     var hash = CryptoJS.RIPEMD160('message');
     *     var hash = CryptoJS.RIPEMD160(wordArray);
     */
    export const RIPEMD160: HasherHelper;
    /**
     * Shortcut function to the HMAC's object interface.
     *
     * @param message The message to hash.
     * @param key The secret key.
     *
     * @return The HMAC.
     *
     * @example
     *
     *     var hmac = CryptoJS.HmacRIPEMD160(message, key);
     */
    export const HmacRIPEMD160: HmacHasherHelper;
    /**
     * Computes the Password-Based Key Derivation Function 2.
     *
     * @param password The password.
     * @param salt A salt.
     * @param cfg (Optional) The configuration options to use for this computation.
     *
     * @return The derived key.
     *
     * @example
     *
     *     var key = CryptoJS.PBKDF2(password, salt);
     *     var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 });
     *     var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 });
     */
    export function PBKDF2(
      password: WordArray | string,
      salt: WordArray | string,
      cfg?: KDFOption
    ): WordArray;

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

    /**
     * Shortcut functions to the cipher's object interface.
     *
     * @example
     *
     *     var ciphertext = CryptoJS.SEED.encrypt(message, key, cfg);
     *     var plaintext  = CryptoJS.SEED.decrypt(ciphertext, key, cfg);
     */
    export const SEED: CipherHelper;

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

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

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

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

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

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

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

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