{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/utils.ts","../src/crypto-context.ts","../src/base32-context.ts","../src/plugin-factories.ts","../src/utility-types.ts"],"sourcesContent":["export type {\n  Base32EncodeOptions,\n  Base32Plugin,\n  CryptoPlugin,\n  Digits,\n  HashAlgorithm,\n  OTPHooks,\n  SecretOptions,\n  OTPResult,\n  OTPResultOk,\n  OTPResultError,\n} from \"./types.js\";\n\nexport type { OTPGuardrailsConfig, OTPGuardrails } from \"./utils.js\";\n\nexport {\n  OTPError,\n  SecretError,\n  SecretTooShortError,\n  SecretTooLongError,\n  CounterError,\n  CounterNegativeError,\n  CounterOverflowError,\n  CounterNotIntegerError,\n  TimeError,\n  TimeNegativeError,\n  TimeNotFiniteError,\n  PeriodError,\n  PeriodTooSmallError,\n  PeriodTooLargeError,\n  DigitsError,\n  AlgorithmError,\n  AlgorithmUnsupportedError,\n  type AlgorithmUnsupportedContext,\n  TokenError,\n  TokenLengthError,\n  TokenFormatError,\n  CryptoError,\n  HMACError,\n  RandomBytesError,\n  Base32Error,\n  Base32EncodeError,\n  Base32DecodeError,\n  CounterToleranceError,\n  CounterToleranceTooLargeError,\n  CounterToleranceNegativeError,\n  EpochToleranceError,\n  EpochToleranceNegativeError,\n  EpochToleranceTooLargeError,\n  PluginError,\n  CryptoPluginMissingError,\n  Base32PluginMissingError,\n  ConfigurationError,\n  SecretMissingError,\n  LabelMissingError,\n  IssuerMissingError,\n  SecretTypeError,\n  AfterTimeStepError,\n  AfterTimeStepNegativeError,\n  AfterTimeStepNotIntegerError,\n  AfterTimeStepRangeExceededError,\n  type OTPErrorOptions,\n} from \"./errors.js\";\n\nexport {\n  createGuardrails,\n  hasGuardrailOverrides,\n  HASH_ALGORITHMS,\n  normalizeHashAlgorithm,\n  type NormalizeHashAlgorithmOptions,\n  validateSecret,\n  validateCounter,\n  validateTime,\n  validatePeriod,\n  validateToken,\n  validateCounterTolerance,\n  validateEpochTolerance,\n  counterToBytes,\n  dynamicTruncate,\n  truncateDigits,\n  validateByteLengthEqual,\n  constantTimeEqual,\n  getDigestSize,\n  stringToBytes,\n  bytesToString,\n  normalizeSecret,\n  normalizeCounterTolerance,\n  normalizeEpochTolerance,\n  generateSecret,\n  requireCryptoPlugin,\n  requireBase32Plugin,\n  requireSecret,\n  requireLabel,\n  requireIssuer,\n  requireBase32String,\n  wrapResult,\n  wrapResultAsync,\n  MIN_SECRET_BYTES,\n  MAX_SECRET_BYTES,\n  RECOMMENDED_SECRET_BYTES,\n  MIN_PERIOD,\n  MAX_PERIOD,\n  DEFAULT_PERIOD,\n  MAX_COUNTER,\n  MAX_WINDOW,\n} from \"./utils.js\";\n\nexport { CryptoContext, createCryptoContext } from \"./crypto-context.js\";\n\nexport { Base32Context, createBase32Context } from \"./base32-context.js\";\n\nexport { createBase32Plugin, createCryptoPlugin } from \"./plugin-factories.js\";\n\nexport type { CreateBase32PluginOptions, CreateCryptoPluginOptions } from \"./plugin-factories.js\";\n\n// Utility types for enhanced developer experience\nexport type {\n  Brand,\n  Base32Secret,\n  OTPToken,\n  RequireKeys,\n  OptionalKeys,\n  PluginConfig,\n  WithRequiredPlugins,\n  GenerationReady,\n  NarrowBy,\n} from \"./utility-types.js\";\n\nexport { hasPlugins, hasCrypto, hasBase32 } from \"./utility-types.js\";\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 * Additional context for {@link AlgorithmUnsupportedError}\n */\nexport type AlgorithmUnsupportedContext = {\n  /**\n   * The algorithms accepted at the point of failure.\n   *\n   * Supplied by the caller rather than defaulted here: this module has no\n   * business restating the allowlist, and `errors.ts` cannot import it from\n   * `utils.ts` without an import cycle. Every thrower inside the library\n   * passes it. Omitting it drops the \"Expected one of\" clause rather than\n   * guessing, so the message never names a set the caller did not vouch for.\n   */\n  supported?: readonly string[];\n\n  /**\n   * Name of the crypto plugin that rejected the value, when applicable.\n   */\n  plugin?: string;\n};\n\n/**\n * Error thrown when a hash algorithm is not recognised or is outside a\n * plugin's declared supported set\n *\n * The message identifies the declared supported algorithms and, when\n * applicable, the plugin that rejected the request. It deliberately does not\n * render the caller-supplied value; callers should retain that input in their\n * own error context.\n *\n * @example\n * ```typescript\n * try {\n *   crypto.hmac('md5', key, data);\n * } catch (error) {\n *   if (error instanceof AlgorithmUnsupportedError) {\n *     console.log(error.message);\n *     // Unsupported hash algorithm. Expected one of: sha1, sha256, sha512\n *   }\n * }\n * ```\n */\nexport class AlgorithmUnsupportedError extends AlgorithmError {\n  constructor(_value: unknown, context: AlgorithmUnsupportedContext = {}) {\n    const { supported, plugin } = context;\n\n    super(\n      \"Unsupported hash algorithm.\" +\n        (supported ? ` Expected one of: ${supported.join(\", \") || \"(none)\"}` : \"\") +\n        (plugin ? ` [plugin: ${plugin}]` : \"\"),\n    );\n    this.name = \"AlgorithmUnsupportedError\";\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","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  AlgorithmUnsupportedError,\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 * Every accepted name for each supported algorithm, grouped by the canonical\n * name it resolves to\n *\n * Each list includes the canonical name itself, so the lookup built from this\n * needs no separate case for it. (Strictly, a registry such as IANA's lists the\n * canonical `Name` apart from its `Alias` entries; folding them together here\n * keeps the lookup a single branch.)\n *\n * Enumerated rather than derived from a pattern. A pattern is a compressed\n * encoding of this list that can generalize past its intent - an earlier\n * separator-stripping implementation accepted `'sha-2-5-6'` and `'s-h-a-1'`\n * for exactly that reason. Nothing here can drift: the accepted set is the\n * list.\n *\n * The `satisfies` constraint is load-bearing. It requires an entry for every\n * member of {@link HashAlgorithm} and forbids keys outside it, so widening the\n * union fails to compile until aliases are supplied here.\n *\n * @internal\n */\nconst HASH_ALGORITHM_ALIASES = {\n  sha1: [\"sha1\", \"sha-1\", \"sha_1\"],\n  sha256: [\"sha256\", \"sha-256\", \"sha_256\"],\n  sha512: [\"sha512\", \"sha-512\", \"sha_512\"],\n} as const satisfies Record<HashAlgorithm, readonly string[]>;\n\n/**\n * The hash algorithms supported for HMAC operations\n *\n * Derived from `HASH_ALGORITHM_ALIASES` rather than written out again, so\n * the runtime allowlist cannot disagree with the names that resolve to it. That\n * matters because this array is both the default `supported` set and the\n * intersection base in `normalizeHashAlgorithm`: an algorithm missing here is\n * rejected at runtime no matter what the types say.\n *\n * Frozen because it is a runtime allowlist, not merely a type-level constant -\n * types are erased at compile time and would leave the exported array mutable,\n * allowing in-process code to corrupt the validation policy and its reported\n * supported set globally.\n */\nexport const HASH_ALGORITHMS = Object.freeze(\n  Object.keys(HASH_ALGORITHM_ALIASES) as (keyof typeof HASH_ALGORITHM_ALIASES)[],\n);\n\n/**\n * Lowercased name to canonical algorithm\n *\n * A `Map` rather than an object literal: `ALIAS_LOOKUP.get('__proto__')` is\n * `undefined`, whereas an object would resolve `'__proto__'`, `'constructor'`\n * and `'toString'` through the prototype chain and hand back inherited junk.\n * That safety holds by construction, with no `Object.hasOwn` guard to forget.\n *\n * @internal\n */\nconst ALIAS_LOOKUP: ReadonlyMap<string, HashAlgorithm> = new Map(\n  Object.entries(HASH_ALGORITHM_ALIASES).flatMap(([canonical, aliases]) =>\n    aliases.map((alias) => [alias, canonical as HashAlgorithm] as const),\n  ),\n);\n\n/**\n * Options for {@link normalizeHashAlgorithm}\n */\nexport type NormalizeHashAlgorithmOptions = {\n  /**\n   * Accepted algorithms\n   *\n   * **Omitted and empty mean different things, deliberately.** Omitting it (or\n   * passing `undefined`) accepts all of {@link HASH_ALGORITHMS} - the\n   * backward-compatible reading for a `CryptoPlugin` written before\n   * `algorithms` existed, which supports the full set by definition. An\n   * explicit `[]` declares support for nothing and rejects every algorithm; it\n   * must never fall back to the full set, or a plugin could not express that.\n   *\n   * Intersected with {@link HASH_ALGORITHMS}, so this can only ever narrow the\n   * allowlist - a crypto plugin cannot widen the library's supported set.\n   */\n  supported?: readonly HashAlgorithm[];\n\n  /**\n   * Name of the calling crypto plugin, used to enrich the error message\n   */\n  plugin?: string;\n};\n\n/**\n * Normalize and validate a hash algorithm\n *\n * Matching ignores case and accepts an optional `-` or `_` before the digest\n * size, so `'SHA1'`, `'Sha1'`, `'SHA-1'` and `'sha_1'` all resolve to `'sha1'`.\n * This is safe to be forgiving about: every accepted alias names the *same*\n * algorithm. No alias of any other digest appears in the table, so `'sha3-256'`\n * and `'sha-384'` are rejected outright.\n *\n * Anything that is not an alias of a supported algorithm is rejected rather\n * than guessed at, because substituting a *different* algorithm produces\n * self-consistent tokens that do not match conforming implementations using the\n * requested algorithm - a failure that can remain hidden until interoperability\n * is tested.\n *\n * @param value - The algorithm to normalize\n * @param options - Narrowed algorithm set and calling plugin name\n * @returns The canonical lowercase algorithm\n * @throws {AlgorithmUnsupportedError} If the value is not a supported algorithm\n *\n * @example\n * ```typescript\n * normalizeHashAlgorithm('SHA1');   // 'sha1'\n * normalizeHashAlgorithm('SHA-1');  // 'sha1'\n * normalizeHashAlgorithm('sha384'); // throws AlgorithmUnsupportedError\n *\n * // A plugin backed by a restricted implementation\n * normalizeHashAlgorithm('sha256', { supported: ['sha1'], plugin: 'custom' });\n * ```\n */\nexport function normalizeHashAlgorithm(\n  value: unknown,\n  options: NormalizeHashAlgorithmOptions = {},\n): HashAlgorithm {\n  // Tested against `undefined` rather than truthiness, because `[]` must not\n  // take the same branch as an omitted value: omitted means \"the full set\"\n  // (a plugin predating `algorithms` supports all of them), while `[]` means\n  // \"none\" and has to reject everything. Simplifying this to a `.length` check\n  // would silently turn an empty declaration back into the full set.\n  //\n  // The intersection is applied rather than trusting the input: `supported`\n  // reaches here from crypto plugins, including untyped ones, so it may only\n  // ever narrow.\n  const { supported: declared, plugin } = options;\n  const supported =\n    declared === undefined\n      ? HASH_ALGORITHMS\n      : HASH_ALGORITHMS.filter((algorithm) => declared.includes(algorithm));\n\n  if (typeof value === \"string\") {\n    const canonical = ALIAS_LOOKUP.get(value.toLowerCase());\n    if (canonical !== undefined && supported.includes(canonical)) {\n      return canonical;\n    }\n  }\n\n  throw new AlgorithmUnsupportedError(value, { supported, plugin });\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 * @throws {AlgorithmUnsupportedError} If the algorithm is not supported\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    default:\n      throw new AlgorithmUnsupportedError(algorithm, { supported: HASH_ALGORITHMS });\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","import { HMACError, RandomBytesError } from \"./errors.js\";\nimport { normalizeHashAlgorithm } from \"./utils.js\";\n\nimport type { CryptoPlugin, HashAlgorithm } from \"./types.js\";\n\nfunction isPromiseLike(value: Uint8Array | Promise<Uint8Array>): boolean {\n  return typeof (value as { then?: unknown }).then === \"function\";\n}\n\n/**\n * CryptoContext provides a unified interface for crypto operations\n * using a pluggable crypto backend\n */\nexport class CryptoContext {\n  /**\n   * Create a new CryptoContext with the given crypto plugin\n   *\n   * @param crypto - The crypto plugin to use\n   */\n  constructor(private readonly crypto: CryptoPlugin) {}\n\n  /**\n   * Get the underlying crypto plugin\n   */\n  get plugin(): CryptoPlugin {\n    return this.crypto;\n  }\n\n  /**\n   * Resolve an algorithm against the plugin's own supported set\n   *\n   * When a plugin declares `algorithms`, an unsupported value is rejected here\n   * rather than the plugin being left to discover it after delegation.\n   *\n   * @param algorithm - The hash algorithm to resolve\n   * @returns The canonical lowercase algorithm\n   * @throws {AlgorithmUnsupportedError} If the algorithm is not supported\n   */\n  private normalize(algorithm: HashAlgorithm): HashAlgorithm {\n    return normalizeHashAlgorithm(algorithm, {\n      supported: this.crypto.algorithms,\n      plugin: this.crypto.name,\n    });\n  }\n\n  /**\n   * Compute HMAC using the configured crypto plugin\n   *\n   * @param algorithm - The hash algorithm to use\n   * @param key - The secret key as a byte array\n   * @param data - The data to authenticate as a byte array\n   * @returns HMAC digest as a byte array\n   * @throws {AlgorithmUnsupportedError} If the algorithm is not supported\n   * @throws {HMACError} If HMAC computation fails\n   */\n  async hmac(algorithm: HashAlgorithm, key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {\n    // Normalized outside the try so the algorithm error surfaces as-is rather\n    // than being rewrapped as an HMACError.\n    const normalized = this.normalize(algorithm);\n\n    try {\n      return await this.crypto.hmac(normalized, key, data);\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error);\n      throw new HMACError(message, { cause: error });\n    }\n  }\n\n  /**\n   * Synchronous HMAC computation\n   *\n   * @param algorithm - The hash algorithm to use\n   * @param key - The secret key as a byte array\n   * @param data - The data to authenticate as a byte array\n   * @returns HMAC digest as a byte array\n   * @throws {AlgorithmUnsupportedError} If the algorithm is not supported\n   * @throws {HMACError} If HMAC computation fails or if crypto plugin doesn't support sync operations\n   */\n  hmacSync(algorithm: HashAlgorithm, key: Uint8Array, data: Uint8Array): Uint8Array {\n    const normalized = this.normalize(algorithm);\n\n    try {\n      const result = this.crypto.hmac(normalized, key, data);\n\n      if (!isPromiseLike(result)) {\n        return result as Uint8Array;\n      }\n\n      // Attach a rejection handler before throwing the synchronous guard.\n      // Promise.resolve assimilates cross-realm promises and generic thenables.\n      void Promise.resolve(result).catch(() => undefined);\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error);\n      throw new HMACError(message, { cause: error });\n    }\n\n    throw new HMACError(\"Crypto plugin does not support synchronous HMAC operations\");\n  }\n\n  /**\n   * Generate cryptographically secure random bytes\n   *\n   * @param length - Number of random bytes to generate\n   * @returns Random bytes\n   * @throws {RandomBytesError} If random byte generation fails\n   */\n  randomBytes(length: number): Uint8Array {\n    try {\n      return this.crypto.randomBytes(length);\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error);\n      throw new RandomBytesError(message, { cause: error });\n    }\n  }\n}\n\n/**\n * Create a CryptoContext from a crypto plugin\n *\n * @param crypto - The crypto plugin to use\n * @returns A new CryptoContext instance\n */\nexport function createCryptoContext(crypto: CryptoPlugin): CryptoContext {\n  return new CryptoContext(crypto);\n}\n","import { Base32EncodeError, Base32DecodeError } from \"./errors.js\";\n\nimport type { Base32Plugin, Base32EncodeOptions } from \"./types.js\";\n\n/**\n * Base32Context provides a unified interface for Base32 operations\n * using a pluggable Base32 backend.\n *\n * All errors from the underlying plugin are wrapped in otplib error types\n * with the original error preserved via the `cause` property.\n */\nexport class Base32Context {\n  /**\n   * Create a new Base32Context with the given Base32 plugin\n   *\n   * @param base32 - The Base32 plugin to use\n   */\n  constructor(private readonly base32: Base32Plugin) {}\n\n  /**\n   * Get the underlying Base32 plugin\n   */\n  get plugin(): Base32Plugin {\n    return this.base32;\n  }\n\n  /**\n   * Encode binary data to Base32 string using the configured plugin\n   *\n   * @param data - Uint8Array to encode\n   * @param options - Encoding options\n   * @returns Base32 encoded string\n   * @throws {Base32EncodeError} If encoding fails\n   */\n  encode(data: Uint8Array, options?: Base32EncodeOptions): string {\n    try {\n      return this.base32.encode(data, options);\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error);\n      throw new Base32EncodeError(message, { cause: error });\n    }\n  }\n\n  /**\n   * Decode Base32 string to binary data using the configured plugin\n   *\n   * @param str - Base32 string to decode\n   * @returns Decoded Uint8Array\n   * @throws {Base32DecodeError} If string contains invalid characters or decoding fails\n   */\n  decode(str: string): Uint8Array {\n    try {\n      return this.base32.decode(str);\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error);\n      throw new Base32DecodeError(message, { cause: error });\n    }\n  }\n}\n\n/**\n * Create a Base32Context from a Base32 plugin\n *\n * @param base32 - The Base32 plugin to use\n * @returns A new Base32Context instance\n */\nexport function createBase32Context(base32: Base32Plugin): Base32Context {\n  return new Base32Context(base32);\n}\n","import { Base32DecodeError, Base32EncodeError } from \"./errors.js\";\nimport { constantTimeEqual, normalizeHashAlgorithm } from \"./utils.js\";\n\nimport type { Base32EncodeOptions, Base32Plugin, CryptoPlugin, HashAlgorithm } from \"./types.js\";\n\n/**\n * Options for creating a custom Base32 plugin\n */\nexport type CreateBase32PluginOptions = {\n  /**\n   * Plugin name for identification (default: \"custom\")\n   */\n  name?: string;\n\n  /**\n   * Encode binary data to string\n   */\n  encode: (data: Uint8Array) => string;\n\n  /**\n   * Decode string to binary data\n   */\n  decode: (str: string) => Uint8Array;\n};\n\n/**\n * Options for creating a custom Crypto plugin\n */\nexport type CreateCryptoPluginOptions = {\n  /**\n   * Plugin name for identification (default: \"custom\")\n   */\n  name?: string;\n\n  /**\n   * The algorithms this plugin can compute, when it supports fewer than all of\n   * {@link HASH_ALGORITHMS}\n   *\n   * Omit it unless the backing implementation is genuinely restricted - an\n   * absent value means the full set. Declaring it is enforced, not advisory:\n   * the factory rejects an undeclared algorithm before `hmac` is called, so the\n   * implementation below never sees a value it cannot handle.\n   *\n   * This can only narrow. The value is intersected with `HASH_ALGORITHMS`, so\n   * listing a digest outside that set does not enable it.\n   */\n  algorithms?: readonly HashAlgorithm[];\n\n  /**\n   * Compute HMAC using the specified hash algorithm\n   *\n   * Receives the canonical lowercase name, already checked against\n   * `algorithms` - no validation is needed here.\n   */\n  hmac: (\n    algorithm: HashAlgorithm,\n    key: Uint8Array,\n    data: Uint8Array,\n  ) => Promise<Uint8Array> | Uint8Array;\n\n  /**\n   * Generate cryptographically secure random bytes\n   */\n  randomBytes: (length: number) => Uint8Array;\n\n  /**\n   * Constant-time comparison (optional, falls back to core utility)\n   */\n  constantTimeEqual?: (a: string | Uint8Array, b: string | Uint8Array) => boolean;\n};\n\n/**\n * Create a custom Base32 plugin from encode/decode functions\n *\n * Use this factory to create plugins that bypass Base32 encoding\n * or implement custom secret transformations.\n *\n * @example\n * ```ts\n * import { createBase32Plugin, stringToBytes, bytesToString } from '@otplib/core';\n *\n * // UTF-8 string bypass (no Base32)\n * const bypassAsString = createBase32Plugin({\n *   name: 'bypass-as-string',\n *   encode: bytesToString,\n *   decode: stringToBytes,\n * });\n *\n * // Base64 bypass\n * const base64Bypass = createBase32Plugin({\n *   name: 'base64-bypass',\n *   encode: (data) => btoa(String.fromCharCode(...data)),\n *   decode: (str) => new Uint8Array([...atob(str)].map(c => c.charCodeAt(0))),\n * });\n * ```\n */\nexport function createBase32Plugin(options: CreateBase32PluginOptions): Base32Plugin {\n  const { name = \"custom\", encode, decode } = options;\n\n  return Object.freeze({\n    name,\n    encode: (data: Uint8Array, _options?: Base32EncodeOptions) => {\n      try {\n        return encode(data);\n      } catch (error) {\n        const message = error instanceof Error ? error.message : String(error);\n        throw new Base32EncodeError(message, { cause: error });\n      }\n    },\n    decode: (str: string) => {\n      try {\n        return decode(str);\n      } catch (error) {\n        const message = error instanceof Error ? error.message : String(error);\n        throw new Base32DecodeError(message, { cause: error });\n      }\n    },\n  });\n}\n\n/**\n * Create a custom Crypto plugin from crypto operation functions\n *\n * Use this factory when you need a custom cryptographic implementation\n * that doesn't fit the existing plugins (node, web, noble).\n *\n * The returned plugin validates the algorithm before delegating, so `hmac`\n * receives the canonical lowercase name and never has to guess at an\n * unrecognised one. A plugin declaring `algorithms` is held to that\n * declaration: anything outside it throws `AlgorithmUnsupportedError`, whether\n * the plugin is called directly or through `CryptoContext`.\n *\n * @example\n * ```ts\n * import { createCryptoPlugin } from '@otplib/core';\n *\n * const customCrypto = createCryptoPlugin({\n *   name: 'my-crypto',\n *   hmac: async (algorithm, key, data) => {\n *     // Custom HMAC implementation - `algorithm` is already validated\n *   },\n *   randomBytes: (length) => {\n *     // Custom random bytes implementation\n *   },\n * });\n *\n * // A plugin backed by a restricted implementation\n * const sha1Only = createCryptoPlugin({\n *   name: 'sha1-only',\n *   algorithms: ['sha1'],\n *   hmac: (algorithm, key, data) => computeSha1Hmac(key, data),\n *   randomBytes: (length) => crypto.getRandomValues(new Uint8Array(length)),\n * });\n *\n * sha1Only.hmac('sha256', key, data); // throws AlgorithmUnsupportedError\n * ```\n */\nexport function createCryptoPlugin(options: CreateCryptoPluginOptions): CryptoPlugin {\n  const { name = \"custom\", algorithms, hmac, randomBytes, constantTimeEqual: cte } = options;\n\n  // Copied and frozen, never held by reference. `readonly` is erased at compile\n  // time, so retaining the caller's array would let them push to it after\n  // construction and broaden a restricted plugin's capability - and the copy is\n  // what both the declaration and the check below read, so the two cannot\n  // diverge.\n  const supportedAlgorithms = algorithms ? Object.freeze([...algorithms]) : undefined;\n\n  return Object.freeze({\n    name,\n    ...(supportedAlgorithms ? { algorithms: supportedAlgorithms } : {}),\n    hmac: (algorithm: HashAlgorithm, key: Uint8Array, data: Uint8Array) =>\n      hmac(\n        normalizeHashAlgorithm(algorithm, { supported: supportedAlgorithms, plugin: name }),\n        key,\n        data,\n      ),\n    randomBytes,\n    constantTimeEqual: cte ?? constantTimeEqual,\n  });\n}\n","/**\n * TypeScript Utility Types for otplib\n *\n * These types enhance developer experience by providing:\n * - Branded types for type-safe string handling\n * - Type guards for discriminated unions\n * - Helper types for option extraction\n */\n\nimport type { CryptoPlugin, Base32Plugin } from \"./types.js\";\n\n/**\n * Brand type for creating nominal types from primitives\n *\n * @example\n * ```ts\n * type UserId = Brand<string, 'UserId'>;\n * const id: UserId = 'abc' as UserId;\n * ```\n */\nexport type Brand<T, B extends string> = T & { readonly __brand: B };\n\n/**\n * Branded string type for Base32-encoded secrets\n *\n * Use this type to distinguish Base32-encoded secrets from regular strings\n * at compile time, preventing accidental misuse.\n *\n * @example\n * ```ts\n * import type { Base32Secret } from '@otplib/core';\n *\n * function processSecret(secret: Base32Secret): void {\n *   // TypeScript ensures only Base32Secret values are passed\n * }\n *\n * const secret = generateSecret() as Base32Secret;\n * processSecret(secret); // OK\n * processSecret('random-string'); // Type error\n * ```\n */\nexport type Base32Secret = Brand<string, \"Base32Secret\">;\n\n/**\n * Branded string type for OTP tokens\n *\n * Use this type to distinguish OTP tokens from regular strings\n * at compile time, preventing accidental misuse.\n *\n * @example\n * ```ts\n * import type { OTPToken } from '@otplib/core';\n *\n * function validateToken(token: OTPToken): boolean {\n *   // TypeScript ensures only OTPToken values are passed\n * }\n *\n * const token = await generate() as OTPToken;\n * validateToken(token); // OK\n * validateToken('123456'); // Type error\n * ```\n */\nexport type OTPToken = Brand<string, \"OTPToken\">;\n\n/**\n * Helper type to make all properties of T required except those in K\n *\n * @example\n * ```ts\n * type Options = { a?: string; b?: number; c?: boolean };\n * type RequiredAB = RequireKeys<Options, 'a' | 'b'>;\n * // { a: string; b: number; c?: boolean }\n * ```\n */\nexport type RequireKeys<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;\n\n/**\n * Helper type to make all properties of T optional except those in K\n *\n * @example\n * ```ts\n * type Options = { a: string; b: number; c: boolean };\n * type OptionalBC = OptionalKeys<Options, 'b' | 'c'>;\n * // { a: string; b?: number; c?: boolean }\n * ```\n */\nexport type OptionalKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;\n\n/**\n * Extract the plugin configuration from an options type\n *\n * @example\n * ```ts\n * type Plugins = PluginConfig<TOTPOptions>;\n * // { crypto: CryptoPlugin; base32?: Base32Plugin }\n * ```\n */\nexport type PluginConfig<T> = T extends { crypto?: CryptoPlugin; base32?: Base32Plugin }\n  ? Pick<T, \"crypto\" | \"base32\">\n  : never;\n\n/**\n * Ensure an options type has plugins defined\n *\n * @example\n * ```ts\n * type ConfiguredOptions = WithRequiredPlugins<TOTPOptions>;\n * // TOTPOptions with crypto and base32 required\n * ```\n */\nexport type WithRequiredPlugins<T extends { crypto?: CryptoPlugin; base32?: Base32Plugin }> = T & {\n  crypto: CryptoPlugin;\n  base32: Base32Plugin;\n};\n\n/**\n * Options type for OTP generation (crypto required)\n *\n * @example\n * ```ts\n * type MyGenerateOptions = GenerationReady<HOTPOptions>;\n * // HOTPOptions with crypto required\n * ```\n */\nexport type GenerationReady<T extends { crypto?: CryptoPlugin }> = T & {\n  crypto: CryptoPlugin;\n};\n\n/**\n * Type predicate to check if an object has the required plugins\n *\n * @example\n * ```ts\n * const options = getOptions();\n * if (hasPlugins(options)) {\n *   // TypeScript knows plugins are defined\n *   options.crypto.hmac(...);\n * }\n * ```\n */\nexport function hasPlugins<T extends { crypto?: CryptoPlugin; base32?: Base32Plugin }>(\n  options: T,\n): options is T & { crypto: CryptoPlugin; base32: Base32Plugin } {\n  return options.crypto !== undefined && options.base32 !== undefined;\n}\n\n/**\n * Type predicate to check if an object has a crypto plugin\n *\n * @example\n * ```ts\n * if (hasCrypto(options)) {\n *   await options.crypto.hmac('sha1', key, data);\n * }\n * ```\n */\nexport function hasCrypto<T extends { crypto?: CryptoPlugin }>(\n  options: T,\n): options is T & { crypto: CryptoPlugin } {\n  return options.crypto !== undefined;\n}\n\n/**\n * Type predicate to check if an object has a base32 plugin\n *\n * @example\n * ```ts\n * if (hasBase32(options)) {\n *   const decoded = options.base32.decode(secret);\n * }\n * ```\n */\nexport function hasBase32<T extends { base32?: Base32Plugin }>(\n  options: T,\n): options is T & { base32: Base32Plugin } {\n  return options.base32 !== undefined;\n}\n\n/**\n * Narrow union type by a specific property value\n *\n * @example\n * ```ts\n * type Result = VerifyResultValid | VerifyResultInvalid;\n * type ValidOnly = NarrowBy<Result, 'valid', true>;\n * // VerifyResultValid\n * ```\n */\nexport type NarrowBy<T, K extends keyof T, V extends T[K]> = T extends { [key in K]: V }\n  ? T\n  : never;\n"],"mappings":"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","names":["src_exports","__export","AfterTimeStepError","AfterTimeStepNegativeError","AfterTimeStepNotIntegerError","AfterTimeStepRangeExceededError","AlgorithmError","AlgorithmUnsupportedError","Base32Context","Base32DecodeError","Base32EncodeError","Base32Error","Base32PluginMissingError","ConfigurationError","CounterError","CounterNegativeError","CounterNotIntegerError","CounterOverflowError","CounterToleranceError","CounterToleranceNegativeError","CounterToleranceTooLargeError","CryptoContext","CryptoError","CryptoPluginMissingError","DEFAULT_PERIOD","DigitsError","EpochToleranceError","EpochToleranceNegativeError","EpochToleranceTooLargeError","HASH_ALGORITHMS","HMACError","IssuerMissingError","LabelMissingError","MAX_COUNTER","MAX_PERIOD","MAX_SECRET_BYTES","MAX_WINDOW","MIN_PERIOD","MIN_SECRET_BYTES","OTPError","PeriodError","PeriodTooLargeError","PeriodTooSmallError","PluginError","RECOMMENDED_SECRET_BYTES","RandomBytesError","SecretError","SecretMissingError","SecretTooLongError","SecretTooShortError","SecretTypeError","TimeError","TimeNegativeError","TimeNotFiniteError","TokenError","TokenFormatError","TokenLengthError","bytesToString","constantTimeEqual","counterToBytes","createBase32Context","createBase32Plugin","createCryptoContext","createCryptoPlugin","createGuardrails","dynamicTruncate","generateSecret","getDigestSize","hasBase32","hasCrypto","hasGuardrailOverrides","hasPlugins","normalizeCounterTolerance","normalizeEpochTolerance","normalizeHashAlgorithm","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","DigitsError","AlgorithmError","AlgorithmUnsupportedError","_value","context","supported","plugin","TokenError","TokenLengthError","expected","actual","TokenFormatError","CryptoError","HMACError","RandomBytesError","Base32Error","Base32EncodeError","Base32DecodeError","CounterToleranceError","CounterToleranceTooLargeError","maxWindow","totalChecks","CounterToleranceNegativeError","EpochToleranceError","EpochToleranceNegativeError","EpochToleranceTooLargeError","maxTolerance","actualValue","PluginError","CryptoPluginMissingError","Base32PluginMissingError","ConfigurationError","SecretMissingError","LabelMissingError","IssuerMissingError","SecretTypeError","AfterTimeStepError","AfterTimeStepNegativeError","AfterTimeStepNotIntegerError","AfterTimeStepRangeExceededError","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","HASH_ALGORITHM_ALIASES","HASH_ALGORITHMS","ALIAS_LOOKUP","canonical","aliases","alias","normalizeHashAlgorithm","options","declared","plugin","supported","algorithm","AlgorithmUnsupportedError","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","bytesToString","bytes","normalizeSecret","base32","requireBase32Plugin","generateSecret","crypto","length","requireCryptoPlugin","randomBytes","normalizeEpochTolerance","CryptoPluginMissingError","Base32PluginMissingError","requireSecret","SecretMissingError","requireLabel","label","LabelMissingError","requireIssuer","issuer","IssuerMissingError","requireBase32String","SecretTypeError","ok","err","error","wrapResult","fn","args","wrapResultAsync","isPromiseLike","value","CryptoContext","crypto","algorithm","normalizeHashAlgorithm","key","data","normalized","error","message","HMACError","result","length","RandomBytesError","createCryptoContext","Base32Context","base32","data","options","error","message","Base32EncodeError","str","Base32DecodeError","createBase32Context","createBase32Plugin","options","name","encode","decode","data","_options","error","message","Base32EncodeError","str","Base32DecodeError","createCryptoPlugin","algorithms","hmac","randomBytes","cte","supportedAlgorithms","algorithm","key","normalizeHashAlgorithm","constantTimeEqual","hasPlugins","options","hasCrypto","hasBase32"]}