{"version":3,"sources":["../src/utils.ts","../src/errors.ts"],"sourcesContent":["import {\n  OTPError,\n  SecretTooShortError,\n  SecretTooLongError,\n  CounterNegativeError,\n  CounterOverflowError,\n  CounterNotIntegerError,\n  TimeNegativeError,\n  TimeNotFiniteError,\n  PeriodTooSmallError,\n  PeriodTooLargeError,\n  TokenLengthError,\n  TokenFormatError,\n  CounterToleranceError,\n  CounterToleranceTooLargeError,\n  CounterToleranceNegativeError,\n  EpochToleranceError,\n  EpochToleranceNegativeError,\n  EpochToleranceTooLargeError,\n  CryptoPluginMissingError,\n  Base32PluginMissingError,\n  ConfigurationError,\n  SecretMissingError,\n  LabelMissingError,\n  IssuerMissingError,\n  SecretTypeError,\n} from \"./errors.js\";\n\nimport type {\n  HashAlgorithm,\n  SecretOptions,\n  OTPResultOk,\n  OTPResultError,\n  OTPResult,\n} from \"./types.js\";\n\n/**\n * Singleton TextEncoder instance to avoid repeated allocations\n */\nconst textEncoder = new TextEncoder();\n\n/**\n * Singleton TextDecoder instance to avoid repeated allocations\n */\nconst textDecoder = new TextDecoder();\n\n/**\n * Minimum secret length in bytes (128 bits as per RFC 4226)\n */\nexport const MIN_SECRET_BYTES = 16;\n\n/**\n * Maximum secret length in bytes (512 bits)\n *\n * The 64-byte maximum is not part of the RFCs.\n * This is to prevent excessive memory usage in HMAC operations.\n */\nexport const MAX_SECRET_BYTES = 64;\n\n/**\n * Recommended secret length in bytes (160 bits as per RFC 4226)\n */\nexport const RECOMMENDED_SECRET_BYTES = 20;\n\n/**\n * Minimum period in seconds\n */\nexport const MIN_PERIOD = 1;\n\n/**\n * Maximum period in seconds (1 hour)\n */\nexport const MAX_PERIOD = 3600;\n\n/**\n * Default period in seconds (30 seconds as per RFC 6238)\n */\nexport const DEFAULT_PERIOD = 30;\n\n/**\n * Maximum safe integer for counter (2^53 - 1)\n */\nexport const MAX_COUNTER = Number.MAX_SAFE_INTEGER;\n\n/**\n * Maximum verification window size\n *\n * Limits the number of HMAC computations during verification to prevent DoS attacks.\n * A window of 99 means up to 99 HMAC computations (total checks including current counter).\n * Odd number to cater for equal distribution of time drift + current.\n *\n * For TOTP: window=1 is typically sufficient (allows +-30 seconds clock drift)\n * For HOTP: window=10-50 handles reasonable counter desynchronization\n */\nexport const MAX_WINDOW = 99;\n\n/**\n * Configurable guardrails for OTP validation\n *\n * Allows overriding default safety limits for non-standard production requirements.\n * Use with caution - custom guardrails can weaken security.\n */\nexport type OTPGuardrailsConfig = {\n  MIN_SECRET_BYTES: number;\n  MAX_SECRET_BYTES: number;\n  MIN_PERIOD: number;\n  MAX_PERIOD: number;\n  MAX_COUNTER: number;\n  MAX_WINDOW: number;\n};\n\n/**\n * Module-private symbol to track guardrail override status\n *\n * This symbol is used as a property key to store whether guardrails contain custom values.\n * Being module-private and a symbol ensures:\n * - Cannot be accessed outside this module (not exported)\n * - Cannot be recreated (each Symbol() call is unique)\n * - Hidden from normal enumeration (Object.keys, JSON.stringify, for-in)\n * - Minimal memory overhead (~1 byte per object)\n * - No garbage collection concerns\n *\n * @internal\n */\nconst OVERRIDE_SYMBOL = Symbol(\"otplib.guardrails.override\");\n\n/**\n * Complete guardrails configuration\n *\n * This represents the final, immutable configuration used by validation functions.\n * Internally tracks whether any values were overridden from RFC recommendations,\n * enabling security auditing and compliance monitoring without exposing implementation\n * details in the public API.\n *\n * The override status is stored using a module-private Symbol that cannot be accessed\n * or recreated outside this module, providing true encapsulation.\n *\n * @see {@link OTPGuardrailsConfig} for the base configuration structure\n * @see {@link createGuardrails} for creating guardrails instances\n * @see {@link hasGuardrailOverrides} to check if guardrails were customized\n */\nexport type OTPGuardrails = Readonly<OTPGuardrailsConfig> & {\n  [OVERRIDE_SYMBOL]?: boolean;\n};\n\n/**\n * Validate guardrail numeric field\n */\nfunction assertGuardrailSafeInteger(\n  name: string,\n  value: unknown,\n  min: number,\n): asserts value is number {\n  if (typeof value !== \"number\" || !Number.isSafeInteger(value)) {\n    throw new ConfigurationError(`Guardrail '${name}' must be a safe integer`);\n  }\n  if (value < min) {\n    throw new ConfigurationError(`Guardrail '${name}' must be >= ${min}`);\n  }\n}\n\n/**\n * Default guardrails matching RFC recommendations\n *\n * Frozen to ensure immutability. Used as default parameter for validation functions.\n * For custom guardrails, use the createGuardrails() factory function.\n */\nconst DEFAULT_GUARDRAILS: OTPGuardrails = Object.freeze({\n  MIN_SECRET_BYTES,\n  MAX_SECRET_BYTES,\n  MIN_PERIOD,\n  MAX_PERIOD,\n  MAX_COUNTER,\n  MAX_WINDOW,\n  [OVERRIDE_SYMBOL]: false,\n});\n\n/**\n * Create guardrails configuration object\n *\n * Factory function that merges custom guardrails with defaults and returns\n * an immutable (frozen) object. Validates custom guardrails to ensure they\n * maintain basic safety invariants.\n *\n * When called without arguments or with `undefined`, returns the default guardrails\n * singleton (optimized to avoid unnecessary allocations). When called with custom\n * values, creates a new frozen object and internally marks it as overridden.\n *\n * @param custom - Optional partial guardrails to override defaults\n * @returns Frozen guardrails object\n * @throws {ConfigurationError} If custom guardrails violate safety invariants\n *\n * @example Basic usage\n * ```ts\n * import { createGuardrails, hasGuardrailOverrides } from '@otplib/core'\n *\n * // Returns default singleton (no overrides)\n * const defaults = createGuardrails();\n * hasGuardrailOverrides(defaults); // false\n *\n * // Creates new object with overrides\n * const custom = createGuardrails({\n *   MIN_SECRET_BYTES: 8,\n *   MAX_WINDOW: 200\n * });\n * hasGuardrailOverrides(custom); // true\n * ```\n *\n * @example Monitoring custom guardrails\n * ```ts\n * import { createGuardrails, hasGuardrailOverrides } from '@otplib/core';\n *\n * const guardrails = createGuardrails({ MAX_WINDOW: 20 });\n *\n * if (hasGuardrailOverrides(guardrails)) {\n *   logger.warn('Non-default guardrails in use', { guardrails });\n * }\n * ```\n *\n * @see {@link hasGuardrailOverrides} to check if guardrails were customized\n */\nexport function createGuardrails(custom?: Partial<OTPGuardrailsConfig>): OTPGuardrails {\n  if (!custom) {\n    return DEFAULT_GUARDRAILS;\n  }\n\n  if (custom.MIN_SECRET_BYTES !== undefined) {\n    assertGuardrailSafeInteger(\"MIN_SECRET_BYTES\", custom.MIN_SECRET_BYTES, 1);\n  }\n\n  if (custom.MAX_SECRET_BYTES !== undefined) {\n    assertGuardrailSafeInteger(\"MAX_SECRET_BYTES\", custom.MAX_SECRET_BYTES, 1);\n  }\n\n  if (custom.MIN_PERIOD !== undefined) {\n    assertGuardrailSafeInteger(\"MIN_PERIOD\", custom.MIN_PERIOD, 1);\n  }\n\n  if (custom.MAX_PERIOD !== undefined) {\n    assertGuardrailSafeInteger(\"MAX_PERIOD\", custom.MAX_PERIOD, 1);\n  }\n\n  if (custom.MAX_COUNTER !== undefined) {\n    assertGuardrailSafeInteger(\"MAX_COUNTER\", custom.MAX_COUNTER, 0);\n  }\n\n  if (custom.MAX_WINDOW !== undefined) {\n    assertGuardrailSafeInteger(\"MAX_WINDOW\", custom.MAX_WINDOW, 1);\n  }\n\n  const merged = {\n    ...DEFAULT_GUARDRAILS,\n    ...custom,\n  };\n\n  if (merged.MIN_SECRET_BYTES > merged.MAX_SECRET_BYTES) {\n    throw new ConfigurationError(\"Guardrail 'MIN_SECRET_BYTES' must be <= 'MAX_SECRET_BYTES'\");\n  }\n\n  if (merged.MIN_PERIOD > merged.MAX_PERIOD) {\n    throw new ConfigurationError(\"Guardrail 'MIN_PERIOD' must be <= 'MAX_PERIOD'\");\n  }\n\n  return Object.freeze({\n    ...merged,\n    [OVERRIDE_SYMBOL]: true,\n  });\n}\n\n/**\n * Check if guardrails contain custom overrides\n *\n * Returns `true` if the guardrails object was created with custom values,\n * `false` if using RFC-recommended defaults. Useful for security auditing,\n * compliance monitoring, and development warnings.\n *\n * This function accesses a module-private Symbol property that cannot be\n * accessed or modified outside this module, ensuring reliable detection.\n *\n * @param guardrails - The guardrails object to check\n * @returns `true` if guardrails were customized, `false` if using defaults\n *\n * @example Security monitoring\n * ```ts\n * import { createGuardrails, hasGuardrailOverrides } from '@otplib/core';\n *\n * const guardrails = createGuardrails({ MAX_WINDOW: 20 });\n *\n * if (hasGuardrailOverrides(guardrails)) {\n *   console.warn('Custom guardrails detected:', guardrails);\n *   // Log to security audit system\n * }\n * ```\n *\n * @example Compliance check\n * ```ts\n * function validateGuardrails(guardrails: OTPGuardrails) {\n *   if (hasGuardrailOverrides(guardrails)) {\n *     throw new Error('Custom guardrails not allowed in production');\n *   }\n * }\n * ```\n */\nexport function hasGuardrailOverrides(guardrails: OTPGuardrails): boolean {\n  return guardrails[OVERRIDE_SYMBOL] ?? false;\n}\n\n/**\n * Validate secret key\n *\n * @param secret - The secret to validate\n * @param guardrails - Validation guardrails (defaults to RFC recommendations)\n * @throws {SecretTooShortError} If secret is too short\n * @throws {SecretTooLongError} If secret is too long\n */\nexport function validateSecret(\n  secret: Uint8Array,\n  guardrails: OTPGuardrails = DEFAULT_GUARDRAILS,\n): void {\n  if (secret.length < guardrails.MIN_SECRET_BYTES) {\n    throw new SecretTooShortError(guardrails.MIN_SECRET_BYTES, secret.length);\n  }\n\n  if (secret.length > guardrails.MAX_SECRET_BYTES) {\n    throw new SecretTooLongError(guardrails.MAX_SECRET_BYTES, secret.length);\n  }\n}\n\n/**\n * Validate counter value\n *\n * @param counter - The counter to validate\n * @param guardrails - Validation guardrails (defaults to RFC recommendations)\n * @throws {CounterNegativeError} If counter is negative\n * @throws {CounterOverflowError} If counter exceeds safe integer\n */\nexport function validateCounter(\n  counter: number | bigint,\n  guardrails: OTPGuardrails = DEFAULT_GUARDRAILS,\n): void {\n  if (typeof counter === \"number\") {\n    if (!Number.isFinite(counter) || !Number.isInteger(counter)) {\n      throw new CounterNotIntegerError();\n    }\n\n    if (!Number.isSafeInteger(counter)) {\n      // Numbers outside the safe integer range cannot be reliably converted to bigint\n      throw new CounterOverflowError();\n    }\n  }\n\n  const value = typeof counter === \"bigint\" ? counter : BigInt(counter);\n\n  if (value < 0n) {\n    throw new CounterNegativeError();\n  }\n\n  if (value > BigInt(guardrails.MAX_COUNTER)) {\n    throw new CounterOverflowError();\n  }\n}\n\n/**\n * Validate time value\n *\n * @param time - The time in seconds to validate\n * @throws {TimeNegativeError} If time is negative\n */\nexport function validateTime(time: number): void {\n  if (!Number.isFinite(time)) {\n    throw new TimeNotFiniteError();\n  }\n\n  if (time < 0) {\n    throw new TimeNegativeError();\n  }\n}\n\n/**\n * Validate period value\n *\n * @param period - The period in seconds to validate\n * @param guardrails - Validation guardrails (defaults to RFC recommendations)\n * @throws {PeriodTooSmallError} If period is too small\n * @throws {PeriodTooLargeError} If period is too large\n */\nexport function validatePeriod(\n  period: number,\n  guardrails: OTPGuardrails = DEFAULT_GUARDRAILS,\n): void {\n  if (!Number.isInteger(period) || period < guardrails.MIN_PERIOD) {\n    throw new PeriodTooSmallError(guardrails.MIN_PERIOD);\n  }\n\n  if (period > guardrails.MAX_PERIOD) {\n    throw new PeriodTooLargeError(guardrails.MAX_PERIOD);\n  }\n}\n\n/**\n * Validate token\n *\n * @param token - The token string to validate\n * @param digits - Expected number of digits\n * @throws {TokenLengthError} If token has incorrect length\n * @throws {TokenFormatError} If token contains non-digit characters\n */\nexport function validateToken(token: string, digits: number): void {\n  if (token.length !== digits) {\n    throw new TokenLengthError(digits, token.length);\n  }\n\n  if (!/^\\d+$/.test(token)) {\n    throw new TokenFormatError();\n  }\n}\n\n/**\n * Validate counter tolerance for HOTP verification\n *\n * Prevents DoS attacks by limiting the number of counter values checked.\n *\n * @param counterTolerance - Counter tolerance specification (number or array of offsets)\n * @param guardrails - Validation guardrails (defaults to RFC recommendations)\n * @throws {CounterToleranceTooLargeError} If tolerance size exceeds MAX_WINDOW\n *\n * @example\n * ```ts\n * validateCounterTolerance(1);        // OK: [0, 1] = 2 checks\n * validateCounterTolerance(98);       // OK: [0, 98] = 99 checks\n * validateCounterTolerance(99);       // Throws: exceeds MAX_WINDOW\n * validateCounterTolerance([0, 1]);   // OK: 2 offsets\n * ```\n */\nexport function validateCounterTolerance(\n  counterTolerance: number | [number, number],\n  guardrails: OTPGuardrails = DEFAULT_GUARDRAILS,\n): void {\n  const [past, future] = normalizeCounterTolerance(counterTolerance);\n\n  if (!Number.isSafeInteger(past) || !Number.isSafeInteger(future)) {\n    throw new CounterToleranceError(\"Counter tolerance values must be safe integers\");\n  }\n\n  if (past < 0 || future < 0) {\n    throw new CounterToleranceNegativeError();\n  }\n\n  const totalChecks = past + future + 1;\n\n  if (totalChecks > guardrails.MAX_WINDOW) {\n    throw new CounterToleranceTooLargeError(guardrails.MAX_WINDOW, totalChecks);\n  }\n}\n\n/**\n * Validate epoch tolerance for TOTP verification\n *\n * Prevents DoS attacks by limiting the time range checked.\n * Also validates that tolerance values are non-negative.\n *\n * @param epochTolerance - Epoch tolerance specification (number or tuple [past, future])\n * @param period - The TOTP period in seconds (default: 30). Used to calculate max tolerance.\n * @param guardrails - Validation guardrails (defaults to RFC recommendations)\n * @throws {EpochToleranceNegativeError} If tolerance contains negative values\n * @throws {EpochToleranceTooLargeError} If tolerance exceeds MAX_WINDOW periods\n *\n * @example\n * ```ts\n * validateEpochTolerance(30);            // OK: 30 seconds symmetric\n * validateEpochTolerance([5, 0]);        // OK: 5 seconds past only\n * validateEpochTolerance([-5, 0]);       // Throws: negative values not allowed\n * validateEpochTolerance(1471);          // Throws with default guardrails (30s period)\n * validateEpochTolerance(2940, 60);      // OK with 60s period\n * ```\n */\nexport function validateEpochTolerance(\n  epochTolerance: number | [number, number],\n  period: number = DEFAULT_PERIOD,\n  guardrails: OTPGuardrails = DEFAULT_GUARDRAILS,\n): void {\n  const [pastTolerance, futureTolerance] = Array.isArray(epochTolerance)\n    ? epochTolerance\n    : [epochTolerance, epochTolerance];\n\n  if (!Number.isSafeInteger(pastTolerance) || !Number.isSafeInteger(futureTolerance)) {\n    throw new EpochToleranceError(\"Epoch tolerance values must be safe integers\");\n  }\n\n  // Check for negative values\n  if (pastTolerance < 0 || futureTolerance < 0) {\n    throw new EpochToleranceNegativeError();\n  }\n\n  // MAX_WINDOW checks means at most MAX_WINDOW - 1 periods of tolerance\n  // (the current time step always consumes one check).\n  const maxToleranceSeconds = (guardrails.MAX_WINDOW - 1) * period;\n  const totalToleranceSeconds = pastTolerance + futureTolerance;\n\n  if (totalToleranceSeconds > maxToleranceSeconds) {\n    throw new EpochToleranceTooLargeError(maxToleranceSeconds, totalToleranceSeconds);\n  }\n}\n\n/**\n * Convert counter to 8-byte big-endian array\n *\n * Per RFC 4226 Section 5.1, the counter value is represented as an 8-byte\n * big-endian (network byte order) unsigned integer.\n *\n * @see {@link https://tools.ietf.org/html/rfc4226#section-5.1 | RFC 4226 Section 5.1 - Symbol Descriptions}\n *\n * @param value - The counter value to convert\n * @returns 8-byte big-endian array\n */\nexport function counterToBytes(value: number | bigint): Uint8Array {\n  const bigintValue = typeof value === \"bigint\" ? value : BigInt(value);\n  const buffer = new ArrayBuffer(8);\n  const view = new DataView(buffer);\n\n  view.setBigUint64(0, bigintValue, false);\n\n  return new Uint8Array(buffer);\n}\n\n/**\n * Perform Dynamic Truncation as per RFC 4226 Section 5.3\n *\n * The algorithm:\n * 1. Take the low-order 4 bits of the last byte as offset\n * 2. Extract 4 bytes starting at offset\n * 3. Mask the most significant bit to get a 31-bit unsigned integer\n *\n * This ensures consistent extraction across different HMAC output sizes\n * while producing a value that fits in a signed 32-bit integer.\n *\n * @see {@link https://tools.ietf.org/html/rfc4226#section-5.3 | RFC 4226 Section 5.3 - Generating an HOTP Value}\n *\n * @param hmacResult - HMAC result (at least 20 bytes for SHA-1)\n * @returns Truncated 31-bit unsigned integer\n */\nexport function dynamicTruncate(hmacResult: Uint8Array): number {\n  const offset = hmacResult[hmacResult.length - 1] & 0x0f;\n\n  const binary =\n    ((hmacResult[offset] & 0x7f) << 24) |\n    (hmacResult[offset + 1] << 16) |\n    (hmacResult[offset + 2] << 8) |\n    hmacResult[offset + 3];\n\n  return binary;\n}\n\n/**\n * Convert truncated integer to OTP string with specified digits\n *\n * Computes: Snum mod 10^Digit (RFC 4226 Section 5.3)\n *\n * The result is zero-padded to ensure consistent length,\n * as required for proper token comparison.\n *\n * @see {@link https://tools.ietf.org/html/rfc4226#section-5.3 | RFC 4226 Section 5.3 - Generating an HOTP Value}\n *\n * @param value - The truncated integer value (Snum)\n * @param digits - Number of digits for the OTP (Digit, typically 6-8)\n * @returns OTP string with leading zeros if necessary\n */\nexport function truncateDigits(value: number, digits: number): string {\n  const maxOtp = 10 ** digits;\n  const otp = value % maxOtp;\n  return otp.toString().padStart(digits, \"0\");\n}\n\n/**\n * Validate that two byte arrays have equal length\n *\n * Useful as a preliminary check before performing byte-by-byte comparisons.\n *\n * @param a - First byte array\n * @param b - Second byte array\n * @returns true if arrays have equal length, false otherwise\n */\nexport function validateByteLengthEqual(a: Uint8Array, b: Uint8Array): boolean {\n  return a.length === b.length;\n}\n\n/**\n * Constant-time comparison to prevent timing attacks\n *\n * This implements a timing-safe equality check as recommended in\n * RFC 4226 Section 7.2 for token validation to prevent\n * timing side-channel attacks.\n *\n * @see {@link https://tools.ietf.org/html/rfc4226#section-7.2 | RFC 4226 Section 7.2 - Validation and Verification}\n *\n * @param a - First value to compare\n * @param b - Second value to compare\n * @returns true if values are equal, false otherwise\n */\nexport function constantTimeEqual(a: string | Uint8Array, b: string | Uint8Array): boolean {\n  const bufA = stringToBytes(a);\n  const bufB = stringToBytes(b);\n\n  if (!validateByteLengthEqual(bufA, bufB)) {\n    return false;\n  }\n\n  let result = 0;\n  for (let i = 0; i < bufA.length; i++) {\n    result |= bufA[i] ^ bufB[i];\n  }\n\n  return result === 0;\n}\n\n/**\n * Get HMAC digest size in bytes for a given algorithm\n *\n * @param algorithm - The hash algorithm\n * @returns Digest size in bytes\n */\nexport function getDigestSize(algorithm: HashAlgorithm): number {\n  switch (algorithm) {\n    case \"sha1\":\n      return 20;\n    case \"sha256\":\n      return 32;\n    case \"sha512\":\n      return 64;\n  }\n}\n\n/**\n * Convert a string or Uint8Array to Uint8Array\n *\n * This utility function normalizes input to Uint8Array, converting strings\n * using UTF-8 encoding. Uint8Array inputs are returned as-is.\n *\n * Use this to convert raw secret strings (passphrases) to Uint8Array\n * before passing them to generation or verification functions.\n *\n * @param value - The value to convert (string or Uint8Array)\n * @returns The value as a Uint8Array (UTF-8 encoded for strings)\n *\n * @example\n * ```ts\n * import { stringToBytes } from '@otplib/core'\n *\n * const bytes1 = stringToBytes('1234567890123456')\n * // Returns: Uint8Array([49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54])\n *\n * const bytes2 = stringToBytes(new Uint8Array([1, 2, 3]))\n * // Returns: Uint8Array([1, 2, 3]) - returned as-is\n * ```\n */\nexport function stringToBytes(value: string | Uint8Array): Uint8Array {\n  return typeof value === \"string\" ? textEncoder.encode(value) : value;\n}\n\n/**\n * Convert bytes to UTF-8 string\n *\n * Uses TextDecoder for proper UTF-8 handling.\n *\n * @param bytes - Uint8Array to convert\n * @returns UTF-8 string\n *\n * @example\n * ```ts\n * const str = bytesToString(new Uint8Array([104, 101, 108, 108, 111]));\n * // str === \"hello\"\n * ```\n */\nexport function bytesToString(bytes: Uint8Array): string {\n  return textDecoder.decode(bytes);\n}\n\n/**\n * Normalize secret input to Uint8Array\n *\n * Accepts either a Base32-encoded string or Uint8Array and returns Uint8Array.\n * If a Base32Plugin is provided, string secrets will be automatically decoded.\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string secret (e.g. a passphrase), you must convert it\n * to a Uint8Array using {@link stringToBytes} before calling this function.\n *\n * @param secret - The secret to normalize (Base32 string or Uint8Array)\n * @param base32 - Optional Base32Plugin to decode string secrets\n * @returns The secret as Uint8Array\n * @throws {Error} If secret is a string but no Base32Plugin is provided\n *\n * @example\n * ```ts\n * import { normalizeSecret } from '@otplib/core'\n * import { ScureBase32Plugin } from '@otplib/plugin-base32-scure'\n *\n * const base32 = new ScureBase32Plugin()\n *\n * // Uint8Array - returned as-is\n * const secret1 = normalizeSecret(new Uint8Array([1, 2, 3]))\n *\n * // Base32 string - automatically decoded\n * const secret2 = normalizeSecret('JBSWY3DPEHPK3PXP', base32)\n * ```\n */\nexport function normalizeSecret(\n  secret: string | Uint8Array,\n  base32?: { decode: (str: string) => Uint8Array },\n): Uint8Array {\n  if (typeof secret === \"string\") {\n    requireBase32Plugin(base32);\n    return base32.decode(secret);\n  }\n  return secret;\n}\n\n/**\n * Generate a random Base32-encoded secret\n *\n * Creates a cryptographically secure random secret suitable for OTP generation.\n * The default length of 20 bytes (160 bits) matches RFC 4226 recommendations\n * and provides good security margin.\n *\n * @param options - Secret generation options\n * @returns Base32-encoded secret string (without padding for Google Authenticator compatibility)\n *\n * @example\n * ```ts\n * import { generateSecret } from '@otplib/core';\n * import { NodeCryptoPlugin } from '@otplib/plugin-crypto-node';\n * import { ScureBase32Plugin } from '@otplib/plugin-base32-scure';\n *\n * const secret = generateSecret({\n *   crypto: new NodeCryptoPlugin(),\n *   base32: new ScureBase32Plugin(),\n * });\n * // Returns: 'JBSWY3DPEHPK3PXP...' (32 characters)\n * ```\n *\n * @example Custom length\n * ```ts\n * const secret = generateSecret({\n *   crypto: new NodeCryptoPlugin(),\n *   base32: new ScureBase32Plugin(),\n *   length: 32, // 256 bits for SHA-256\n * });\n * ```\n */\nexport function generateSecret(options: SecretOptions): string {\n  const { crypto, base32, length = RECOMMENDED_SECRET_BYTES } = options;\n\n  requireCryptoPlugin(crypto);\n  requireBase32Plugin(base32);\n\n  const randomBytes = crypto.randomBytes(length);\n  return base32.encode(randomBytes, { padding: false });\n}\n\n/**\n * Normalize counter tolerance to [past, future] tuple\n *\n * Converts a number or tuple counter tolerance specification into a [past, future] tuple\n * - Number: creates look-ahead only tolerance [0, tolerance] (default for security)\n * - Tuple: uses the tuple as-is (past, future)\n *\n * The default behavior (number → look-ahead only) improves security by preventing\n * replay attacks. HOTP counters should only move forward in normal operation.\n *\n * @param counterTolerance - Counter tolerance specification (number or tuple [past, future])\n * @returns Tuple [past, future] representing counters to check\n *\n * @example\n * ```ts\n * normalizeCounterTolerance(0)        // [0, 0]\n * normalizeCounterTolerance(5)        // [0, 5] - look-ahead only (secure default)\n * normalizeCounterTolerance([10, 5])  // [10, 5] - explicit past/future\n * normalizeCounterTolerance([5, 5])   // [5, 5] - explicit symmetric (use with caution)\n * ```\n */\nexport function normalizeCounterTolerance(\n  counterTolerance: number | [number, number] = 0,\n): [number, number] {\n  return Array.isArray(counterTolerance) ? counterTolerance : [0, counterTolerance];\n}\n\n/**\n * Normalize epoch tolerance to [past, future] tuple\n *\n * Converts a number or tuple epoch tolerance specification into a [past, future] tuple\n * - Number: creates symmetric tolerance [tolerance, tolerance]\n * - Tuple: uses the tuple as-is\n *\n * @param epochTolerance - Epoch tolerance specification (number or tuple [past, future])\n * @returns Tuple [pastTolerance, futureTolerance] in seconds\n *\n * @example\n * ```ts\n * normalizeEpochTolerance(0)        // [0, 0]\n * normalizeEpochTolerance(30)       // [30, 30]\n * normalizeEpochTolerance([5, 0])   // [5, 0]\n * normalizeEpochTolerance([10, 5])  // [10, 5]\n * ```\n */\nexport function normalizeEpochTolerance(\n  epochTolerance: number | [number, number] = 0,\n): [number, number] {\n  return Array.isArray(epochTolerance) ? epochTolerance : [epochTolerance, epochTolerance];\n}\n\n/**\n * Require crypto plugin to be configured\n *\n * @param crypto - The crypto plugin\n * @throws {CryptoPluginMissingError} If crypto plugin is not set\n */\nexport function requireCryptoPlugin<T>(crypto: T | undefined): asserts crypto is T {\n  if (!crypto) {\n    throw new CryptoPluginMissingError();\n  }\n}\n\n/**\n * Require Base32 plugin to be configured\n *\n * @param base32 - The Base32 plugin\n * @throws {Base32PluginMissingError} If Base32 plugin is not set\n */\nexport function requireBase32Plugin<T>(base32: T | undefined): asserts base32 is T {\n  if (!base32) {\n    throw new Base32PluginMissingError();\n  }\n}\n\n/**\n * Require secret to be configured\n *\n * @param secret - The secret value\n * @throws {SecretMissingError} If secret is not set\n */\nexport function requireSecret<T>(secret: T | undefined): asserts secret is T {\n  if (!secret) {\n    throw new SecretMissingError();\n  }\n}\n\n/**\n * Require label to be configured (for URI generation)\n *\n * @param label - The label value\n * @throws {LabelMissingError} If label is not set\n */\nexport function requireLabel(label: string | undefined): asserts label is string {\n  if (!label) {\n    throw new LabelMissingError();\n  }\n}\n\n/**\n * Require issuer to be configured (for URI generation)\n *\n * @param issuer - The issuer value\n * @throws {IssuerMissingError} If issuer is not set\n */\nexport function requireIssuer(issuer: string | undefined): asserts issuer is string {\n  if (!issuer) {\n    throw new IssuerMissingError();\n  }\n}\n\n/**\n * Require secret to be a Base32 string (for URI generation)\n *\n * @param secret - The secret value\n * @throws {SecretTypeError} If secret is not a string\n */\nexport function requireBase32String(secret: string | Uint8Array): asserts secret is string {\n  if (typeof secret !== \"string\") {\n    throw new SecretTypeError();\n  }\n}\n\n/**\n * Create a success result\n * @internal\n */\nfunction ok<T>(value: T): OTPResultOk<T> {\n  return { ok: true, value };\n}\n\n/**\n * Create a failure result\n * @internal\n */\nfunction err<E>(error: E): OTPResultError<E> {\n  return { ok: false, error };\n}\n\n/**\n * Wrap a synchronous function to return OTPResult instead of throwing\n *\n * Preserves the original OTPError subclass so users can access\n * specific error information via instanceof checks.\n *\n * @internal\n */\nexport function wrapResult<T, Args extends unknown[]>(\n  fn: (...args: Args) => T,\n): (...args: Args) => OTPResult<T, OTPError> {\n  return (...args: Args): OTPResult<T, OTPError> => {\n    try {\n      return ok(fn(...args));\n    } catch (error) {\n      return err(error as OTPError);\n    }\n  };\n}\n\n/**\n * Wrap an async function to return OTPResult instead of throwing\n *\n * Preserves the original OTPError subclass so users can access\n * specific error information via instanceof checks.\n *\n * @internal\n */\nexport function wrapResultAsync<T, Args extends unknown[]>(\n  fn: (...args: Args) => Promise<T>,\n): (...args: Args) => Promise<OTPResult<T, OTPError>> {\n  return async (...args: Args): Promise<OTPResult<T, OTPError>> => {\n    try {\n      return ok(await fn(...args));\n    } catch (error) {\n      return err(error as OTPError);\n    }\n  };\n}\n","/**\n * Options for OTPError construction\n */\nexport type OTPErrorOptions = {\n  /**\n   * The underlying error that caused this error.\n   * Useful for error chaining and debugging.\n   */\n  cause?: unknown;\n};\n\n/**\n * Base error class for all otplib errors\n *\n * Supports ES2022 error chaining via the `cause` property.\n *\n * @example\n * ```typescript\n * try {\n *   // ... operation that throws\n * } catch (error) {\n *   throw new OTPError('Operation failed', { cause: error });\n * }\n * ```\n */\nexport class OTPError extends Error {\n  constructor(message: string, options?: OTPErrorOptions) {\n    super(message, options);\n    this.name = \"OTPError\";\n  }\n}\n\n/**\n * Error thrown when secret validation fails\n */\nexport class SecretError extends OTPError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"SecretError\";\n  }\n}\n\n/**\n * Error thrown when secret is too short (< 128 bits)\n */\nexport class SecretTooShortError extends SecretError {\n  constructor(minBytes: number, actualBytes: number) {\n    super(\n      `Secret must be at least ${minBytes} bytes (${minBytes * 8} bits), got ${actualBytes} bytes`,\n    );\n    this.name = \"SecretTooShortError\";\n  }\n}\n\n/**\n * Error thrown when secret is unreasonably large (> 64 bytes)\n */\nexport class SecretTooLongError extends SecretError {\n  constructor(maxBytes: number, actualBytes: number) {\n    super(`Secret must not exceed ${maxBytes} bytes, got ${actualBytes} bytes`);\n    this.name = \"SecretTooLongError\";\n  }\n}\n\n/**\n * Error thrown when counter is invalid\n */\nexport class CounterError extends OTPError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"CounterError\";\n  }\n}\n\n/**\n * Error thrown when counter is negative\n */\nexport class CounterNegativeError extends CounterError {\n  constructor() {\n    super(\"Counter must be non-negative\");\n    this.name = \"CounterNegativeError\";\n  }\n}\n\n/**\n * Error thrown when counter exceeds maximum value (2^53 - 1 for safe integer)\n */\nexport class CounterOverflowError extends CounterError {\n  constructor() {\n    super(\"Counter exceeds maximum safe integer value\");\n    this.name = \"CounterOverflowError\";\n  }\n}\n\n/**\n * Error thrown when counter is not an integer\n */\nexport class CounterNotIntegerError extends CounterError {\n  constructor() {\n    super(\"Counter must be a finite integer\");\n    this.name = \"CounterNotIntegerError\";\n  }\n}\n\n/**\n * Error thrown when time is invalid\n */\nexport class TimeError extends OTPError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"TimeError\";\n  }\n}\n\n/**\n * Error thrown when time is negative\n */\nexport class TimeNegativeError extends TimeError {\n  constructor() {\n    super(\"Time must be non-negative\");\n    this.name = \"TimeNegativeError\";\n  }\n}\n\n/**\n * Error thrown when time is not a finite number\n */\nexport class TimeNotFiniteError extends TimeError {\n  constructor() {\n    super(\"Time must be a finite number\");\n    this.name = \"TimeNotFiniteError\";\n  }\n}\n\n/**\n * Error thrown when period is invalid\n */\nexport class PeriodError extends OTPError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"PeriodError\";\n  }\n}\n\n/**\n * Error thrown when period is too small\n */\nexport class PeriodTooSmallError extends PeriodError {\n  constructor(minPeriod: number) {\n    super(`Period must be at least ${minPeriod} second(s)`);\n    this.name = \"PeriodTooSmallError\";\n  }\n}\n\n/**\n * Error thrown when period is too large\n */\nexport class PeriodTooLargeError extends PeriodError {\n  constructor(maxPeriod: number) {\n    super(`Period must not exceed ${maxPeriod} seconds`);\n    this.name = \"PeriodTooLargeError\";\n  }\n}\n\n/**\n * Error thrown when digits value is invalid\n */\nexport class DigitsError extends OTPError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"DigitsError\";\n  }\n}\n\n/**\n * Error thrown when hash algorithm is invalid\n */\nexport class AlgorithmError extends OTPError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"AlgorithmError\";\n  }\n}\n\n/**\n * Error thrown when token is invalid\n */\nexport class TokenError extends OTPError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"TokenError\";\n  }\n}\n\n/**\n * Error thrown when token has incorrect length\n */\nexport class TokenLengthError extends TokenError {\n  constructor(expected: number, actual: number) {\n    super(`Token must be ${expected} digits, got ${actual}`);\n    this.name = \"TokenLengthError\";\n  }\n}\n\n/**\n * Error thrown when token contains non-digit characters\n */\nexport class TokenFormatError extends TokenError {\n  constructor() {\n    super(\"Token must contain only digits\");\n    this.name = \"TokenFormatError\";\n  }\n}\n\n/**\n * Error thrown when crypto operation fails\n */\nexport class CryptoError extends OTPError {\n  constructor(message: string, options?: OTPErrorOptions) {\n    super(message, options);\n    this.name = \"CryptoError\";\n  }\n}\n\n/**\n * Error thrown when HMAC computation fails\n *\n * The original error from the crypto plugin is available via `cause`.\n *\n * @example\n * ```typescript\n * try {\n *   await cryptoContext.hmac('sha1', key, data);\n * } catch (error) {\n *   if (error instanceof HMACError) {\n *     console.log('HMAC failed:', error.message);\n *     console.log('Original error:', error.cause);\n *   }\n * }\n * ```\n */\nexport class HMACError extends CryptoError {\n  constructor(message: string, options?: OTPErrorOptions) {\n    super(`HMAC computation failed: ${message}`, options);\n    this.name = \"HMACError\";\n  }\n}\n\n/**\n * Error thrown when random byte generation fails\n *\n * The original error from the crypto plugin is available via `cause`.\n */\nexport class RandomBytesError extends CryptoError {\n  constructor(message: string, options?: OTPErrorOptions) {\n    super(`Random byte generation failed: ${message}`, options);\n    this.name = \"RandomBytesError\";\n  }\n}\n\n/**\n * Error thrown when Base32 operation fails\n */\nexport class Base32Error extends OTPError {\n  constructor(message: string, options?: OTPErrorOptions) {\n    super(message, options);\n    this.name = \"Base32Error\";\n  }\n}\n\n/**\n * Error thrown when Base32 encoding fails\n *\n * The original error from the Base32 plugin is available via `cause`.\n *\n * @example\n * ```typescript\n * try {\n *   base32Context.encode(data);\n * } catch (error) {\n *   if (error instanceof Base32EncodeError) {\n *     console.log('Encoding failed:', error.message);\n *     console.log('Original error:', error.cause);\n *   }\n * }\n * ```\n */\nexport class Base32EncodeError extends Base32Error {\n  constructor(message: string, options?: OTPErrorOptions) {\n    super(`Base32 encoding failed: ${message}`, options);\n    this.name = \"Base32EncodeError\";\n  }\n}\n\n/**\n * Error thrown when Base32 decoding fails\n *\n * The original error from the Base32 plugin is available via `cause`.\n *\n * @example\n * ```typescript\n * try {\n *   base32Context.decode(invalidString);\n * } catch (error) {\n *   if (error instanceof Base32DecodeError) {\n *     console.log('Decoding failed:', error.message);\n *     console.log('Original error:', error.cause);\n *   }\n * }\n * ```\n */\nexport class Base32DecodeError extends Base32Error {\n  constructor(message: string, options?: OTPErrorOptions) {\n    super(`Base32 decoding failed: ${message}`, options);\n    this.name = \"Base32DecodeError\";\n  }\n}\n\n/**\n * Error thrown when counter tolerance is invalid\n */\nexport class CounterToleranceError extends OTPError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"CounterToleranceError\";\n  }\n}\n\n/**\n * Error thrown when counter tolerance is too large\n */\nexport class CounterToleranceTooLargeError extends CounterToleranceError {\n  constructor(maxWindow: number, totalChecks: number) {\n    super(\n      `Counter tolerance validation failed: total checks (${totalChecks}) exceeds MAX_WINDOW (${maxWindow})`,\n    );\n    this.name = \"CounterToleranceTooLargeError\";\n  }\n}\n\n/**\n * Error thrown when counter tolerance contains negative values\n */\nexport class CounterToleranceNegativeError extends CounterToleranceError {\n  constructor() {\n    super(\"Counter tolerance cannot contain negative values\");\n    this.name = \"CounterToleranceNegativeError\";\n  }\n}\n\n/**\n * Error thrown when epoch tolerance is invalid\n */\nexport class EpochToleranceError extends OTPError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"EpochToleranceError\";\n  }\n}\n\n/**\n * Error thrown when epoch tolerance contains negative values\n */\nexport class EpochToleranceNegativeError extends EpochToleranceError {\n  constructor() {\n    super(\"Epoch tolerance cannot contain negative values\");\n    this.name = \"EpochToleranceNegativeError\";\n  }\n}\n\n/**\n * Error thrown when epoch tolerance is too large\n */\nexport class EpochToleranceTooLargeError extends EpochToleranceError {\n  constructor(maxTolerance: number, actualValue: number) {\n    super(\n      `Epoch tolerance must not exceed ${maxTolerance} seconds, got ${actualValue}. ` +\n        `Large tolerances can cause performance issues.`,\n    );\n    this.name = \"EpochToleranceTooLargeError\";\n  }\n}\n\n/**\n * Error thrown when a required plugin is missing\n */\nexport class PluginError extends OTPError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"PluginError\";\n  }\n}\n\n/**\n * Error thrown when crypto plugin is not configured\n */\nexport class CryptoPluginMissingError extends PluginError {\n  constructor() {\n    super(\"Crypto plugin is required.\");\n    this.name = \"CryptoPluginMissingError\";\n  }\n}\n\n/**\n * Error thrown when Base32 plugin is not configured\n */\nexport class Base32PluginMissingError extends PluginError {\n  constructor() {\n    super(\"Base32 plugin is required.\");\n    this.name = \"Base32PluginMissingError\";\n  }\n}\n\n/**\n * Error thrown when required configuration is missing\n */\nexport class ConfigurationError extends OTPError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"ConfigurationError\";\n  }\n}\n\n/**\n * Error thrown when secret is not configured\n */\nexport class SecretMissingError extends ConfigurationError {\n  constructor() {\n    super(\n      \"Secret is required. \" +\n        \"Use generateSecret() to create one, or provide via { secret: 'YOUR_BASE32_SECRET' }\",\n    );\n    this.name = \"SecretMissingError\";\n  }\n}\n\n/**\n * Error thrown when label is not configured (required for URI generation)\n */\nexport class LabelMissingError extends ConfigurationError {\n  constructor() {\n    super(\"Label is required for URI generation. Example: { label: 'user@example.com' }\");\n    this.name = \"LabelMissingError\";\n  }\n}\n\n/**\n * Error thrown when issuer is not configured (required for URI generation)\n */\nexport class IssuerMissingError extends ConfigurationError {\n  constructor() {\n    super(\"Issuer is required for URI generation. Example: { issuer: 'MyApp' }\");\n    this.name = \"IssuerMissingError\";\n  }\n}\n\n/**\n * Error thrown when secret must be a Base32 string but is provided as bytes\n */\nexport class SecretTypeError extends ConfigurationError {\n  constructor() {\n    super(\n      \"Class API requires secret to be a Base32 string, not Uint8Array. \" +\n        \"Use generateSecret() or provide a Base32-encoded string.\",\n    );\n    this.name = \"SecretTypeError\";\n  }\n}\n\n/**\n * Error thrown when afterTimeStep parameter is invalid\n */\nexport class AfterTimeStepError extends OTPError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"AfterTimeStepError\";\n  }\n}\n\n/**\n * Error thrown when afterTimeStep is negative\n */\nexport class AfterTimeStepNegativeError extends AfterTimeStepError {\n  constructor() {\n    super(\"afterTimeStep must be >= 0\");\n    this.name = \"AfterTimeStepNegativeError\";\n  }\n}\n\n/**\n * Error thrown when afterTimeStep is not an integer\n */\nexport class AfterTimeStepNotIntegerError extends AfterTimeStepError {\n  constructor() {\n    super(\"Invalid afterTimeStep: non-integer value\");\n    this.name = \"AfterTimeStepNotIntegerError\";\n  }\n}\n\n/**\n * Error thrown when afterTimeStep exceeds the verification range\n */\nexport class AfterTimeStepRangeExceededError extends AfterTimeStepError {\n  constructor() {\n    super(\"Invalid afterTimeStep: cannot be greater than current time step plus window\");\n    this.name = \"AfterTimeStepRangeExceededError\";\n  }\n}\n"],"mappings":"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","names":["utils_exports","__export","DEFAULT_PERIOD","MAX_COUNTER","MAX_PERIOD","MAX_SECRET_BYTES","MAX_WINDOW","MIN_PERIOD","MIN_SECRET_BYTES","RECOMMENDED_SECRET_BYTES","bytesToString","constantTimeEqual","counterToBytes","createGuardrails","dynamicTruncate","generateSecret","getDigestSize","hasGuardrailOverrides","normalizeCounterTolerance","normalizeEpochTolerance","normalizeSecret","requireBase32Plugin","requireBase32String","requireCryptoPlugin","requireIssuer","requireLabel","requireSecret","stringToBytes","truncateDigits","validateByteLengthEqual","validateCounter","validateCounterTolerance","validateEpochTolerance","validatePeriod","validateSecret","validateTime","validateToken","wrapResult","wrapResultAsync","__toCommonJS","OTPError","message","options","SecretError","SecretTooShortError","minBytes","actualBytes","SecretTooLongError","maxBytes","CounterError","CounterNegativeError","CounterOverflowError","CounterNotIntegerError","TimeError","TimeNegativeError","TimeNotFiniteError","PeriodError","PeriodTooSmallError","minPeriod","PeriodTooLargeError","maxPeriod","TokenError","OTPError","message","TokenLengthError","expected","actual","TokenFormatError","CounterToleranceError","OTPError","message","CounterToleranceTooLargeError","maxWindow","totalChecks","CounterToleranceNegativeError","EpochToleranceError","EpochToleranceNegativeError","EpochToleranceTooLargeError","maxTolerance","actualValue","PluginError","CryptoPluginMissingError","Base32PluginMissingError","ConfigurationError","SecretMissingError","LabelMissingError","IssuerMissingError","SecretTypeError","textEncoder","textDecoder","MIN_SECRET_BYTES","MAX_SECRET_BYTES","RECOMMENDED_SECRET_BYTES","MIN_PERIOD","MAX_PERIOD","DEFAULT_PERIOD","MAX_COUNTER","MAX_WINDOW","OVERRIDE_SYMBOL","assertGuardrailSafeInteger","name","value","min","ConfigurationError","DEFAULT_GUARDRAILS","createGuardrails","custom","merged","hasGuardrailOverrides","guardrails","validateSecret","secret","SecretTooShortError","SecretTooLongError","validateCounter","counter","CounterNotIntegerError","CounterOverflowError","CounterNegativeError","validateTime","time","TimeNotFiniteError","TimeNegativeError","validatePeriod","period","PeriodTooSmallError","PeriodTooLargeError","validateToken","token","digits","TokenLengthError","TokenFormatError","validateCounterTolerance","counterTolerance","past","future","normalizeCounterTolerance","CounterToleranceError","CounterToleranceNegativeError","totalChecks","CounterToleranceTooLargeError","validateEpochTolerance","epochTolerance","pastTolerance","futureTolerance","EpochToleranceError","EpochToleranceNegativeError","maxToleranceSeconds","totalToleranceSeconds","EpochToleranceTooLargeError","counterToBytes","bigintValue","buffer","dynamicTruncate","hmacResult","offset","truncateDigits","maxOtp","validateByteLengthEqual","a","b","constantTimeEqual","bufA","stringToBytes","bufB","result","i","getDigestSize","algorithm","bytesToString","bytes","normalizeSecret","base32","requireBase32Plugin","generateSecret","options","crypto","length","requireCryptoPlugin","randomBytes","normalizeEpochTolerance","CryptoPluginMissingError","Base32PluginMissingError","requireSecret","SecretMissingError","requireLabel","label","LabelMissingError","requireIssuer","issuer","IssuerMissingError","requireBase32String","SecretTypeError","ok","err","error","wrapResult","fn","args","wrapResultAsync"]}