{"version":3,"file":"cipher-core.cjs","names":["BufferedBlockAlgorithm","Base","block: number[] | undefined","Pkcs7: Padding","paddingWords: number[]","WordArray","modeCreator: ((cipher: Cipher, iv?: number[]) => BlockCipherMode) | undefined","finalProcessedBlocks: WordArray","OpenSSLFormatter: Format","wordArray: WordArray","Base64","salt: WordArray | undefined","OpenSSLKdf: Kdf","_salt: WordArray","Hex","key: WordArray","EvpKDFAlgo"],"sources":["../src/cipher-core.ts"],"sourcesContent":["/* eslint-disable no-use-before-define */\n\nimport {\n  Base,\n  WordArray,\n  BufferedBlockAlgorithm,\n  Hasher,\n  HasherCfg,\n  Hex,\n} from './core';\nimport { Base64 } from './enc-base64';\nimport { EvpKDFAlgo } from './evpkdf';\n\n// Re-export WordArray for convenience\nexport { WordArray } from './core';\n\n/**\n * Configuration options for ciphers\n */\nexport interface CipherCfg {\n  /** Initialization vector */\n  iv?: WordArray;\n  /** Block cipher mode */\n  mode?: typeof BlockCipherMode;\n  /** Padding strategy */\n  padding?: Padding;\n  /** Formatter for serialization */\n  format?: Format;\n  /** Key derivation function */\n  kdf?: Kdf;\n  /** Salt for key derivation */\n  salt?: WordArray | string;\n  /** Hasher for key derivation */\n  hasher?: new (cfg?: HasherCfg) => Hasher;\n  /** Drop value for RC4Drop */\n  drop?: number;\n}\n\n/**\n * Cipher parameters configuration\n */\nexport interface CipherParamsCfg {\n  /** The raw ciphertext */\n  ciphertext?: WordArray;\n  /** The key to this ciphertext */\n  key?: WordArray;\n  /** The IV used in the ciphering operation */\n  iv?: WordArray;\n  /** The salt used with a key derivation function */\n  salt?: WordArray;\n  /** The cipher algorithm */\n  algorithm?: typeof Cipher;\n  /** The block mode used in the ciphering operation */\n  mode?: typeof BlockCipherMode;\n  /** The padding scheme used in the ciphering operation */\n  padding?: Padding;\n  /** The block size of the cipher */\n  blockSize?: number;\n  /** The default formatting strategy */\n  formatter?: Format;\n  /** Allow additional properties */\n  [key: string]: unknown;\n}\n\n/**\n * Cipher object interface\n */\nexport interface CipherObj {\n  /**\n   * Encrypts a message\n   * @param message - The message to encrypt\n   * @param key - The key\n   * @param cfg - Configuration options\n   * @returns The encrypted cipher params\n   */\n  encrypt(message: WordArray | string, key: WordArray | string, cfg?: CipherCfg): CipherParams;\n  \n  /**\n   * Decrypts ciphertext\n   * @param ciphertext - The ciphertext to decrypt\n   * @param key - The key\n   * @param cfg - Configuration options\n   * @returns The decrypted plaintext\n   */\n  decrypt(ciphertext: CipherParams | CipherParamsCfg | string, key: WordArray | string, cfg?: CipherCfg): WordArray;\n}\n\n/**\n * Padding strategy interface\n */\nexport interface Padding {\n  /**\n   * Pads data to a multiple of blockSize\n   * @param data - The data to pad\n   * @param blockSize - The block size in words\n   */\n  pad(data: WordArray, blockSize: number): void;\n  \n  /**\n   * Unpads data\n   * @param data - The data to unpad\n   */\n  unpad(data: WordArray): void;\n}\n\n/**\n * Format strategy interface\n */\nexport interface Format {\n  /**\n   * Converts cipher params to string\n   * @param cipherParams - The cipher params\n   * @returns The string representation\n   */\n  stringify(cipherParams: CipherParams): string;\n  \n  /**\n   * Parses string to cipher params\n   * @param str - The string to parse\n   * @param cipher - The cipher class\n   * @returns The cipher params\n   */\n  parse(str: string, cipher?: any): CipherParams;\n}\n\n/**\n * Key derivation function interface\n */\nexport interface Kdf {\n  /**\n   * Derives key and IV from password\n   * @param password - The password\n   * @param keySize - Key size in words\n   * @param ivSize - IV size in words\n   * @param salt - Optional salt\n   * @param hasher - Optional hasher\n   * @returns The derived cipher params\n   */\n  execute(\n    password: string,\n    keySize: number,\n    ivSize: number,\n    salt?: WordArray | string,\n    hasher?: new (cfg?: HasherCfg) => Hasher\n  ): CipherParams;\n}\n\n/**\n * Abstract base cipher template.\n * Provides the foundation for all encryption and decryption algorithms.\n * \n * @property keySize - This cipher's key size in words (default: 4 = 128 bits)\n * @property ivSize - This cipher's IV size in words (default: 4 = 128 bits)\n * @property _ENC_XFORM_MODE - A constant representing encryption mode\n * @property _DEC_XFORM_MODE - A constant representing decryption mode\n */\nexport abstract class Cipher extends BufferedBlockAlgorithm {\n  /** Encryption mode constant */\n  static readonly _ENC_XFORM_MODE: number = 1;\n  \n  /** Decryption mode constant */\n  static readonly _DEC_XFORM_MODE: number = 2;\n  \n  /** Default key size in words (128 bits) */\n  static keySize: number = 128 / 32;\n  \n  /** Default IV size in words (128 bits) */\n  static ivSize: number = 128 / 32;\n  \n  /** Configuration options */\n  cfg: CipherCfg;\n  \n  /** Transform mode (encryption or decryption) */\n  protected _xformMode: number;\n  \n  /** The key */\n  protected _key: WordArray;\n  \n  /** Block size in words */\n  blockSize: number = 128 / 32;\n\n  /**\n   * Initializes a newly created cipher.\n   * \n   * @param xformMode - Either the encryption or decryption transformation mode constant\n   * @param key - The key\n   * @param cfg - Configuration options to use for this operation\n   * @example\n   * ```javascript\n   * const cipher = new AESAlgo(\n   *   Cipher._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray }\n   * );\n   * ```\n   */\n  constructor(xformMode: number, key: WordArray, cfg?: CipherCfg) {\n    super();\n    this.cfg = Object.assign({}, cfg);\n    this._xformMode = xformMode;\n    this._key = key;\n    // Note: reset() is called by subclasses after initialization\n  }\n\n  /**\n   * Creates this cipher in encryption mode.\n   * \n   * @param key - The key\n   * @param cfg - Configuration options to use for this operation\n   * @returns A cipher instance\n   * @static\n   * @example\n   * ```javascript\n   * const cipher = AESAlgo.createEncryptor(keyWordArray, { iv: ivWordArray });\n   * ```\n   */\n  static createEncryptor<T extends Cipher>(\n    this: new (xformMode: number, key: WordArray, cfg?: CipherCfg) => T,\n    key: WordArray,\n    cfg?: CipherCfg\n  ): T {\n    return (this as any).create(Cipher._ENC_XFORM_MODE, key, cfg);\n  }\n\n  /**\n   * Creates this cipher in decryption mode.\n   * \n   * @param key - The key\n   * @param cfg - Configuration options to use for this operation\n   * @returns A cipher instance\n   * @static\n   * @example\n   * ```javascript\n   * const cipher = AESAlgo.createDecryptor(keyWordArray, { iv: ivWordArray });\n   * ```\n   */\n  static createDecryptor<T extends Cipher>(\n    this: new (xformMode: number, key: WordArray, cfg?: CipherCfg) => T,\n    key: WordArray,\n    cfg?: CipherCfg\n  ): T {\n    return (this as any).create(Cipher._DEC_XFORM_MODE, key, cfg);\n  }\n\n  /**\n   * Factory method to create a cipher instance.\n   * \n   * @param xformMode - Transform mode\n   * @param key - The key\n   * @param cfg - Configuration options\n   * @returns A cipher instance\n   * @static\n   */\n  static create<T extends Cipher>(\n    this: new (xformMode: number, key: WordArray, cfg?: CipherCfg) => T,\n    xformMode: number,\n    key: WordArray,\n    cfg?: CipherCfg\n  ): T;\n  static create<T extends Base>(this: new (...args: any[]) => T, ...args: any[]): T;\n  static create(this: any, ...args: any[]): any {\n    // Handle both Cipher and Base cases\n    if (args.length >= 2 && typeof args[0] === 'number') {\n      // Cipher case: xformMode, key, cfg\n      const [xformMode, key, cfg] = args;\n      const instance = new this(xformMode, key, cfg);\n      // Call reset after construction to properly initialize\n      instance.reset();\n      return instance;\n    } else {\n      // Base case: pass all arguments\n      return new this(...args);\n    }\n  }\n\n  /**\n   * Creates shortcut functions to a cipher's object interface.\n   * \n   * @param SubCipher - The cipher to create a helper for\n   * @returns An object with encrypt and decrypt shortcut functions\n   * @static\n   * @example\n   * ```javascript\n   * const AES = Cipher._createHelper(AESAlgo);\n   * ```\n   */\n  static _createHelper(SubCipher: typeof Cipher): CipherObj {\n    const selectCipherStrategy = (key: WordArray | string): typeof SerializableCipher => {\n      if (typeof key === 'string') {\n        return PasswordBasedCipher;\n      }\n      return SerializableCipher;\n    };\n\n    return {\n      encrypt(message: WordArray | string, key: WordArray | string, cfg?: CipherCfg): CipherParams {\n        return selectCipherStrategy(key).encrypt(SubCipher, message, key, cfg);\n      },\n\n      decrypt(\n        ciphertext: CipherParams | CipherParamsCfg | string,\n        key: WordArray | string,\n        cfg?: CipherCfg\n      ): WordArray {\n        return selectCipherStrategy(key).decrypt(SubCipher, ciphertext, key, cfg);\n      },\n    };\n  }\n\n  /**\n   * Resets this cipher to its initial state.\n   * \n   * @example\n   * ```javascript\n   * cipher.reset();\n   * ```\n   */\n  reset(): void {\n    super.reset();\n    this._doReset();\n  }\n\n  /**\n   * Adds data to be encrypted or decrypted.\n   * \n   * @param dataUpdate - The data to encrypt or decrypt\n   * @returns The data after processing\n   * @example\n   * ```javascript\n   * const encrypted = cipher.process('data');\n   * const encrypted = cipher.process(wordArray);\n   * ```\n   */\n  process(dataUpdate: WordArray | string): WordArray {\n    this._append(dataUpdate);\n    return this._process();\n  }\n\n  /**\n   * Finalizes the encryption or decryption process.\n   * Note that the finalize operation is effectively a destructive, read-once operation.\n   * \n   * @param dataUpdate - The final data to encrypt or decrypt\n   * @returns The data after final processing\n   * @example\n   * ```javascript\n   * const encrypted = cipher.finalize();\n   * const encrypted = cipher.finalize('data');\n   * const encrypted = cipher.finalize(wordArray);\n   * ```\n   */\n  finalize(dataUpdate?: WordArray | string): WordArray {\n    if (dataUpdate) {\n      this._append(dataUpdate);\n    }\n    const finalProcessedData = this._doFinalize();\n    return finalProcessedData;\n  }\n\n  /**\n   * Reset implementation for concrete cipher\n   * Must be implemented by subclasses\n   */\n  protected abstract _doReset(): void;\n\n  /**\n   * Finalize implementation for concrete cipher\n   * Must be implemented by subclasses\n   */\n  protected abstract _doFinalize(): WordArray;\n\n  /**\n   * Encrypt a block of data\n   * Must be implemented by block ciphers\n   */\n  encryptBlock?(words: number[], offset: number): void;\n\n  /**\n   * Decrypt a block of data\n   * Must be implemented by block ciphers\n   */\n  decryptBlock?(words: number[], offset: number): void;\n}\n\n/**\n * Abstract base stream cipher template.\n * Stream ciphers process data one unit at a time rather than in blocks.\n * \n * @property blockSize - The number of 32-bit words this cipher operates on (default: 1 = 32 bits)\n */\nexport abstract class StreamCipher extends Cipher {\n  blockSize: number = 1;\n\n  constructor(xformMode: number, key: WordArray, cfg?: CipherCfg) {\n    super(xformMode, key, cfg);\n    this.blockSize = 1;\n    // Don't call reset() here - let it be called after construction\n    // to avoid field initialization issues\n  }\n\n  protected _doFinalize(): WordArray {\n    // Process partial blocks\n    const finalProcessedBlocks = this._process(true);\n    return finalProcessedBlocks;\n  }\n}\n\n/**\n * Abstract base block cipher mode template.\n * Defines how multiple blocks are processed together.\n */\nexport class BlockCipherMode extends Base {\n  /** The cipher instance */\n  _cipher: Cipher;\n  \n  /** The initialization vector */\n  _iv?: number[];\n  \n  /** The previous block (for chaining modes) */\n  _prevBlock?: number[];\n\n  /**\n   * Initializes a newly created mode.\n   * \n   * @param cipher - A block cipher instance\n   * @param iv - The IV words\n   * @example\n   * ```javascript\n   * const mode = new CBCMode(cipher, iv.words);\n   * ```\n   */\n  constructor(cipher: Cipher, iv?: number[]) {\n    super();\n    this._cipher = cipher;\n    this._iv = iv;\n  }\n\n  /**\n   * Creates this mode for encryption.\n   * \n   * @param cipher - A block cipher instance\n   * @param iv - The IV words\n   * @returns The mode instance\n   * @static\n   * @example\n   * ```javascript\n   * const mode = CBC.createEncryptor(cipher, iv.words);\n   * ```\n   */\n  static createEncryptor(cipher: Cipher, iv?: number[]): BlockCipherMode {\n    return (this as any).Encryptor.create(cipher, iv);\n  }\n\n  /**\n   * Creates this mode for decryption.\n   * \n   * @param cipher - A block cipher instance\n   * @param iv - The IV words\n   * @returns The mode instance\n   * @static\n   * @example\n   * ```javascript\n   * const mode = CBC.createDecryptor(cipher, iv.words);\n   * ```\n   */\n  static createDecryptor(cipher: Cipher, iv?: number[]): BlockCipherMode {\n    return (this as any).Decryptor.create(cipher, iv);\n  }\n\n  /**\n   * Process a block of data\n   * Must be implemented by concrete modes\n   */\n  processBlock(_words: number[], _offset: number): void {\n    // Abstract method\n  }\n}\n\n/**\n * XOR blocks for cipher block chaining\n * @private\n */\nfunction xorBlock(this: BlockCipherMode, words: number[], offset: number, blockSize: number): void {\n  const _words = words;\n  let block: number[] | undefined;\n\n  // Shortcut\n  const iv = this._iv;\n\n  // Choose mixing block\n  if (iv) {\n    block = iv;\n    // Remove IV for subsequent blocks\n    this._iv = undefined;\n  } else {\n    block = this._prevBlock;\n  }\n\n  // XOR blocks\n  if (block) {\n    for (let i = 0; i < blockSize; i += 1) {\n      _words[offset + i] ^= block[i];\n    }\n  }\n}\n\n/**\n * CBC Encryptor\n */\nclass CBCEncryptor extends BlockCipherMode {\n  /**\n   * Processes the data block at offset.\n   * \n   * @param words - The data words to operate on\n   * @param offset - The offset where the block starts\n   * @example\n   * ```javascript\n   * mode.processBlock(data.words, offset);\n   * ```\n   */\n  processBlock(words: number[], offset: number): void {\n    const cipher = this._cipher;\n    const blockSize = cipher.blockSize;\n\n    // XOR and encrypt\n    xorBlock.call(this, words, offset, blockSize);\n    cipher.encryptBlock!(words, offset);\n\n    // Remember this block to use with next block\n    this._prevBlock = words.slice(offset, offset + blockSize);\n  }\n}\n\n/**\n * CBC Decryptor\n */\nclass CBCDecryptor extends BlockCipherMode {\n  /**\n   * Processes the data block at offset.\n   * \n   * @param words - The data words to operate on\n   * @param offset - The offset where the block starts\n   * @example\n   * ```javascript\n   * mode.processBlock(data.words, offset);\n   * ```\n   */\n  processBlock(words: number[], offset: number): void {\n    const cipher = this._cipher;\n    const blockSize = cipher.blockSize;\n\n    // Remember this block to use with next block\n    const thisBlock = words.slice(offset, offset + blockSize);\n\n    // Decrypt and XOR\n    cipher.decryptBlock!(words, offset);\n    xorBlock.call(this, words, offset, blockSize);\n\n    // This block becomes the previous block\n    this._prevBlock = thisBlock;\n  }\n}\n\n/**\n * Cipher Block Chaining mode.\n * Each block is XORed with the previous ciphertext block before encryption.\n */\nexport class CBC extends BlockCipherMode {\n  /** CBC Encryptor */\n  static Encryptor = CBCEncryptor;\n\n  /** CBC Decryptor */\n  static Decryptor = CBCDecryptor;\n}\n\n/**\n * PKCS #5/7 padding strategy.\n * Pads data with bytes all of the same value as the count of padding bytes.\n */\nexport const Pkcs7: Padding = {\n  /**\n   * Pads data using the algorithm defined in PKCS #5/7.\n   * \n   * @param data - The data to pad\n   * @param blockSize - The multiple that the data should be padded to\n   * @example\n   * ```javascript\n   * Pkcs7.pad(wordArray, 4);\n   * ```\n   */\n  pad(data: WordArray, blockSize: number): void {\n    // Shortcut\n    const blockSizeBytes = blockSize * 4;\n\n    // Count padding bytes\n    const nPaddingBytes = blockSizeBytes - (data.sigBytes % blockSizeBytes);\n\n    // Create padding word\n    const paddingWord = (nPaddingBytes << 24)\n      | (nPaddingBytes << 16)\n      | (nPaddingBytes << 8)\n      | nPaddingBytes;\n\n    // Create padding\n    const paddingWords: number[] = [];\n    for (let i = 0; i < nPaddingBytes; i += 4) {\n      paddingWords.push(paddingWord);\n    }\n    const padding = WordArray.create(paddingWords, nPaddingBytes);\n\n    // Add padding\n    data.concat(padding);\n  },\n\n  /**\n   * Unpads data that had been padded using the algorithm defined in PKCS #5/7.\n   * \n   * @param data - The data to unpad\n   * @example\n   * ```javascript\n   * Pkcs7.unpad(wordArray);\n   * ```\n   */\n  unpad(data: WordArray): void {\n    // Get number of padding bytes from last byte\n    const nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;\n\n    // Remove padding\n    data.sigBytes -= nPaddingBytes;\n  }\n};\n\n/**\n * Abstract base block cipher template.\n * Block ciphers process data in fixed-size blocks.\n * \n * @property blockSize - The number of 32-bit words this cipher operates on (default: 4 = 128 bits)\n */\nexport abstract class BlockCipher extends Cipher {\n  /** Block mode instance */\n  protected _mode?: BlockCipherMode & { __creator?: Function };\n\n  /**\n   * Initializes a newly created block cipher.\n   * \n   * @param xformMode - Transform mode\n   * @param key - The key\n   * @param cfg - Configuration options\n   */\n  constructor(xformMode: number, key: WordArray, cfg?: CipherCfg) {\n    super(xformMode, key, Object.assign(\n      {\n        mode: CBC,\n        padding: Pkcs7,\n      },\n      cfg\n    ));\n    this.blockSize = 128 / 32;\n    // Don't call reset() here - let it be called after construction\n    // to avoid field initialization issues\n  }\n\n  reset(): void {\n    // Reset cipher\n    super.reset();\n\n    // Shortcuts\n    const { cfg } = this;\n    const { iv, mode } = cfg;\n\n    // Reset block mode\n    let modeCreator: ((cipher: Cipher, iv?: number[]) => BlockCipherMode) | undefined;\n    \n    if (this._xformMode === (this.constructor as typeof Cipher)._ENC_XFORM_MODE) {\n      modeCreator = mode?.createEncryptor;\n    } else {\n      modeCreator = mode?.createDecryptor;\n      // Keep at least one block in the buffer for unpadding\n      this._minBufferSize = 1;\n    }\n\n    if (modeCreator && mode) {\n      this._mode = modeCreator.call(mode, this, iv?.words) as BlockCipherMode & { __creator?: Function };\n      this._mode.__creator = modeCreator;\n    }\n  }\n\n  protected _doProcessBlock(words: number[], offset: number): void {\n    this._mode?.processBlock(words, offset);\n  }\n\n  /**\n   * Encrypt a block of data\n   * Must be implemented by block ciphers\n   */\n  abstract encryptBlock(words: number[], offset: number): void;\n\n  /**\n   * Decrypt a block of data\n   * Must be implemented by block ciphers\n   */\n  abstract decryptBlock(words: number[], offset: number): void;\n\n  protected _doFinalize(): WordArray {\n    let finalProcessedBlocks: WordArray;\n\n    // Shortcut\n    const { padding } = this.cfg;\n\n    // Finalize\n    if (this._xformMode === (this.constructor as typeof Cipher)._ENC_XFORM_MODE) {\n      // Pad data\n      if (padding) {\n        padding.pad(this._data, this.blockSize);\n      }\n\n      // Process final blocks\n      finalProcessedBlocks = this._process(true);\n    } else {\n      // Process final blocks\n      finalProcessedBlocks = this._process(true);\n\n      // Unpad data\n      if (padding) {\n        padding.unpad(finalProcessedBlocks);\n      }\n    }\n\n    return finalProcessedBlocks;\n  }\n}\n\n/**\n * A collection of cipher parameters.\n * Encapsulates all the parameters used in a cipher operation.\n * \n * @property ciphertext - The raw ciphertext\n * @property key - The key to this ciphertext\n * @property iv - The IV used in the ciphering operation\n * @property salt - The salt used with a key derivation function\n * @property algorithm - The cipher algorithm\n * @property mode - The block mode used in the ciphering operation\n * @property padding - The padding scheme used in the ciphering operation\n * @property blockSize - The block size of the cipher\n * @property formatter - The default formatting strategy\n */\nexport class CipherParams extends Base implements CipherParamsCfg {\n  ciphertext?: WordArray;\n  key?: WordArray;\n  iv?: WordArray;\n  salt?: WordArray;\n  algorithm?: typeof Cipher;\n  mode?: typeof BlockCipherMode;\n  padding?: Padding;\n  blockSize?: number;\n  formatter?: Format;\n  [key: string]: unknown;\n\n  /**\n   * Initializes a newly created cipher params object.\n   * \n   * @param cipherParams - An object with any of the possible cipher parameters\n   * @example\n   * ```javascript\n   * const cipherParams = new CipherParams({\n   *   ciphertext: ciphertextWordArray,\n   *   key: keyWordArray,\n   *   iv: ivWordArray,\n   *   salt: saltWordArray,\n   *   algorithm: AESAlgo,\n   *   mode: CBC,\n   *   padding: Pkcs7,\n   *   blockSize: 4,\n   *   formatter: OpenSSLFormatter\n   * });\n   * ```\n   */\n  constructor(cipherParams?: CipherParamsCfg) {\n    super();\n    if (cipherParams) {\n      this.mixIn(cipherParams);\n    }\n    // Set default formatter if not provided\n    if (!this.formatter) {\n      this.formatter = OpenSSLFormatter;\n    }\n  }\n\n  /**\n   * Factory method to create cipher params\n   * \n   * @param cipherParams - The cipher parameters\n   * @returns A new CipherParams instance\n   * @static\n   */\n  static create(cipherParams?: CipherParamsCfg): CipherParams;\n  static create<T extends CipherParams>(this: new (...args: any[]) => T, ...args: any[]): T;\n  static create(...args: any[]): any {\n    const [cipherParams] = args;\n    return new CipherParams(cipherParams);\n  }\n\n  /**\n   * Converts this cipher params object to a string.\n   * \n   * @param formatter - The formatting strategy to use\n   * @returns The stringified cipher params\n   * @throws Error if neither the formatter nor the default formatter is set\n   * @example\n   * ```javascript\n   * const string = cipherParams.toString();\n   * const string = cipherParams.toString(OpenSSLFormatter);\n   * ```\n   */\n  toString(formatter?: Format): string {\n    const fmt = formatter || this.formatter;\n    if (!fmt) {\n      throw new Error('cipher params formatter required');\n    }\n    return fmt.stringify(this);\n  }\n}\n\n/**\n * OpenSSL formatting strategy.\n * Formats cipher params in OpenSSL-compatible format.\n */\nexport const OpenSSLFormatter: Format = {\n  /**\n   * Converts a cipher params object to an OpenSSL-compatible string.\n   * \n   * @param cipherParams - The cipher params object\n   * @returns The OpenSSL-compatible string\n   * @example\n   * ```javascript\n   * const openSSLString = OpenSSLFormatter.stringify(cipherParams);\n   * ```\n   */\n  stringify(cipherParams: CipherParams): string {\n    let wordArray: WordArray;\n\n    // Shortcuts\n    const { ciphertext, salt } = cipherParams;\n\n    // Format\n    if (salt && ciphertext) {\n      wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext);\n    } else if (ciphertext) {\n      wordArray = ciphertext;\n    } else {\n      // No ciphertext, return empty\n      wordArray = new WordArray();\n    }\n\n    return wordArray.toString(Base64);\n  },\n\n  /**\n   * Converts an OpenSSL-compatible string to a cipher params object.\n   * \n   * @param openSSLStr - The OpenSSL-compatible string\n   * @returns The cipher params object\n   * @example\n   * ```javascript\n   * const cipherParams = OpenSSLFormatter.parse(openSSLString);\n   * ```\n   */\n  parse(openSSLStr: string): CipherParams {\n    let salt: WordArray | undefined;\n\n    // Parse base64\n    const ciphertext = Base64.parse(openSSLStr);\n\n    // Shortcut\n    const ciphertextWords = ciphertext.words;\n\n    // Test for salt\n    if (ciphertextWords[0] === 0x53616c74 && ciphertextWords[1] === 0x65645f5f) {\n      // Extract salt\n      salt = WordArray.create(ciphertextWords.slice(2, 4));\n\n      // Remove salt from ciphertext\n      ciphertextWords.splice(0, 4);\n      ciphertext.sigBytes -= 16;\n    }\n\n    return CipherParams.create({ ciphertext, salt });\n  }\n};\n\n/**\n * A cipher wrapper that returns ciphertext as a serializable cipher params object.\n * Handles the serialization and deserialization of cipher operations.\n */\nexport class SerializableCipher extends Base {\n  /** Configuration options */\n  static cfg: { format: Format } = { format: OpenSSLFormatter };\n\n  /**\n   * Encrypts a message.\n   * \n   * @param cipher - The cipher algorithm to use\n   * @param message - The message to encrypt\n   * @param key - The key\n   * @param cfg - Configuration options to use for this operation\n   * @returns A cipher params object\n   * @static\n   * @example\n   * ```javascript\n   * const ciphertextParams = SerializableCipher.encrypt(AESAlgo, message, key);\n   * const ciphertextParams = SerializableCipher.encrypt(AESAlgo, message, key, { iv: iv });\n   * ```\n   */\n  static encrypt(\n    cipher: typeof Cipher,\n    message: WordArray | string,\n    key: WordArray | string,\n    cfg?: CipherCfg\n  ): CipherParams {\n    // Apply config defaults\n    const _cfg = Object.assign({}, this.cfg, cfg);\n\n    // Encrypt\n    const encryptor = (cipher as any).createEncryptor(key as WordArray, _cfg);\n    const ciphertext = encryptor.finalize(message);\n\n    // Shortcut\n    const cipherCfg = encryptor.cfg;\n\n    // Create and return serializable cipher params\n    return CipherParams.create({\n      ciphertext,\n      key: key as WordArray,\n      iv: cipherCfg.iv,\n      algorithm: cipher,\n      mode: cipherCfg.mode,\n      padding: cipherCfg.padding,\n      blockSize: encryptor.blockSize,\n      formatter: _cfg.format || OpenSSLFormatter,\n    });\n  }\n\n  /**\n   * Decrypts serialized ciphertext.\n   * \n   * @param cipher - The cipher algorithm to use\n   * @param ciphertext - The ciphertext to decrypt\n   * @param key - The key\n   * @param cfg - Configuration options to use for this operation\n   * @returns The plaintext\n   * @static\n   * @example\n   * ```javascript\n   * const plaintext = SerializableCipher.decrypt(AESAlgo, formattedCiphertext, key, { iv: iv });\n   * const plaintext = SerializableCipher.decrypt(AESAlgo, ciphertextParams, key, { iv: iv });\n   * ```\n   */\n  static decrypt(\n    cipher: typeof Cipher,\n    ciphertext: CipherParams | CipherParamsCfg | string,\n    key: WordArray | string,\n    cfg?: CipherCfg\n  ): WordArray {\n    // Apply config defaults\n    const _cfg = Object.assign({}, this.cfg, cfg);\n\n    // Convert string to CipherParams\n    const _ciphertext = this._parse(ciphertext, _cfg.format);\n\n    // Decrypt\n    const plaintext = (cipher as any).createDecryptor(key as WordArray, _cfg).finalize(_ciphertext.ciphertext!);\n\n    return plaintext;\n  }\n\n  /**\n   * Converts serialized ciphertext to CipherParams.\n   * \n   * @param ciphertext - The ciphertext\n   * @param format - The formatting strategy to use to parse serialized ciphertext\n   * @returns The unserialized ciphertext\n   * @static\n   * @private\n   */\n  protected static _parse(\n    ciphertext: CipherParams | CipherParamsCfg | string,\n    format?: Format\n  ): CipherParams {\n    if (typeof ciphertext === 'string') {\n      if (!format) {\n        throw new Error('Format required to parse string');\n      }\n      return format.parse(ciphertext, this);\n    }\n    if (ciphertext instanceof CipherParams) {\n      return ciphertext;\n    }\n    return new CipherParams(ciphertext);\n  }\n}\n\n/**\n * OpenSSL key derivation function.\n * Derives a key and IV from a password using the OpenSSL method.\n */\nexport const OpenSSLKdf: Kdf = {\n  /**\n   * Derives a key and IV from a password.\n   * \n   * @param password - The password to derive from\n   * @param keySize - The size in words of the key to generate\n   * @param ivSize - The size in words of the IV to generate\n   * @param salt - A 64-bit salt to use (if omitted, a salt will be generated randomly)\n   * @param hasher - The hasher to use\n   * @returns A cipher params object with the key, IV, and salt\n   * @example\n   * ```javascript\n   * const derivedParams = OpenSSLKdf.execute('Password', 256/32, 128/32);\n   * const derivedParams = OpenSSLKdf.execute('Password', 256/32, 128/32, 'saltsalt');\n   * ```\n   */\n  execute(\n    password: string,\n    keySize: number,\n    ivSize: number,\n    salt?: WordArray | string,\n    hasher?: new (cfg?: HasherCfg) => Hasher\n  ): CipherParams {\n    let _salt: WordArray;\n\n    // Generate random salt\n    if (!salt) {\n      _salt = WordArray.random(64 / 8);\n    } else if (typeof salt === 'string') {\n      // Parse string salt as hex or utf8\n      _salt = Hex.parse(salt);\n    } else {\n      _salt = salt;\n    }\n\n    // Derive key and IV\n    let key: WordArray;\n    if (!hasher) {\n      key = EvpKDFAlgo.create({ keySize: keySize + ivSize }).compute(password, _salt);\n    } else {\n      key = EvpKDFAlgo.create({ keySize: keySize + ivSize, hasher }).compute(password, _salt);\n    }\n\n    // Separate key and IV\n    const iv = WordArray.create(key.words.slice(keySize), ivSize * 4);\n    key.sigBytes = keySize * 4;\n\n    // Return params\n    return CipherParams.create({ key, iv, salt: _salt });\n  }\n};\n\n/**\n * A serializable cipher wrapper that derives the key from a password.\n * Returns ciphertext as a serializable cipher params object.\n */\nexport class PasswordBasedCipher extends SerializableCipher {\n  /** Configuration options */\n  static cfg = Object.assign({}, SerializableCipher.cfg, { kdf: OpenSSLKdf });\n\n  /**\n   * Encrypts a message using a password.\n   * \n   * @param cipher - The cipher algorithm to use\n   * @param message - The message to encrypt\n   * @param password - The password\n   * @param cfg - Configuration options to use for this operation\n   * @returns A cipher params object\n   * @static\n   * @example\n   * ```javascript\n   * const ciphertextParams = PasswordBasedCipher.encrypt(AESAlgo, message, 'password');\n   * ```\n   */\n  static encrypt(\n    cipher: typeof Cipher,\n    message: WordArray | string,\n    password: string,\n    cfg?: CipherCfg\n  ): CipherParams {\n    // Apply config defaults\n    const _cfg = Object.assign({}, this.cfg, cfg);\n\n    // Derive key and other params\n    if (!_cfg.kdf) {\n      throw new Error('KDF required for password-based encryption');\n    }\n    \n    const derivedParams = _cfg.kdf.execute(\n      password,\n      (cipher as any).keySize || cipher.keySize,\n      (cipher as any).ivSize || cipher.ivSize,\n      _cfg.salt,\n      _cfg.hasher\n    );\n\n    // Add IV to config\n    _cfg.iv = derivedParams.iv;\n\n    // Encrypt\n    const ciphertext = SerializableCipher.encrypt.call(\n      this,\n      cipher,\n      message,\n      derivedParams.key!,\n      _cfg\n    );\n\n    // Mix in derived params (only salt, not the whole object to avoid overwriting ciphertext)\n    ciphertext.salt = derivedParams.salt;\n\n    return ciphertext;\n  }\n\n  /**\n   * Decrypts serialized ciphertext using a password.\n   * \n   * @param cipher - The cipher algorithm to use\n   * @param ciphertext - The ciphertext to decrypt\n   * @param password - The password\n   * @param cfg - Configuration options to use for this operation\n   * @returns The plaintext\n   * @static\n   * @example\n   * ```javascript\n   * const plaintext = PasswordBasedCipher.decrypt(AESAlgo, formattedCiphertext, 'password');\n   * ```\n   */\n  static decrypt(\n    cipher: typeof Cipher,\n    ciphertext: CipherParams | CipherParamsCfg | string,\n    password: string,\n    cfg?: CipherCfg\n  ): WordArray {\n    // Apply config defaults\n    const _cfg = Object.assign({}, this.cfg, cfg);\n\n    // Convert string to CipherParams\n    const _ciphertext = this._parse(ciphertext, _cfg.format);\n\n    // Derive key and other params\n    if (!_cfg.kdf) {\n      throw new Error('KDF required for password-based decryption');\n    }\n    \n    const derivedParams = _cfg.kdf.execute(\n      password,\n      (cipher as any).keySize || cipher.keySize,\n      (cipher as any).ivSize || cipher.ivSize,\n      _ciphertext.salt,\n      _cfg.hasher\n    );\n\n    // Add IV to config\n    _cfg.iv = derivedParams.iv;\n\n    // Decrypt\n    const plaintext = SerializableCipher.decrypt.call(\n      this,\n      cipher,\n      _ciphertext,\n      derivedParams.key!,\n      _cfg\n    );\n\n    return plaintext;\n  }\n}\n"],"mappings":"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"}