otplib 13.1.0 → 13.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -93,6 +93,21 @@ const uri = otp.generateURI({
93
93
  });
94
94
  ```
95
95
 
96
+ ## Notes
97
+
98
+ ### Secret Format
99
+
100
+ By default, otplib expects secrets to be in **Base32** format. While the core HOTP (RFC 4226) and TOTP (RFC 6238) specifications work with raw binary data and don't mandate Base32 encoding, Base32 is the standard format used by authenticator applications and QR code URIs for compatibility.
101
+
102
+ ```typescript
103
+ // Base32 secret (standard format for authenticator compatibility)
104
+ const secret = "GEZDGNBVGY3TQOJQGEZDGNBVGY";
105
+ ```
106
+
107
+ However, if you need to use secrets in other formats, you can either use the `plugin-base32-alt` plugin for raw strings or pass a byte array (using `stringToBytes` helper) for binary data.
108
+
109
+ For more details and examples, see the [Secret Handling Guide](https://otplib.yeojz.dev/guide/secret-handling.md) and related plugin documentation in the guides directory.
110
+
96
111
  ## Documentation
97
112
 
98
113
  Refer to the [Getting Started Guide](https://otplib.yeojz.dev/guide/getting-started), or check out the other sections in the guide:
package/dist/class.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var T=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var B=Object.prototype.hasOwnProperty;var U=(t,e)=>{for(var r in e)T(t,r,{get:e[r],enumerable:!0})},w=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of D(e))!B.call(t,o)&&o!==r&&T(t,o,{get:()=>e[o],enumerable:!(n=C(e,o))||n.enumerable});return t};var I=t=>w(T({},"__esModule",{value:!0}),t);var k={};U(k,{OTP:()=>b});module.exports=I(k);var G=require("@otplib/core");var d=require("@otplib/plugin-base32-scure"),S=require("@otplib/plugin-crypto-noble"),l=Object.freeze(new S.NobleCryptoPlugin),f=Object.freeze(new d.ScureBase32Plugin);function m(t){return{secret:t.secret,strategy:t.strategy??"totp",crypto:t.crypto??l,base32:t.base32??f,algorithm:t.algorithm??"sha1",digits:t.digits??6,period:t.period??30,epoch:t.epoch??Math.floor(Date.now()/1e3),t0:t.t0??0,counter:t.counter}}function P(t){return{...m(t),token:t.token,epochTolerance:t.epochTolerance??0,counterTolerance:t.counterTolerance??0}}var O=require("@otplib/core"),c=require("@otplib/hotp"),y=require("@otplib/totp"),h=require("@otplib/uri");function u(t,e,r){if(t==="totp")return r.totp();if(t==="hotp"){if(e===void 0)throw new O.ConfigurationError("Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }");return r.hotp(e)}throw new O.ConfigurationError(`Unknown OTP strategy: ${t}. Valid strategies are 'totp' or 'hotp'.`)}function V(t){let{strategy:e="totp",issuer:r,label:n,secret:o,algorithm:a="sha1",digits:p=6,period:i=30,counter:s}=t;return u(e,s,{totp:()=>(0,h.generateTOTP)({issuer:r,label:n,secret:o,algorithm:a,digits:p,period:i}),hotp:g=>(0,h.generateHOTP)({issuer:r,label:n,secret:o,algorithm:a,digits:p,counter:g})})}async function R(t){let e=m(t),{secret:r,crypto:n,base32:o,algorithm:a,digits:p}=e,i={secret:r,crypto:n,base32:o,algorithm:a,digits:p};return u(e.strategy,e.counter,{totp:()=>(0,y.generate)({...i,period:e.period,epoch:e.epoch,t0:e.t0}),hotp:s=>(0,c.generate)({...i,counter:s})})}function x(t){let e=m(t),{secret:r,crypto:n,base32:o,algorithm:a,digits:p}=e,i={secret:r,crypto:n,base32:o,algorithm:a,digits:p};return u(e.strategy,e.counter,{totp:()=>(0,y.generateSync)({...i,period:e.period,epoch:e.epoch,t0:e.t0}),hotp:s=>(0,c.generateSync)({...i,counter:s})})}async function H(t){let e=P(t),{secret:r,token:n,crypto:o,base32:a,algorithm:p,digits:i}=e,s={secret:r,token:n,crypto:o,base32:a,algorithm:p,digits:i};return u(e.strategy,e.counter,{totp:()=>(0,y.verify)({...s,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance}),hotp:g=>(0,c.verify)({...s,counter:g,counterTolerance:e.counterTolerance})})}function v(t){let e=P(t),{secret:r,token:n,crypto:o,base32:a,algorithm:p,digits:i}=e,s={secret:r,token:n,crypto:o,base32:a,algorithm:p,digits:i};return u(e.strategy,e.counter,{totp:()=>(0,y.verifySync)({...s,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance}),hotp:g=>(0,c.verifySync)({...s,counter:g,counterTolerance:e.counterTolerance})})}var b=class{strategy;crypto;base32;constructor(e={}){let{strategy:r="totp",crypto:n=l,base32:o=f}=e;this.strategy=r,this.crypto=n,this.base32=o}getStrategy(){return this.strategy}generateSecret(e=20){return(0,G.generateSecret)({crypto:this.crypto,base32:this.base32,length:e})}async generate(e){return R({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32})}generateSync(e){return x({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32})}async verify(e){return H({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32})}verifySync(e){return v({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32})}generateURI(e){return V({...e,strategy:this.strategy})}};0&&(module.exports={OTP});
1
+ "use strict";var T=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var B=Object.prototype.hasOwnProperty;var w=(r,e)=>{for(var t in e)T(r,t,{get:e[t],enumerable:!0})},A=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of U(e))!B.call(r,a)&&a!==t&&T(r,a,{get:()=>e[a],enumerable:!(i=D(e,a))||i.enumerable});return r};var I=r=>A(T({},"__esModule",{value:!0}),r);var k={};w(k,{OTP:()=>b});module.exports=I(k);var d=require("@otplib/core");var S=require("@otplib/core"),V=require("@otplib/plugin-base32-scure"),R=require("@otplib/plugin-crypto-noble"),l=Object.freeze(new R.NobleCryptoPlugin),f=Object.freeze(new V.ScureBase32Plugin);function m(r){return{secret:r.secret,strategy:r.strategy??"totp",crypto:r.crypto??l,base32:r.base32??f,algorithm:r.algorithm??"sha1",digits:r.digits??6,period:r.period??30,epoch:r.epoch??Math.floor(Date.now()/1e3),t0:r.t0??0,counter:r.counter,guardrails:r.guardrails??(0,S.createGuardrails)()}}function P(r){return{...m(r),token:r.token,epochTolerance:r.epochTolerance??0,counterTolerance:r.counterTolerance??0}}var O=require("@otplib/core"),g=require("@otplib/hotp"),u=require("@otplib/totp"),h=require("@otplib/uri");function c(r,e,t){if(r==="totp")return t.totp();if(r==="hotp"){if(e===void 0)throw new O.ConfigurationError("Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }");return t.hotp(e)}throw new O.ConfigurationError(`Unknown OTP strategy: ${r}. Valid strategies are 'totp' or 'hotp'.`)}function G(r){let{strategy:e="totp",issuer:t,label:i,secret:a,algorithm:s="sha1",digits:p=6,period:o=30,counter:n}=r;return c(e,n,{totp:()=>(0,h.generateTOTP)({issuer:t,label:i,secret:a,algorithm:s,digits:p,period:o}),hotp:y=>(0,h.generateHOTP)({issuer:t,label:i,secret:a,algorithm:s,digits:p,counter:y})})}async function x(r){let e=m(r),{secret:t,crypto:i,base32:a,algorithm:s,digits:p}=e,o={secret:t,crypto:i,base32:a,algorithm:s,digits:p};return c(e.strategy,e.counter,{totp:()=>(0,u.generate)({...o,period:e.period,epoch:e.epoch,t0:e.t0,guardrails:e.guardrails}),hotp:n=>(0,g.generate)({...o,counter:n,guardrails:e.guardrails})})}function H(r){let e=m(r),{secret:t,crypto:i,base32:a,algorithm:s,digits:p}=e,o={secret:t,crypto:i,base32:a,algorithm:s,digits:p};return c(e.strategy,e.counter,{totp:()=>(0,u.generateSync)({...o,period:e.period,epoch:e.epoch,t0:e.t0,guardrails:e.guardrails}),hotp:n=>(0,g.generateSync)({...o,counter:n,guardrails:e.guardrails})})}async function v(r){let e=P(r),{secret:t,token:i,crypto:a,base32:s,algorithm:p,digits:o}=e,n={secret:t,token:i,crypto:a,base32:s,algorithm:p,digits:o};return c(e.strategy,e.counter,{totp:()=>(0,u.verify)({...n,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance,guardrails:e.guardrails}),hotp:y=>(0,g.verify)({...n,counter:y,counterTolerance:e.counterTolerance,guardrails:e.guardrails})})}function C(r){let e=P(r),{secret:t,token:i,crypto:a,base32:s,algorithm:p,digits:o}=e,n={secret:t,token:i,crypto:a,base32:s,algorithm:p,digits:o};return c(e.strategy,e.counter,{totp:()=>(0,u.verifySync)({...n,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance,guardrails:e.guardrails}),hotp:y=>(0,g.verifySync)({...n,counter:y,counterTolerance:e.counterTolerance,guardrails:e.guardrails})})}var b=class{strategy;crypto;base32;guardrails;constructor(e={}){let{strategy:t="totp",crypto:i=l,base32:a=f,guardrails:s}=e;this.strategy=t,this.crypto=i,this.base32=a,this.guardrails=(0,d.createGuardrails)(s)}getStrategy(){return this.strategy}generateSecret(e=20){return(0,d.generateSecret)({crypto:this.crypto,base32:this.base32,length:e})}async generate(e){return x({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}generateSync(e){return H({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}async verify(e){return v({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}verifySync(e){return C({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}generateURI(e){return G({...e,strategy:this.strategy})}};0&&(module.exports={OTP});
2
2
  //# sourceMappingURL=class.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/class.ts","../src/defaults.ts","../src/functional.ts"],"sourcesContent":["/**\n * OTP Wrapper Class\n *\n * A unified class that dynamically handles TOTP and HOTP strategies.\n */\n\nimport { generateSecret as generateSecretCore } from \"@otplib/core\";\n\nimport { defaultCrypto, defaultBase32 } from \"./defaults\";\nimport {\n generate as functionalGenerate,\n generateSync as functionalGenerateSync,\n verify as functionalVerify,\n verifySync as functionalVerifySync,\n generateURI as functionalGenerateURI,\n} from \"./functional\";\n\nimport type { OTPStrategy } from \"./functional\";\nimport type { CryptoPlugin, Digits, HashAlgorithm, Base32Plugin } from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\n/**\n * Combined verify result that works for both TOTP and HOTP\n */\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\n/**\n * Options for the OTP class\n */\nexport type OTPClassOptions = {\n /**\n * OTP strategy to use\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n */\n strategy?: OTPStrategy;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n};\n\n/**\n * Options for generating a token with the OTP class\n */\nexport type OTPGenerateOptions = {\n /**\n * Base32-encoded secret key\n */\n secret: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n};\n\n/**\n * Options for verifying a token with the OTP class\n */\nexport type OTPVerifyOptions = {\n /**\n * Base32-encoded secret key\n */\n secret: string;\n\n /**\n * OTP code to verify\n */\n token: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n\n /**\n * Time tolerance in seconds for TOTP verification (default: 0)\n * - Number: symmetric tolerance (same for past and future)\n * - Tuple [past, future]: asymmetric tolerance\n * Use [5, 0] for RFC-compliant past-only verification.\n */\n epochTolerance?: number | [number, number];\n\n /**\n * Counter tolerance for HOTP verification (default: 0)\n * - Number: symmetric look-ahead window\n * - Array: asymmetric window\n */\n counterTolerance?: number | number[];\n};\n\n/**\n * Options for generating URI with the OTP class\n */\nexport type OTPURIGenerateOptions = {\n /**\n * Issuer name (e.g., 'ACME Co')\n */\n issuer: string;\n\n /**\n * Label/Account name (e.g., 'john@example.com')\n */\n label: string;\n\n /**\n * Base32-encoded secret key\n */\n secret: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value (default: 0)\n * Used by HOTP strategy\n */\n counter?: number;\n};\n\n/**\n * OTP Class\n *\n * A wrapper class that dynamically handles TOTP and HOTP strategies.\n *\n * @example\n * ```ts\n * import { OTP } from 'otplib';\n *\n * // Create OTP instance with TOTP strategy (default)\n * const otp = new OTP({ strategy: 'totp' });\n *\n * // Generate and verify\n * const secret = otp.generateSecret();\n * const token = await otp.generate({ secret });\n * const result = await otp.verify({ secret, token });\n * ```\n *\n * @example With HOTP strategy\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'hotp' });\n * const token = await otp.generate({ secret: 'ABC123', counter: 0 });\n * ```\n *\n * @example Generating otpauth:// URI for authenticator apps\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'totp' });\n * const uri = otp.generateURI({\n * issuer: 'MyApp',\n * label: 'user@example.com',\n * secret: 'ABC123',\n * });\n * ```\n */\nexport class OTP {\n private readonly strategy: OTPStrategy;\n private readonly crypto: CryptoPlugin;\n private readonly base32: Base32Plugin;\n\n constructor(options: OTPClassOptions = {}) {\n const { strategy = \"totp\", crypto = defaultCrypto, base32 = defaultBase32 } = options;\n\n this.strategy = strategy;\n this.crypto = crypto;\n this.base32 = base32;\n }\n\n /**\n * Get the current strategy\n */\n getStrategy(): OTPStrategy {\n return this.strategy;\n }\n\n /**\n * Generate a random secret key\n *\n * @param length - Number of random bytes (default: 20)\n * @returns Base32-encoded secret key\n */\n generateSecret(length: number = 20): string {\n return generateSecretCore({ crypto: this.crypto, base32: this.base32, length });\n }\n\n /**\n * Generate an OTP token based on the configured strategy\n *\n * @param options - Generation options\n * @returns OTP code\n */\n async generate(options: OTPGenerateOptions): Promise<string> {\n return functionalGenerate({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n });\n }\n\n /**\n * Generate an OTP token based on the configured strategy synchronously\n *\n * @param options - Generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n generateSync(options: OTPGenerateOptions): string {\n return functionalGenerateSync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n */\n async verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n return functionalVerify({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy synchronously\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n verifySync(options: OTPVerifyOptions): VerifyResult {\n return functionalVerifySync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n });\n }\n\n /**\n * Generate an otpauth:// URI for QR code generation\n *\n * Supports both TOTP and HOTP strategies.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n */\n generateURI(options: OTPURIGenerateOptions): string {\n return functionalGenerateURI({\n ...options,\n strategy: this.strategy,\n });\n }\n}\n","/**\n * Default plugin instances\n *\n * Shared across functional and class APIs to ensure singleton behavior\n * and reduce memory overhead.\n */\nimport { ScureBase32Plugin } from \"@otplib/plugin-base32-scure\";\nimport { NobleCryptoPlugin } from \"@otplib/plugin-crypto-noble\";\n\nimport type {\n OTPGenerateOptions,\n OTPVerifyOptions,\n OTPGenerateOptionsWithDefaults,\n OTPVerifyOptionsWithDefaults,\n} from \"./types\";\n\n/**\n * Default crypto plugin instance (Noble Hashes)\n *\n * This plugin provides cross-platform cryptographic operations\n * using the @noble/hashes library.\n */\nexport const defaultCrypto = Object.freeze(new NobleCryptoPlugin());\n\n/**\n * Default Base32 plugin instance (@scure/base)\n *\n * This plugin provides Base32 encoding/decoding operations\n * using the @scure/base library.\n */\nexport const defaultBase32 = Object.freeze(new ScureBase32Plugin());\n\nexport function normalizeGenerateOptions(\n options: OTPGenerateOptions,\n): OTPGenerateOptionsWithDefaults {\n return {\n secret: options.secret,\n strategy: options.strategy ?? \"totp\",\n crypto: options.crypto ?? defaultCrypto,\n base32: options.base32 ?? defaultBase32,\n algorithm: options.algorithm ?? \"sha1\",\n digits: options.digits ?? 6,\n period: options.period ?? 30,\n epoch: options.epoch ?? Math.floor(Date.now() / 1000),\n t0: options.t0 ?? 0,\n counter: options.counter,\n };\n}\n\nexport function normalizeVerifyOptions(options: OTPVerifyOptions): OTPVerifyOptionsWithDefaults {\n return {\n ...normalizeGenerateOptions(options),\n token: options.token,\n epochTolerance: options.epochTolerance ?? 0,\n counterTolerance: options.counterTolerance ?? 0,\n };\n}\n","import { generateSecret as generateSecretCore, ConfigurationError } from \"@otplib/core\";\nimport {\n generate as generateHOTP,\n generateSync as generateHOTPSync,\n verify as verifyHOTP,\n verifySync as verifyHOTPSync,\n} from \"@otplib/hotp\";\nimport {\n generate as generateTOTP,\n generateSync as generateTOTPSync,\n verify as verifyTOTP,\n verifySync as verifyTOTPSync,\n} from \"@otplib/totp\";\nimport { generateTOTP as generateTOTPURI, generateHOTP as generateHOTURI } from \"@otplib/uri\";\n\nimport {\n defaultCrypto,\n defaultBase32,\n normalizeGenerateOptions,\n normalizeVerifyOptions,\n} from \"./defaults\";\n\nimport type { OTPGenerateOptions, OTPVerifyOptions, OTPStrategy, StrategyHandlers } from \"./types\";\nimport type { CryptoPlugin, Base32Plugin, Digits, HashAlgorithm } from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\nexport type { OTPStrategy };\n\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\nfunction executeByStrategy<T>(\n strategy: OTPStrategy,\n counter: number | undefined,\n handlers: StrategyHandlers<T>,\n): T {\n if (strategy === \"totp\") {\n return handlers.totp();\n }\n if (strategy === \"hotp\") {\n if (counter === undefined) {\n throw new ConfigurationError(\n \"Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }\",\n );\n }\n return handlers.hotp(counter);\n }\n throw new ConfigurationError(\n `Unknown OTP strategy: ${strategy}. Valid strategies are 'totp' or 'hotp'.`,\n );\n}\n\n/**\n * Generate a random secret key for use with OTP\n *\n * The secret is encoded in Base32 format for compatibility with\n * Google Authenticator and other authenticator apps.\n *\n * @param options - Secret generation options\n * @returns Base32-encoded secret key\n *\n * @example\n * ```ts\n * import { generateSecret } from 'otplib';\n *\n * const secret = generateSecret();\n * // Returns: 'JBSWY3DPEHPK3PXP'\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generateSecret, NodeCryptoPlugin } from 'otplib';\n *\n * const secret = generateSecret({\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport function generateSecret(options?: {\n /**\n * Number of random bytes to generate (default: 20)\n * 20 bytes = 160 bits, which provides a good security margin\n */\n length?: number;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n}): string {\n const { crypto = defaultCrypto, base32 = defaultBase32, length = 20 } = options || {};\n\n return generateSecretCore({ crypto, base32, length });\n}\n\n/**\n * Generate an otpauth:// URI for QR code generation\n *\n * This URI can be used to generate a QR code that can be scanned\n * by Google Authenticator and other authenticator apps.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n *\n * @example TOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: 'otpauth://totp/ACME%20Co:john%40example.com?secret=...'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * strategy: 'hotp',\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * counter: 5,\n * });\n * // Returns: 'otpauth://hotp/ACME%20Co:john%40example.com?secret=...&counter=5'\n * ```\n */\nexport function generateURI(options: {\n /**\n * OTP strategy to use (default: 'totp')\n */\n strategy?: OTPStrategy;\n issuer: string;\n label: string;\n secret: string;\n algorithm?: HashAlgorithm;\n digits?: Digits;\n period?: number;\n counter?: number;\n}): string {\n const {\n strategy = \"totp\",\n issuer,\n label,\n secret,\n algorithm = \"sha1\",\n digits = 6,\n period = 30,\n counter,\n } = options;\n\n return executeByStrategy(strategy, counter, {\n totp: () => generateTOTPURI({ issuer, label, secret, algorithm, digits, period }),\n hotp: (counter) => generateHOTURI({ issuer, label, secret, algorithm, digits, counter }),\n });\n}\n\n/**\n * Generate an OTP code\n *\n * Generates a one-time password based on the specified strategy.\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n *\n * @param options - OTP generation options\n * @returns OTP code\n *\n * @example TOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: '123456'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generate, NodeCryptoPlugin } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function generate(options: OTPGenerateOptions): Promise<string> {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n }),\n hotp: (counter) =>\n generateHOTP({\n ...commonOptions,\n counter,\n }),\n });\n}\n\n/**\n * Generate an OTP code synchronously\n *\n * This is the synchronous version of {@link generate}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { generateSync } from 'otplib';\n *\n * const token = generateSync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * ```\n */\nexport function generateSync(options: OTPGenerateOptions): string {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n }),\n hotp: (counter) =>\n generateHOTPSync({\n ...commonOptions,\n counter,\n }),\n });\n}\n\n/**\n * Verify an OTP code\n *\n * Verifies a provided OTP code against the expected value based on the strategy.\n * - 'totp': Time-based OTP (default, Google Authenticator compatible)\n * - 'hotp': HMAC-based OTP\n *\n * Uses constant-time comparison to prevent timing attacks.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n *\n * @example TOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * // Returns: { valid: true, delta: 0 }\n * ```\n *\n * @example HOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With epochTolerance for TOTP\n * ```ts\n * import { verify, NodeCryptoPlugin } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * epochTolerance: 30,\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n }),\n hotp: (counter) =>\n verifyHOTP({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n }),\n });\n}\n\n/**\n * Verify an OTP code synchronously\n *\n * This is the synchronous version of {@link verify}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { verifySync } from 'otplib';\n *\n * const result = verifySync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * ```\n */\nexport function verifySync(options: OTPVerifyOptions): VerifyResult {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n }),\n hotp: (counter) =>\n verifyHOTPSync({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n }),\n });\n}\n"],"mappings":"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","names":["class_exports","__export","OTP","__toCommonJS","import_core","import_plugin_base32_scure","import_plugin_crypto_noble","defaultCrypto","defaultBase32","normalizeGenerateOptions","options","normalizeVerifyOptions","import_core","import_hotp","import_totp","import_uri","executeByStrategy","strategy","counter","handlers","generateURI","options","strategy","issuer","label","secret","algorithm","digits","period","counter","executeByStrategy","generateTOTPURI","generateHOTURI","generate","opts","normalizeGenerateOptions","crypto","base32","commonOptions","generateTOTP","generateHOTP","generateSync","generateTOTPSync","generateHOTPSync","verify","normalizeVerifyOptions","token","verifyTOTP","verifyHOTP","verifySync","verifyTOTPSync","verifyHOTPSync","OTP","options","strategy","crypto","defaultCrypto","base32","defaultBase32","length","generateSecretCore","generate","generateSync","verify","verifySync","generateURI"]}
1
+ {"version":3,"sources":["../src/class.ts","../src/defaults.ts","../src/functional.ts"],"sourcesContent":["/**\n * OTP Wrapper Class\n *\n * A unified class that dynamically handles TOTP and HOTP strategies.\n */\n\nimport { createGuardrails, generateSecret as generateSecretCore } from \"@otplib/core\";\n\nimport { defaultCrypto, defaultBase32 } from \"./defaults.js\";\nimport {\n generate as functionalGenerate,\n generateSync as functionalGenerateSync,\n verify as functionalVerify,\n verifySync as functionalVerifySync,\n generateURI as functionalGenerateURI,\n} from \"./functional.js\";\n\nimport type { OTPStrategy } from \"./functional.js\";\nimport type {\n CryptoPlugin,\n Digits,\n HashAlgorithm,\n Base32Plugin,\n OTPGuardrails,\n} from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\n/**\n * Combined verify result that works for both TOTP and HOTP\n */\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\n/**\n * Options for the OTP class\n */\nexport type OTPClassOptions = {\n /**\n * OTP strategy to use\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n */\n strategy?: OTPStrategy;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n};\n\n/**\n * Options for generating a token with the OTP class\n */\nexport type OTPGenerateOptions = {\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string | Uint8Array;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n};\n\n/**\n * Options for verifying a token with the OTP class\n */\nexport type OTPVerifyOptions = {\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string | Uint8Array;\n\n /**\n * OTP code to verify\n */\n token: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n\n /**\n * Time tolerance in seconds for TOTP verification (default: 0)\n * - Number: symmetric tolerance (same for past and future)\n * - Tuple [past, future]: asymmetric tolerance\n * Use [5, 0] for RFC-compliant past-only verification.\n */\n epochTolerance?: number | [number, number];\n\n /**\n * Counter tolerance for HOTP verification (default: 0)\n * - Number: creates look-ahead only tolerance [0, n]\n * - Tuple [past, future]: explicit window control\n */\n counterTolerance?: number | [number, number];\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n};\n\n/**\n * Options for generating URI with the OTP class\n */\nexport type OTPURIGenerateOptions = {\n /**\n * Issuer name (e.g., 'ACME Co')\n */\n issuer: string;\n\n /**\n * Label/Account name (e.g., 'john@example.com')\n */\n label: string;\n\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value (default: 0)\n * Used by HOTP strategy\n */\n counter?: number;\n};\n\n/**\n * OTP Class\n *\n * A wrapper class that dynamically handles TOTP and HOTP strategies.\n *\n * @example\n * ```ts\n * import { OTP } from 'otplib';\n *\n * // Create OTP instance with TOTP strategy (default)\n * const otp = new OTP({ strategy: 'totp' });\n *\n * // Generate and verify\n * const secret = otp.generateSecret();\n * const token = await otp.generate({ secret });\n * const result = await otp.verify({ secret, token });\n * ```\n *\n * @example With HOTP strategy\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'hotp' });\n * const token = await otp.generate({ secret: 'ABC123', counter: 0 });\n * ```\n *\n * @example Generating otpauth:// URI for authenticator apps\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'totp' });\n * const uri = otp.generateURI({\n * issuer: 'MyApp',\n * label: 'user@example.com',\n * secret: 'ABC123',\n * });\n * ```\n */\nexport class OTP {\n private readonly strategy: OTPStrategy;\n private readonly crypto: CryptoPlugin;\n private readonly base32: Base32Plugin;\n private readonly guardrails: OTPGuardrails;\n\n constructor(options: OTPClassOptions = {}) {\n const {\n strategy = \"totp\",\n crypto = defaultCrypto,\n base32 = defaultBase32,\n guardrails,\n } = options;\n\n this.strategy = strategy;\n this.crypto = crypto;\n this.base32 = base32;\n this.guardrails = createGuardrails(guardrails);\n }\n\n /**\n * Get the current strategy\n */\n getStrategy(): OTPStrategy {\n return this.strategy;\n }\n\n /**\n * Generate a random secret key\n *\n * @param length - Number of random bytes (default: 20)\n * @returns Base32-encoded secret key\n */\n generateSecret(length: number = 20): string {\n return generateSecretCore({ crypto: this.crypto, base32: this.base32, length });\n }\n\n /**\n * Generate an OTP token based on the configured strategy\n *\n * @param options - Generation options\n * @returns OTP code\n */\n async generate(options: OTPGenerateOptions): Promise<string> {\n return functionalGenerate({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Generate an OTP token based on the configured strategy synchronously\n *\n * @param options - Generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n generateSync(options: OTPGenerateOptions): string {\n return functionalGenerateSync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n */\n async verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n return functionalVerify({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy synchronously\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n verifySync(options: OTPVerifyOptions): VerifyResult {\n return functionalVerifySync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Generate an otpauth:// URI for QR code generation\n *\n * Supports both TOTP and HOTP strategies.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n */\n generateURI(options: OTPURIGenerateOptions): string {\n return functionalGenerateURI({\n ...options,\n strategy: this.strategy,\n });\n }\n}\n","/**\n * Default plugin instances\n *\n * Shared across functional and class APIs to ensure singleton behavior\n * and reduce memory overhead.\n */\nimport { createGuardrails } from \"@otplib/core\";\nimport { ScureBase32Plugin } from \"@otplib/plugin-base32-scure\";\nimport { NobleCryptoPlugin } from \"@otplib/plugin-crypto-noble\";\n\nimport type {\n OTPGenerateOptions,\n OTPVerifyOptions,\n OTPGenerateOptionsWithDefaults,\n OTPVerifyOptionsWithDefaults,\n} from \"./types.js\";\n\n/**\n * Default crypto plugin instance (Noble Hashes)\n *\n * This plugin provides cross-platform cryptographic operations\n * using the @noble/hashes library.\n */\nexport const defaultCrypto = Object.freeze(new NobleCryptoPlugin());\n\n/**\n * Default Base32 plugin instance (@scure/base)\n *\n * This plugin provides Base32 encoding/decoding operations\n * using the @scure/base library.\n */\nexport const defaultBase32 = Object.freeze(new ScureBase32Plugin());\n\nexport function normalizeGenerateOptions(\n options: OTPGenerateOptions,\n): OTPGenerateOptionsWithDefaults {\n return {\n secret: options.secret,\n strategy: options.strategy ?? \"totp\",\n crypto: options.crypto ?? defaultCrypto,\n base32: options.base32 ?? defaultBase32,\n algorithm: options.algorithm ?? \"sha1\",\n digits: options.digits ?? 6,\n period: options.period ?? 30,\n epoch: options.epoch ?? Math.floor(Date.now() / 1000),\n t0: options.t0 ?? 0,\n counter: options.counter,\n guardrails: options.guardrails ?? createGuardrails(),\n };\n}\n\nexport function normalizeVerifyOptions(options: OTPVerifyOptions): OTPVerifyOptionsWithDefaults {\n return {\n ...normalizeGenerateOptions(options),\n token: options.token,\n epochTolerance: options.epochTolerance ?? 0,\n counterTolerance: options.counterTolerance ?? 0,\n };\n}\n","import { generateSecret as generateSecretCore, ConfigurationError } from \"@otplib/core\";\nimport {\n generate as generateHOTP,\n generateSync as generateHOTPSync,\n verify as verifyHOTP,\n verifySync as verifyHOTPSync,\n} from \"@otplib/hotp\";\nimport {\n generate as generateTOTP,\n generateSync as generateTOTPSync,\n verify as verifyTOTP,\n verifySync as verifyTOTPSync,\n} from \"@otplib/totp\";\nimport { generateTOTP as generateTOTPURI, generateHOTP as generateHOTURI } from \"@otplib/uri\";\n\nimport {\n defaultCrypto,\n defaultBase32,\n normalizeGenerateOptions,\n normalizeVerifyOptions,\n} from \"./defaults.js\";\n\nimport type {\n OTPGenerateOptions,\n OTPVerifyOptions,\n OTPStrategy,\n StrategyHandlers,\n} from \"./types.js\";\nimport type { CryptoPlugin, Base32Plugin, Digits, HashAlgorithm } from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\nexport type { OTPStrategy };\n\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\nfunction executeByStrategy<T>(\n strategy: OTPStrategy,\n counter: number | undefined,\n handlers: StrategyHandlers<T>,\n): T {\n if (strategy === \"totp\") {\n return handlers.totp();\n }\n if (strategy === \"hotp\") {\n if (counter === undefined) {\n throw new ConfigurationError(\n \"Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }\",\n );\n }\n return handlers.hotp(counter);\n }\n throw new ConfigurationError(\n `Unknown OTP strategy: ${strategy}. Valid strategies are 'totp' or 'hotp'.`,\n );\n}\n\n/**\n * Generate a random secret key for use with OTP\n *\n * The secret is encoded in Base32 format for compatibility with\n * Google Authenticator and other authenticator apps.\n *\n * @param options - Secret generation options\n * @returns Base32-encoded secret key\n *\n * @example\n * ```ts\n * import { generateSecret } from 'otplib';\n *\n * const secret = generateSecret();\n * // Returns: 'JBSWY3DPEHPK3PXP'\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generateSecret, NodeCryptoPlugin } from 'otplib';\n *\n * const secret = generateSecret({\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport function generateSecret(options?: {\n /**\n * Number of random bytes to generate (default: 20)\n * 20 bytes = 160 bits, which provides a good security margin\n */\n length?: number;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n}): string {\n const { crypto = defaultCrypto, base32 = defaultBase32, length = 20 } = options || {};\n\n return generateSecretCore({ crypto, base32, length });\n}\n\n/**\n * Generate an otpauth:// URI for QR code generation\n *\n * This URI can be used to generate a QR code that can be scanned\n * by Google Authenticator and other authenticator apps.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n *\n * @example TOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: 'otpauth://totp/ACME%20Co:john%40example.com?secret=...'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * strategy: 'hotp',\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * counter: 5,\n * });\n * // Returns: 'otpauth://hotp/ACME%20Co:john%40example.com?secret=...&counter=5'\n * ```\n */\nexport function generateURI(options: {\n /**\n * OTP strategy to use (default: 'totp')\n */\n strategy?: OTPStrategy;\n issuer: string;\n label: string;\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string;\n algorithm?: HashAlgorithm;\n digits?: Digits;\n period?: number;\n counter?: number;\n}): string {\n const {\n strategy = \"totp\",\n issuer,\n label,\n secret,\n algorithm = \"sha1\",\n digits = 6,\n period = 30,\n counter,\n } = options;\n\n return executeByStrategy(strategy, counter, {\n totp: () => generateTOTPURI({ issuer, label, secret, algorithm, digits, period }),\n hotp: (counter) => generateHOTURI({ issuer, label, secret, algorithm, digits, counter }),\n });\n}\n\n/**\n * Generate an OTP code\n *\n * Generates a one-time password based on the specified strategy.\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n *\n * @param options - OTP generation options\n * @returns OTP code\n *\n * @example TOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: '123456'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generate, NodeCryptoPlugin } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function generate(options: OTPGenerateOptions): Promise<string> {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n generateHOTP({\n ...commonOptions,\n counter,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Generate an OTP code synchronously\n *\n * This is the synchronous version of {@link generate}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { generateSync } from 'otplib';\n *\n * const token = generateSync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * ```\n */\nexport function generateSync(options: OTPGenerateOptions): string {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n generateHOTPSync({\n ...commonOptions,\n counter,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Verify an OTP code\n *\n * Verifies a provided OTP code against the expected value based on the strategy.\n * - 'totp': Time-based OTP (default, Google Authenticator compatible)\n * - 'hotp': HMAC-based OTP\n *\n * Uses constant-time comparison to prevent timing attacks.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n *\n * @example TOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * // Returns: { valid: true, delta: 0 }\n * ```\n *\n * @example HOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With epochTolerance for TOTP\n * ```ts\n * import { verify, NodeCryptoPlugin } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * epochTolerance: 30,\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n verifyHOTP({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Verify an OTP code synchronously\n *\n * This is the synchronous version of {@link verify}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { verifySync } from 'otplib';\n *\n * const result = verifySync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * ```\n */\nexport function verifySync(options: OTPVerifyOptions): VerifyResult {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n verifyHOTPSync({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n guardrails: opts.guardrails,\n }),\n });\n}\n"],"mappings":"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","names":["class_exports","__export","OTP","__toCommonJS","import_core","import_core","import_plugin_base32_scure","import_plugin_crypto_noble","defaultCrypto","defaultBase32","normalizeGenerateOptions","options","normalizeVerifyOptions","import_core","import_hotp","import_totp","import_uri","executeByStrategy","strategy","counter","handlers","generateURI","options","strategy","issuer","label","secret","algorithm","digits","period","counter","executeByStrategy","generateTOTPURI","generateHOTURI","generate","opts","normalizeGenerateOptions","crypto","base32","commonOptions","generateTOTP","generateHOTP","generateSync","generateTOTPSync","generateHOTPSync","verify","normalizeVerifyOptions","token","verifyTOTP","verifyHOTP","verifySync","verifyTOTPSync","verifyHOTPSync","OTP","options","strategy","crypto","defaultCrypto","base32","defaultBase32","guardrails","length","generateSecretCore","generate","generateSync","verify","verifySync","generateURI"]}
package/dist/class.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { c as OTPStrategy } from './types-D1FZb7MW.cjs';
2
- import { CryptoPlugin, Base32Plugin, HashAlgorithm, Digits } from '@otplib/core';
1
+ import { c as OTPStrategy } from './types-Bap9LCID.cjs';
2
+ import { CryptoPlugin, Base32Plugin, OTPGuardrails, HashAlgorithm, Digits } from '@otplib/core';
3
3
  import { VerifyResult as VerifyResult$2 } from '@otplib/hotp';
4
4
  import { VerifyResult as VerifyResult$1 } from '@otplib/totp';
5
5
 
@@ -31,6 +31,10 @@ type OTPClassOptions = {
31
31
  * Base32 plugin to use (default: ScureBase32Plugin)
32
32
  */
33
33
  base32?: Base32Plugin;
34
+ /**
35
+ * Validation guardrails
36
+ */
37
+ guardrails?: OTPGuardrails;
34
38
  };
35
39
  /**
36
40
  * Options for generating a token with the OTP class
@@ -38,8 +42,11 @@ type OTPClassOptions = {
38
42
  type OTPGenerateOptions = {
39
43
  /**
40
44
  * Base32-encoded secret key
45
+ *
46
+ * **Note**: By default, strings are assumed to be Base32 encoded.
47
+ * If you have a raw string/passphrase, you must convert it to Uint8Array first.
41
48
  */
42
- secret: string;
49
+ secret: string | Uint8Array;
43
50
  /**
44
51
  * Hash algorithm (default: 'sha1')
45
52
  */
@@ -68,6 +75,10 @@ type OTPGenerateOptions = {
68
75
  * Used by HOTP strategy (required)
69
76
  */
70
77
  counter?: number;
78
+ /**
79
+ * Validation guardrails
80
+ */
81
+ guardrails?: OTPGuardrails;
71
82
  };
72
83
  /**
73
84
  * Options for verifying a token with the OTP class
@@ -75,8 +86,11 @@ type OTPGenerateOptions = {
75
86
  type OTPVerifyOptions = {
76
87
  /**
77
88
  * Base32-encoded secret key
89
+ *
90
+ * **Note**: By default, strings are assumed to be Base32 encoded.
91
+ * If you have a raw string/passphrase, you must convert it to Uint8Array first.
78
92
  */
79
- secret: string;
93
+ secret: string | Uint8Array;
80
94
  /**
81
95
  * OTP code to verify
82
96
  */
@@ -118,10 +132,14 @@ type OTPVerifyOptions = {
118
132
  epochTolerance?: number | [number, number];
119
133
  /**
120
134
  * Counter tolerance for HOTP verification (default: 0)
121
- * - Number: symmetric look-ahead window
122
- * - Array: asymmetric window
135
+ * - Number: creates look-ahead only tolerance [0, n]
136
+ * - Tuple [past, future]: explicit window control
123
137
  */
124
- counterTolerance?: number | number[];
138
+ counterTolerance?: number | [number, number];
139
+ /**
140
+ * Validation guardrails
141
+ */
142
+ guardrails?: OTPGuardrails;
125
143
  };
126
144
  /**
127
145
  * Options for generating URI with the OTP class
@@ -137,6 +155,9 @@ type OTPURIGenerateOptions = {
137
155
  label: string;
138
156
  /**
139
157
  * Base32-encoded secret key
158
+ *
159
+ * **Note**: By default, strings are assumed to be Base32 encoded.
160
+ * If you have a raw string/passphrase, you must convert it to Uint8Array first.
140
161
  */
141
162
  secret: string;
142
163
  /**
@@ -200,6 +221,7 @@ declare class OTP {
200
221
  private readonly strategy;
201
222
  private readonly crypto;
202
223
  private readonly base32;
224
+ private readonly guardrails;
203
225
  constructor(options?: OTPClassOptions);
204
226
  /**
205
227
  * Get the current strategy
package/dist/class.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { c as OTPStrategy } from './types-D1FZb7MW.js';
2
- import { CryptoPlugin, Base32Plugin, HashAlgorithm, Digits } from '@otplib/core';
1
+ import { c as OTPStrategy } from './types-Bap9LCID.js';
2
+ import { CryptoPlugin, Base32Plugin, OTPGuardrails, HashAlgorithm, Digits } from '@otplib/core';
3
3
  import { VerifyResult as VerifyResult$2 } from '@otplib/hotp';
4
4
  import { VerifyResult as VerifyResult$1 } from '@otplib/totp';
5
5
 
@@ -31,6 +31,10 @@ type OTPClassOptions = {
31
31
  * Base32 plugin to use (default: ScureBase32Plugin)
32
32
  */
33
33
  base32?: Base32Plugin;
34
+ /**
35
+ * Validation guardrails
36
+ */
37
+ guardrails?: OTPGuardrails;
34
38
  };
35
39
  /**
36
40
  * Options for generating a token with the OTP class
@@ -38,8 +42,11 @@ type OTPClassOptions = {
38
42
  type OTPGenerateOptions = {
39
43
  /**
40
44
  * Base32-encoded secret key
45
+ *
46
+ * **Note**: By default, strings are assumed to be Base32 encoded.
47
+ * If you have a raw string/passphrase, you must convert it to Uint8Array first.
41
48
  */
42
- secret: string;
49
+ secret: string | Uint8Array;
43
50
  /**
44
51
  * Hash algorithm (default: 'sha1')
45
52
  */
@@ -68,6 +75,10 @@ type OTPGenerateOptions = {
68
75
  * Used by HOTP strategy (required)
69
76
  */
70
77
  counter?: number;
78
+ /**
79
+ * Validation guardrails
80
+ */
81
+ guardrails?: OTPGuardrails;
71
82
  };
72
83
  /**
73
84
  * Options for verifying a token with the OTP class
@@ -75,8 +86,11 @@ type OTPGenerateOptions = {
75
86
  type OTPVerifyOptions = {
76
87
  /**
77
88
  * Base32-encoded secret key
89
+ *
90
+ * **Note**: By default, strings are assumed to be Base32 encoded.
91
+ * If you have a raw string/passphrase, you must convert it to Uint8Array first.
78
92
  */
79
- secret: string;
93
+ secret: string | Uint8Array;
80
94
  /**
81
95
  * OTP code to verify
82
96
  */
@@ -118,10 +132,14 @@ type OTPVerifyOptions = {
118
132
  epochTolerance?: number | [number, number];
119
133
  /**
120
134
  * Counter tolerance for HOTP verification (default: 0)
121
- * - Number: symmetric look-ahead window
122
- * - Array: asymmetric window
135
+ * - Number: creates look-ahead only tolerance [0, n]
136
+ * - Tuple [past, future]: explicit window control
123
137
  */
124
- counterTolerance?: number | number[];
138
+ counterTolerance?: number | [number, number];
139
+ /**
140
+ * Validation guardrails
141
+ */
142
+ guardrails?: OTPGuardrails;
125
143
  };
126
144
  /**
127
145
  * Options for generating URI with the OTP class
@@ -137,6 +155,9 @@ type OTPURIGenerateOptions = {
137
155
  label: string;
138
156
  /**
139
157
  * Base32-encoded secret key
158
+ *
159
+ * **Note**: By default, strings are assumed to be Base32 encoded.
160
+ * If you have a raw string/passphrase, you must convert it to Uint8Array first.
140
161
  */
141
162
  secret: string;
142
163
  /**
@@ -200,6 +221,7 @@ declare class OTP {
200
221
  private readonly strategy;
201
222
  private readonly crypto;
202
223
  private readonly base32;
224
+ private readonly guardrails;
203
225
  constructor(options?: OTPClassOptions);
204
226
  /**
205
227
  * Get the current strategy
package/dist/class.js CHANGED
@@ -1,2 +1,2 @@
1
- import{generateSecret as I}from"@otplib/core";import{ScureBase32Plugin as S}from"@otplib/plugin-base32-scure";import{NobleCryptoPlugin as V}from"@otplib/plugin-crypto-noble";var g=Object.freeze(new V),u=Object.freeze(new S);function l(t){return{secret:t.secret,strategy:t.strategy??"totp",crypto:t.crypto??g,base32:t.base32??u,algorithm:t.algorithm??"sha1",digits:t.digits??6,period:t.period??30,epoch:t.epoch??Math.floor(Date.now()/1e3),t0:t.t0??0,counter:t.counter}}function f(t){return{...l(t),token:t.token,epochTolerance:t.epochTolerance??0,counterTolerance:t.counterTolerance??0}}import{generateSecret as j,ConfigurationError as m}from"@otplib/core";import{generate as R,generateSync as x,verify as H,verifySync as v}from"@otplib/hotp";import{generate as G,generateSync as C,verify as D,verifySync as B}from"@otplib/totp";import{generateTOTP as U,generateHOTP as w}from"@otplib/uri";function y(t,e,r){if(t==="totp")return r.totp();if(t==="hotp"){if(e===void 0)throw new m("Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }");return r.hotp(e)}throw new m(`Unknown OTP strategy: ${t}. Valid strategies are 'totp' or 'hotp'.`)}function O(t){let{strategy:e="totp",issuer:r,label:o,secret:n,algorithm:a="sha1",digits:p=6,period:i=30,counter:s}=t;return y(e,s,{totp:()=>U({issuer:r,label:o,secret:n,algorithm:a,digits:p,period:i}),hotp:c=>w({issuer:r,label:o,secret:n,algorithm:a,digits:p,counter:c})})}async function h(t){let e=l(t),{secret:r,crypto:o,base32:n,algorithm:a,digits:p}=e,i={secret:r,crypto:o,base32:n,algorithm:a,digits:p};return y(e.strategy,e.counter,{totp:()=>G({...i,period:e.period,epoch:e.epoch,t0:e.t0}),hotp:s=>R({...i,counter:s})})}function T(t){let e=l(t),{secret:r,crypto:o,base32:n,algorithm:a,digits:p}=e,i={secret:r,crypto:o,base32:n,algorithm:a,digits:p};return y(e.strategy,e.counter,{totp:()=>C({...i,period:e.period,epoch:e.epoch,t0:e.t0}),hotp:s=>x({...i,counter:s})})}async function P(t){let e=f(t),{secret:r,token:o,crypto:n,base32:a,algorithm:p,digits:i}=e,s={secret:r,token:o,crypto:n,base32:a,algorithm:p,digits:i};return y(e.strategy,e.counter,{totp:()=>D({...s,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance}),hotp:c=>H({...s,counter:c,counterTolerance:e.counterTolerance})})}function b(t){let e=f(t),{secret:r,token:o,crypto:n,base32:a,algorithm:p,digits:i}=e,s={secret:r,token:o,crypto:n,base32:a,algorithm:p,digits:i};return y(e.strategy,e.counter,{totp:()=>B({...s,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance}),hotp:c=>v({...s,counter:c,counterTolerance:e.counterTolerance})})}var d=class{strategy;crypto;base32;constructor(e={}){let{strategy:r="totp",crypto:o=g,base32:n=u}=e;this.strategy=r,this.crypto=o,this.base32=n}getStrategy(){return this.strategy}generateSecret(e=20){return I({crypto:this.crypto,base32:this.base32,length:e})}async generate(e){return h({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32})}generateSync(e){return T({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32})}async verify(e){return P({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32})}verifySync(e){return b({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32})}generateURI(e){return O({...e,strategy:this.strategy})}};export{d as OTP};
1
+ import{createGuardrails as I,generateSecret as k}from"@otplib/core";import{createGuardrails as S}from"@otplib/core";import{ScureBase32Plugin as V}from"@otplib/plugin-base32-scure";import{NobleCryptoPlugin as R}from"@otplib/plugin-crypto-noble";var y=Object.freeze(new R),c=Object.freeze(new V);function l(r){return{secret:r.secret,strategy:r.strategy??"totp",crypto:r.crypto??y,base32:r.base32??c,algorithm:r.algorithm??"sha1",digits:r.digits??6,period:r.period??30,epoch:r.epoch??Math.floor(Date.now()/1e3),t0:r.t0??0,counter:r.counter,guardrails:r.guardrails??S()}}function f(r){return{...l(r),token:r.token,epochTolerance:r.epochTolerance??0,counterTolerance:r.counterTolerance??0}}import{generateSecret as M,ConfigurationError as m}from"@otplib/core";import{generate as G,generateSync as x,verify as H,verifySync as v}from"@otplib/hotp";import{generate as C,generateSync as D,verify as U,verifySync as B}from"@otplib/totp";import{generateTOTP as w,generateHOTP as A}from"@otplib/uri";function u(r,e,t){if(r==="totp")return t.totp();if(r==="hotp"){if(e===void 0)throw new m("Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }");return t.hotp(e)}throw new m(`Unknown OTP strategy: ${r}. Valid strategies are 'totp' or 'hotp'.`)}function O(r){let{strategy:e="totp",issuer:t,label:a,secret:i,algorithm:s="sha1",digits:p=6,period:o=30,counter:n}=r;return u(e,n,{totp:()=>w({issuer:t,label:a,secret:i,algorithm:s,digits:p,period:o}),hotp:g=>A({issuer:t,label:a,secret:i,algorithm:s,digits:p,counter:g})})}async function h(r){let e=l(r),{secret:t,crypto:a,base32:i,algorithm:s,digits:p}=e,o={secret:t,crypto:a,base32:i,algorithm:s,digits:p};return u(e.strategy,e.counter,{totp:()=>C({...o,period:e.period,epoch:e.epoch,t0:e.t0,guardrails:e.guardrails}),hotp:n=>G({...o,counter:n,guardrails:e.guardrails})})}function d(r){let e=l(r),{secret:t,crypto:a,base32:i,algorithm:s,digits:p}=e,o={secret:t,crypto:a,base32:i,algorithm:s,digits:p};return u(e.strategy,e.counter,{totp:()=>D({...o,period:e.period,epoch:e.epoch,t0:e.t0,guardrails:e.guardrails}),hotp:n=>x({...o,counter:n,guardrails:e.guardrails})})}async function T(r){let e=f(r),{secret:t,token:a,crypto:i,base32:s,algorithm:p,digits:o}=e,n={secret:t,token:a,crypto:i,base32:s,algorithm:p,digits:o};return u(e.strategy,e.counter,{totp:()=>U({...n,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance,guardrails:e.guardrails}),hotp:g=>H({...n,counter:g,counterTolerance:e.counterTolerance,guardrails:e.guardrails})})}function P(r){let e=f(r),{secret:t,token:a,crypto:i,base32:s,algorithm:p,digits:o}=e,n={secret:t,token:a,crypto:i,base32:s,algorithm:p,digits:o};return u(e.strategy,e.counter,{totp:()=>B({...n,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance,guardrails:e.guardrails}),hotp:g=>v({...n,counter:g,counterTolerance:e.counterTolerance,guardrails:e.guardrails})})}var b=class{strategy;crypto;base32;guardrails;constructor(e={}){let{strategy:t="totp",crypto:a=y,base32:i=c,guardrails:s}=e;this.strategy=t,this.crypto=a,this.base32=i,this.guardrails=I(s)}getStrategy(){return this.strategy}generateSecret(e=20){return k({crypto:this.crypto,base32:this.base32,length:e})}async generate(e){return h({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}generateSync(e){return d({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}async verify(e){return T({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}verifySync(e){return P({...e,strategy:this.strategy,crypto:this.crypto,base32:this.base32,guardrails:e.guardrails??this.guardrails})}generateURI(e){return O({...e,strategy:this.strategy})}};export{b as OTP};
2
2
  //# sourceMappingURL=class.js.map
package/dist/class.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/class.ts","../src/defaults.ts","../src/functional.ts"],"sourcesContent":["/**\n * OTP Wrapper Class\n *\n * A unified class that dynamically handles TOTP and HOTP strategies.\n */\n\nimport { generateSecret as generateSecretCore } from \"@otplib/core\";\n\nimport { defaultCrypto, defaultBase32 } from \"./defaults\";\nimport {\n generate as functionalGenerate,\n generateSync as functionalGenerateSync,\n verify as functionalVerify,\n verifySync as functionalVerifySync,\n generateURI as functionalGenerateURI,\n} from \"./functional\";\n\nimport type { OTPStrategy } from \"./functional\";\nimport type { CryptoPlugin, Digits, HashAlgorithm, Base32Plugin } from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\n/**\n * Combined verify result that works for both TOTP and HOTP\n */\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\n/**\n * Options for the OTP class\n */\nexport type OTPClassOptions = {\n /**\n * OTP strategy to use\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n */\n strategy?: OTPStrategy;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n};\n\n/**\n * Options for generating a token with the OTP class\n */\nexport type OTPGenerateOptions = {\n /**\n * Base32-encoded secret key\n */\n secret: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n};\n\n/**\n * Options for verifying a token with the OTP class\n */\nexport type OTPVerifyOptions = {\n /**\n * Base32-encoded secret key\n */\n secret: string;\n\n /**\n * OTP code to verify\n */\n token: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n\n /**\n * Time tolerance in seconds for TOTP verification (default: 0)\n * - Number: symmetric tolerance (same for past and future)\n * - Tuple [past, future]: asymmetric tolerance\n * Use [5, 0] for RFC-compliant past-only verification.\n */\n epochTolerance?: number | [number, number];\n\n /**\n * Counter tolerance for HOTP verification (default: 0)\n * - Number: symmetric look-ahead window\n * - Array: asymmetric window\n */\n counterTolerance?: number | number[];\n};\n\n/**\n * Options for generating URI with the OTP class\n */\nexport type OTPURIGenerateOptions = {\n /**\n * Issuer name (e.g., 'ACME Co')\n */\n issuer: string;\n\n /**\n * Label/Account name (e.g., 'john@example.com')\n */\n label: string;\n\n /**\n * Base32-encoded secret key\n */\n secret: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value (default: 0)\n * Used by HOTP strategy\n */\n counter?: number;\n};\n\n/**\n * OTP Class\n *\n * A wrapper class that dynamically handles TOTP and HOTP strategies.\n *\n * @example\n * ```ts\n * import { OTP } from 'otplib';\n *\n * // Create OTP instance with TOTP strategy (default)\n * const otp = new OTP({ strategy: 'totp' });\n *\n * // Generate and verify\n * const secret = otp.generateSecret();\n * const token = await otp.generate({ secret });\n * const result = await otp.verify({ secret, token });\n * ```\n *\n * @example With HOTP strategy\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'hotp' });\n * const token = await otp.generate({ secret: 'ABC123', counter: 0 });\n * ```\n *\n * @example Generating otpauth:// URI for authenticator apps\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'totp' });\n * const uri = otp.generateURI({\n * issuer: 'MyApp',\n * label: 'user@example.com',\n * secret: 'ABC123',\n * });\n * ```\n */\nexport class OTP {\n private readonly strategy: OTPStrategy;\n private readonly crypto: CryptoPlugin;\n private readonly base32: Base32Plugin;\n\n constructor(options: OTPClassOptions = {}) {\n const { strategy = \"totp\", crypto = defaultCrypto, base32 = defaultBase32 } = options;\n\n this.strategy = strategy;\n this.crypto = crypto;\n this.base32 = base32;\n }\n\n /**\n * Get the current strategy\n */\n getStrategy(): OTPStrategy {\n return this.strategy;\n }\n\n /**\n * Generate a random secret key\n *\n * @param length - Number of random bytes (default: 20)\n * @returns Base32-encoded secret key\n */\n generateSecret(length: number = 20): string {\n return generateSecretCore({ crypto: this.crypto, base32: this.base32, length });\n }\n\n /**\n * Generate an OTP token based on the configured strategy\n *\n * @param options - Generation options\n * @returns OTP code\n */\n async generate(options: OTPGenerateOptions): Promise<string> {\n return functionalGenerate({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n });\n }\n\n /**\n * Generate an OTP token based on the configured strategy synchronously\n *\n * @param options - Generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n generateSync(options: OTPGenerateOptions): string {\n return functionalGenerateSync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n */\n async verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n return functionalVerify({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy synchronously\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n verifySync(options: OTPVerifyOptions): VerifyResult {\n return functionalVerifySync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n });\n }\n\n /**\n * Generate an otpauth:// URI for QR code generation\n *\n * Supports both TOTP and HOTP strategies.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n */\n generateURI(options: OTPURIGenerateOptions): string {\n return functionalGenerateURI({\n ...options,\n strategy: this.strategy,\n });\n }\n}\n","/**\n * Default plugin instances\n *\n * Shared across functional and class APIs to ensure singleton behavior\n * and reduce memory overhead.\n */\nimport { ScureBase32Plugin } from \"@otplib/plugin-base32-scure\";\nimport { NobleCryptoPlugin } from \"@otplib/plugin-crypto-noble\";\n\nimport type {\n OTPGenerateOptions,\n OTPVerifyOptions,\n OTPGenerateOptionsWithDefaults,\n OTPVerifyOptionsWithDefaults,\n} from \"./types\";\n\n/**\n * Default crypto plugin instance (Noble Hashes)\n *\n * This plugin provides cross-platform cryptographic operations\n * using the @noble/hashes library.\n */\nexport const defaultCrypto = Object.freeze(new NobleCryptoPlugin());\n\n/**\n * Default Base32 plugin instance (@scure/base)\n *\n * This plugin provides Base32 encoding/decoding operations\n * using the @scure/base library.\n */\nexport const defaultBase32 = Object.freeze(new ScureBase32Plugin());\n\nexport function normalizeGenerateOptions(\n options: OTPGenerateOptions,\n): OTPGenerateOptionsWithDefaults {\n return {\n secret: options.secret,\n strategy: options.strategy ?? \"totp\",\n crypto: options.crypto ?? defaultCrypto,\n base32: options.base32 ?? defaultBase32,\n algorithm: options.algorithm ?? \"sha1\",\n digits: options.digits ?? 6,\n period: options.period ?? 30,\n epoch: options.epoch ?? Math.floor(Date.now() / 1000),\n t0: options.t0 ?? 0,\n counter: options.counter,\n };\n}\n\nexport function normalizeVerifyOptions(options: OTPVerifyOptions): OTPVerifyOptionsWithDefaults {\n return {\n ...normalizeGenerateOptions(options),\n token: options.token,\n epochTolerance: options.epochTolerance ?? 0,\n counterTolerance: options.counterTolerance ?? 0,\n };\n}\n","import { generateSecret as generateSecretCore, ConfigurationError } from \"@otplib/core\";\nimport {\n generate as generateHOTP,\n generateSync as generateHOTPSync,\n verify as verifyHOTP,\n verifySync as verifyHOTPSync,\n} from \"@otplib/hotp\";\nimport {\n generate as generateTOTP,\n generateSync as generateTOTPSync,\n verify as verifyTOTP,\n verifySync as verifyTOTPSync,\n} from \"@otplib/totp\";\nimport { generateTOTP as generateTOTPURI, generateHOTP as generateHOTURI } from \"@otplib/uri\";\n\nimport {\n defaultCrypto,\n defaultBase32,\n normalizeGenerateOptions,\n normalizeVerifyOptions,\n} from \"./defaults\";\n\nimport type { OTPGenerateOptions, OTPVerifyOptions, OTPStrategy, StrategyHandlers } from \"./types\";\nimport type { CryptoPlugin, Base32Plugin, Digits, HashAlgorithm } from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\nexport type { OTPStrategy };\n\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\nfunction executeByStrategy<T>(\n strategy: OTPStrategy,\n counter: number | undefined,\n handlers: StrategyHandlers<T>,\n): T {\n if (strategy === \"totp\") {\n return handlers.totp();\n }\n if (strategy === \"hotp\") {\n if (counter === undefined) {\n throw new ConfigurationError(\n \"Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }\",\n );\n }\n return handlers.hotp(counter);\n }\n throw new ConfigurationError(\n `Unknown OTP strategy: ${strategy}. Valid strategies are 'totp' or 'hotp'.`,\n );\n}\n\n/**\n * Generate a random secret key for use with OTP\n *\n * The secret is encoded in Base32 format for compatibility with\n * Google Authenticator and other authenticator apps.\n *\n * @param options - Secret generation options\n * @returns Base32-encoded secret key\n *\n * @example\n * ```ts\n * import { generateSecret } from 'otplib';\n *\n * const secret = generateSecret();\n * // Returns: 'JBSWY3DPEHPK3PXP'\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generateSecret, NodeCryptoPlugin } from 'otplib';\n *\n * const secret = generateSecret({\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport function generateSecret(options?: {\n /**\n * Number of random bytes to generate (default: 20)\n * 20 bytes = 160 bits, which provides a good security margin\n */\n length?: number;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n}): string {\n const { crypto = defaultCrypto, base32 = defaultBase32, length = 20 } = options || {};\n\n return generateSecretCore({ crypto, base32, length });\n}\n\n/**\n * Generate an otpauth:// URI for QR code generation\n *\n * This URI can be used to generate a QR code that can be scanned\n * by Google Authenticator and other authenticator apps.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n *\n * @example TOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: 'otpauth://totp/ACME%20Co:john%40example.com?secret=...'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * strategy: 'hotp',\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * counter: 5,\n * });\n * // Returns: 'otpauth://hotp/ACME%20Co:john%40example.com?secret=...&counter=5'\n * ```\n */\nexport function generateURI(options: {\n /**\n * OTP strategy to use (default: 'totp')\n */\n strategy?: OTPStrategy;\n issuer: string;\n label: string;\n secret: string;\n algorithm?: HashAlgorithm;\n digits?: Digits;\n period?: number;\n counter?: number;\n}): string {\n const {\n strategy = \"totp\",\n issuer,\n label,\n secret,\n algorithm = \"sha1\",\n digits = 6,\n period = 30,\n counter,\n } = options;\n\n return executeByStrategy(strategy, counter, {\n totp: () => generateTOTPURI({ issuer, label, secret, algorithm, digits, period }),\n hotp: (counter) => generateHOTURI({ issuer, label, secret, algorithm, digits, counter }),\n });\n}\n\n/**\n * Generate an OTP code\n *\n * Generates a one-time password based on the specified strategy.\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n *\n * @param options - OTP generation options\n * @returns OTP code\n *\n * @example TOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: '123456'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generate, NodeCryptoPlugin } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function generate(options: OTPGenerateOptions): Promise<string> {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n }),\n hotp: (counter) =>\n generateHOTP({\n ...commonOptions,\n counter,\n }),\n });\n}\n\n/**\n * Generate an OTP code synchronously\n *\n * This is the synchronous version of {@link generate}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { generateSync } from 'otplib';\n *\n * const token = generateSync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * ```\n */\nexport function generateSync(options: OTPGenerateOptions): string {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n }),\n hotp: (counter) =>\n generateHOTPSync({\n ...commonOptions,\n counter,\n }),\n });\n}\n\n/**\n * Verify an OTP code\n *\n * Verifies a provided OTP code against the expected value based on the strategy.\n * - 'totp': Time-based OTP (default, Google Authenticator compatible)\n * - 'hotp': HMAC-based OTP\n *\n * Uses constant-time comparison to prevent timing attacks.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n *\n * @example TOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * // Returns: { valid: true, delta: 0 }\n * ```\n *\n * @example HOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With epochTolerance for TOTP\n * ```ts\n * import { verify, NodeCryptoPlugin } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * epochTolerance: 30,\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n }),\n hotp: (counter) =>\n verifyHOTP({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n }),\n });\n}\n\n/**\n * Verify an OTP code synchronously\n *\n * This is the synchronous version of {@link verify}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { verifySync } from 'otplib';\n *\n * const result = verifySync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * ```\n */\nexport function verifySync(options: OTPVerifyOptions): VerifyResult {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n }),\n hotp: (counter) =>\n verifyHOTPSync({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n }),\n });\n}\n"],"mappings":"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","names":["generateSecretCore","ScureBase32Plugin","NobleCryptoPlugin","defaultCrypto","defaultBase32","normalizeGenerateOptions","options","normalizeVerifyOptions","generateSecretCore","ConfigurationError","generateHOTP","generateHOTPSync","verifyHOTP","verifyHOTPSync","generateTOTP","generateTOTPSync","verifyTOTP","verifyTOTPSync","generateTOTPURI","generateHOTURI","executeByStrategy","strategy","counter","handlers","ConfigurationError","generateURI","options","strategy","issuer","label","secret","algorithm","digits","period","counter","executeByStrategy","generateTOTPURI","generateHOTURI","generate","opts","normalizeGenerateOptions","crypto","base32","commonOptions","generateTOTP","generateHOTP","generateSync","generateTOTPSync","generateHOTPSync","verify","normalizeVerifyOptions","token","verifyTOTP","verifyHOTP","verifySync","verifyTOTPSync","verifyHOTPSync","OTP","options","strategy","crypto","defaultCrypto","base32","defaultBase32","length","generateSecretCore","generate","generateSync","verify","verifySync","generateURI"]}
1
+ {"version":3,"sources":["../src/class.ts","../src/defaults.ts","../src/functional.ts"],"sourcesContent":["/**\n * OTP Wrapper Class\n *\n * A unified class that dynamically handles TOTP and HOTP strategies.\n */\n\nimport { createGuardrails, generateSecret as generateSecretCore } from \"@otplib/core\";\n\nimport { defaultCrypto, defaultBase32 } from \"./defaults.js\";\nimport {\n generate as functionalGenerate,\n generateSync as functionalGenerateSync,\n verify as functionalVerify,\n verifySync as functionalVerifySync,\n generateURI as functionalGenerateURI,\n} from \"./functional.js\";\n\nimport type { OTPStrategy } from \"./functional.js\";\nimport type {\n CryptoPlugin,\n Digits,\n HashAlgorithm,\n Base32Plugin,\n OTPGuardrails,\n} from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\n/**\n * Combined verify result that works for both TOTP and HOTP\n */\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\n/**\n * Options for the OTP class\n */\nexport type OTPClassOptions = {\n /**\n * OTP strategy to use\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n */\n strategy?: OTPStrategy;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n};\n\n/**\n * Options for generating a token with the OTP class\n */\nexport type OTPGenerateOptions = {\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string | Uint8Array;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n};\n\n/**\n * Options for verifying a token with the OTP class\n */\nexport type OTPVerifyOptions = {\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string | Uint8Array;\n\n /**\n * OTP code to verify\n */\n token: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Current Unix epoch timestamp in seconds (default: now)\n * Used by TOTP strategy\n */\n epoch?: number;\n\n /**\n * Initial Unix time to start counting time steps (default: 0)\n * Used by TOTP strategy\n */\n t0?: number;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value\n * Used by HOTP strategy (required)\n */\n counter?: number;\n\n /**\n * Time tolerance in seconds for TOTP verification (default: 0)\n * - Number: symmetric tolerance (same for past and future)\n * - Tuple [past, future]: asymmetric tolerance\n * Use [5, 0] for RFC-compliant past-only verification.\n */\n epochTolerance?: number | [number, number];\n\n /**\n * Counter tolerance for HOTP verification (default: 0)\n * - Number: creates look-ahead only tolerance [0, n]\n * - Tuple [past, future]: explicit window control\n */\n counterTolerance?: number | [number, number];\n\n /**\n * Validation guardrails\n */\n guardrails?: OTPGuardrails;\n};\n\n/**\n * Options for generating URI with the OTP class\n */\nexport type OTPURIGenerateOptions = {\n /**\n * Issuer name (e.g., 'ACME Co')\n */\n issuer: string;\n\n /**\n * Label/Account name (e.g., 'john@example.com')\n */\n label: string;\n\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n */\n digits?: Digits;\n\n /**\n * Time step in seconds (default: 30)\n * Used by TOTP strategy\n */\n period?: number;\n\n /**\n * Counter value (default: 0)\n * Used by HOTP strategy\n */\n counter?: number;\n};\n\n/**\n * OTP Class\n *\n * A wrapper class that dynamically handles TOTP and HOTP strategies.\n *\n * @example\n * ```ts\n * import { OTP } from 'otplib';\n *\n * // Create OTP instance with TOTP strategy (default)\n * const otp = new OTP({ strategy: 'totp' });\n *\n * // Generate and verify\n * const secret = otp.generateSecret();\n * const token = await otp.generate({ secret });\n * const result = await otp.verify({ secret, token });\n * ```\n *\n * @example With HOTP strategy\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'hotp' });\n * const token = await otp.generate({ secret: 'ABC123', counter: 0 });\n * ```\n *\n * @example Generating otpauth:// URI for authenticator apps\n * ```ts\n * import { OTP } from 'otplib';\n *\n * const otp = new OTP({ strategy: 'totp' });\n * const uri = otp.generateURI({\n * issuer: 'MyApp',\n * label: 'user@example.com',\n * secret: 'ABC123',\n * });\n * ```\n */\nexport class OTP {\n private readonly strategy: OTPStrategy;\n private readonly crypto: CryptoPlugin;\n private readonly base32: Base32Plugin;\n private readonly guardrails: OTPGuardrails;\n\n constructor(options: OTPClassOptions = {}) {\n const {\n strategy = \"totp\",\n crypto = defaultCrypto,\n base32 = defaultBase32,\n guardrails,\n } = options;\n\n this.strategy = strategy;\n this.crypto = crypto;\n this.base32 = base32;\n this.guardrails = createGuardrails(guardrails);\n }\n\n /**\n * Get the current strategy\n */\n getStrategy(): OTPStrategy {\n return this.strategy;\n }\n\n /**\n * Generate a random secret key\n *\n * @param length - Number of random bytes (default: 20)\n * @returns Base32-encoded secret key\n */\n generateSecret(length: number = 20): string {\n return generateSecretCore({ crypto: this.crypto, base32: this.base32, length });\n }\n\n /**\n * Generate an OTP token based on the configured strategy\n *\n * @param options - Generation options\n * @returns OTP code\n */\n async generate(options: OTPGenerateOptions): Promise<string> {\n return functionalGenerate({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Generate an OTP token based on the configured strategy synchronously\n *\n * @param options - Generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n generateSync(options: OTPGenerateOptions): string {\n return functionalGenerateSync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n */\n async verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n return functionalVerify({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Verify an OTP token based on the configured strategy synchronously\n *\n * @param options - Verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n */\n verifySync(options: OTPVerifyOptions): VerifyResult {\n return functionalVerifySync({\n ...options,\n strategy: this.strategy,\n crypto: this.crypto,\n base32: this.base32,\n guardrails: options.guardrails ?? this.guardrails,\n });\n }\n\n /**\n * Generate an otpauth:// URI for QR code generation\n *\n * Supports both TOTP and HOTP strategies.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n */\n generateURI(options: OTPURIGenerateOptions): string {\n return functionalGenerateURI({\n ...options,\n strategy: this.strategy,\n });\n }\n}\n","/**\n * Default plugin instances\n *\n * Shared across functional and class APIs to ensure singleton behavior\n * and reduce memory overhead.\n */\nimport { createGuardrails } from \"@otplib/core\";\nimport { ScureBase32Plugin } from \"@otplib/plugin-base32-scure\";\nimport { NobleCryptoPlugin } from \"@otplib/plugin-crypto-noble\";\n\nimport type {\n OTPGenerateOptions,\n OTPVerifyOptions,\n OTPGenerateOptionsWithDefaults,\n OTPVerifyOptionsWithDefaults,\n} from \"./types.js\";\n\n/**\n * Default crypto plugin instance (Noble Hashes)\n *\n * This plugin provides cross-platform cryptographic operations\n * using the @noble/hashes library.\n */\nexport const defaultCrypto = Object.freeze(new NobleCryptoPlugin());\n\n/**\n * Default Base32 plugin instance (@scure/base)\n *\n * This plugin provides Base32 encoding/decoding operations\n * using the @scure/base library.\n */\nexport const defaultBase32 = Object.freeze(new ScureBase32Plugin());\n\nexport function normalizeGenerateOptions(\n options: OTPGenerateOptions,\n): OTPGenerateOptionsWithDefaults {\n return {\n secret: options.secret,\n strategy: options.strategy ?? \"totp\",\n crypto: options.crypto ?? defaultCrypto,\n base32: options.base32 ?? defaultBase32,\n algorithm: options.algorithm ?? \"sha1\",\n digits: options.digits ?? 6,\n period: options.period ?? 30,\n epoch: options.epoch ?? Math.floor(Date.now() / 1000),\n t0: options.t0 ?? 0,\n counter: options.counter,\n guardrails: options.guardrails ?? createGuardrails(),\n };\n}\n\nexport function normalizeVerifyOptions(options: OTPVerifyOptions): OTPVerifyOptionsWithDefaults {\n return {\n ...normalizeGenerateOptions(options),\n token: options.token,\n epochTolerance: options.epochTolerance ?? 0,\n counterTolerance: options.counterTolerance ?? 0,\n };\n}\n","import { generateSecret as generateSecretCore, ConfigurationError } from \"@otplib/core\";\nimport {\n generate as generateHOTP,\n generateSync as generateHOTPSync,\n verify as verifyHOTP,\n verifySync as verifyHOTPSync,\n} from \"@otplib/hotp\";\nimport {\n generate as generateTOTP,\n generateSync as generateTOTPSync,\n verify as verifyTOTP,\n verifySync as verifyTOTPSync,\n} from \"@otplib/totp\";\nimport { generateTOTP as generateTOTPURI, generateHOTP as generateHOTURI } from \"@otplib/uri\";\n\nimport {\n defaultCrypto,\n defaultBase32,\n normalizeGenerateOptions,\n normalizeVerifyOptions,\n} from \"./defaults.js\";\n\nimport type {\n OTPGenerateOptions,\n OTPVerifyOptions,\n OTPStrategy,\n StrategyHandlers,\n} from \"./types.js\";\nimport type { CryptoPlugin, Base32Plugin, Digits, HashAlgorithm } from \"@otplib/core\";\nimport type { VerifyResult as HOTPVerifyResult } from \"@otplib/hotp\";\nimport type { VerifyResult as TOTPVerifyResult } from \"@otplib/totp\";\n\nexport type { OTPStrategy };\n\nexport type VerifyResult = TOTPVerifyResult | HOTPVerifyResult;\n\nfunction executeByStrategy<T>(\n strategy: OTPStrategy,\n counter: number | undefined,\n handlers: StrategyHandlers<T>,\n): T {\n if (strategy === \"totp\") {\n return handlers.totp();\n }\n if (strategy === \"hotp\") {\n if (counter === undefined) {\n throw new ConfigurationError(\n \"Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }\",\n );\n }\n return handlers.hotp(counter);\n }\n throw new ConfigurationError(\n `Unknown OTP strategy: ${strategy}. Valid strategies are 'totp' or 'hotp'.`,\n );\n}\n\n/**\n * Generate a random secret key for use with OTP\n *\n * The secret is encoded in Base32 format for compatibility with\n * Google Authenticator and other authenticator apps.\n *\n * @param options - Secret generation options\n * @returns Base32-encoded secret key\n *\n * @example\n * ```ts\n * import { generateSecret } from 'otplib';\n *\n * const secret = generateSecret();\n * // Returns: 'JBSWY3DPEHPK3PXP'\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generateSecret, NodeCryptoPlugin } from 'otplib';\n *\n * const secret = generateSecret({\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport function generateSecret(options?: {\n /**\n * Number of random bytes to generate (default: 20)\n * 20 bytes = 160 bits, which provides a good security margin\n */\n length?: number;\n\n /**\n * Crypto plugin to use (default: NobleCryptoPlugin)\n */\n crypto?: CryptoPlugin;\n\n /**\n * Base32 plugin to use (default: ScureBase32Plugin)\n */\n base32?: Base32Plugin;\n}): string {\n const { crypto = defaultCrypto, base32 = defaultBase32, length = 20 } = options || {};\n\n return generateSecretCore({ crypto, base32, length });\n}\n\n/**\n * Generate an otpauth:// URI for QR code generation\n *\n * This URI can be used to generate a QR code that can be scanned\n * by Google Authenticator and other authenticator apps.\n *\n * @param options - URI generation options\n * @returns otpauth:// URI string\n *\n * @example TOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: 'otpauth://totp/ACME%20Co:john%40example.com?secret=...'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generateURI } from 'otplib';\n *\n * const uri = generateURI({\n * strategy: 'hotp',\n * issuer: 'ACME Co',\n * label: 'john@example.com',\n * secret: 'JBSWY3DPEHPK3PXP',\n * counter: 5,\n * });\n * // Returns: 'otpauth://hotp/ACME%20Co:john%40example.com?secret=...&counter=5'\n * ```\n */\nexport function generateURI(options: {\n /**\n * OTP strategy to use (default: 'totp')\n */\n strategy?: OTPStrategy;\n issuer: string;\n label: string;\n /**\n * Base32-encoded secret key\n *\n * **Note**: By default, strings are assumed to be Base32 encoded.\n * If you have a raw string/passphrase, you must convert it to Uint8Array first.\n */\n secret: string;\n algorithm?: HashAlgorithm;\n digits?: Digits;\n period?: number;\n counter?: number;\n}): string {\n const {\n strategy = \"totp\",\n issuer,\n label,\n secret,\n algorithm = \"sha1\",\n digits = 6,\n period = 30,\n counter,\n } = options;\n\n return executeByStrategy(strategy, counter, {\n totp: () => generateTOTPURI({ issuer, label, secret, algorithm, digits, period }),\n hotp: (counter) => generateHOTURI({ issuer, label, secret, algorithm, digits, counter }),\n });\n}\n\n/**\n * Generate an OTP code\n *\n * Generates a one-time password based on the specified strategy.\n * - 'totp': Time-based OTP (default)\n * - 'hotp': HMAC-based OTP\n *\n * @param options - OTP generation options\n * @returns OTP code\n *\n * @example TOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * // Returns: '123456'\n * ```\n *\n * @example HOTP\n * ```ts\n * import { generate } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With custom plugins\n * ```ts\n * import { generate, NodeCryptoPlugin } from 'otplib';\n *\n * const token = await generate({\n * secret: 'JBSWY3DPEHPK3PXP',\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function generate(options: OTPGenerateOptions): Promise<string> {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n generateHOTP({\n ...commonOptions,\n counter,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Generate an OTP code synchronously\n *\n * This is the synchronous version of {@link generate}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP generation options\n * @returns OTP code\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { generateSync } from 'otplib';\n *\n * const token = generateSync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * });\n * ```\n */\nexport function generateSync(options: OTPGenerateOptions): string {\n const opts = normalizeGenerateOptions(options);\n const { secret, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n generateTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n generateHOTPSync({\n ...commonOptions,\n counter,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Verify an OTP code\n *\n * Verifies a provided OTP code against the expected value based on the strategy.\n * - 'totp': Time-based OTP (default, Google Authenticator compatible)\n * - 'hotp': HMAC-based OTP\n *\n * Uses constant-time comparison to prevent timing attacks.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n *\n * @example TOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * // Returns: { valid: true, delta: 0 }\n * ```\n *\n * @example HOTP\n * ```ts\n * import { verify } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * strategy: 'hotp',\n * counter: 0,\n * });\n * ```\n *\n * @example With epochTolerance for TOTP\n * ```ts\n * import { verify, NodeCryptoPlugin } from 'otplib';\n *\n * const result = await verify({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * epochTolerance: 30,\n * crypto: new NodeCryptoPlugin(),\n * });\n * ```\n */\nexport async function verify(options: OTPVerifyOptions): Promise<VerifyResult> {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTP({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n verifyHOTP({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n guardrails: opts.guardrails,\n }),\n });\n}\n\n/**\n * Verify an OTP code synchronously\n *\n * This is the synchronous version of {@link verify}. It requires a crypto\n * plugin that supports synchronous HMAC operations.\n *\n * @param options - OTP verification options\n * @returns Verification result with validity and optional delta\n * @throws {HMACError} If the crypto plugin doesn't support sync operations\n *\n * @example\n * ```ts\n * import { verifySync } from 'otplib';\n *\n * const result = verifySync({\n * secret: 'JBSWY3DPEHPK3PXP',\n * token: '123456',\n * });\n * ```\n */\nexport function verifySync(options: OTPVerifyOptions): VerifyResult {\n const opts = normalizeVerifyOptions(options);\n const { secret, token, crypto, base32, algorithm, digits } = opts;\n const commonOptions = { secret, token, crypto, base32, algorithm, digits };\n\n return executeByStrategy(opts.strategy, opts.counter, {\n totp: () =>\n verifyTOTPSync({\n ...commonOptions,\n period: opts.period,\n epoch: opts.epoch,\n t0: opts.t0,\n epochTolerance: opts.epochTolerance,\n guardrails: opts.guardrails,\n }),\n hotp: (counter) =>\n verifyHOTPSync({\n ...commonOptions,\n counter,\n counterTolerance: opts.counterTolerance,\n guardrails: opts.guardrails,\n }),\n });\n}\n"],"mappings":"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","names":["createGuardrails","generateSecretCore","createGuardrails","ScureBase32Plugin","NobleCryptoPlugin","defaultCrypto","defaultBase32","normalizeGenerateOptions","options","normalizeVerifyOptions","generateSecretCore","ConfigurationError","generateHOTP","generateHOTPSync","verifyHOTP","verifyHOTPSync","generateTOTP","generateTOTPSync","verifyTOTP","verifyTOTPSync","generateTOTPURI","generateHOTURI","executeByStrategy","strategy","counter","handlers","ConfigurationError","generateURI","options","strategy","issuer","label","secret","algorithm","digits","period","counter","executeByStrategy","generateTOTPURI","generateHOTURI","generate","opts","normalizeGenerateOptions","crypto","base32","commonOptions","generateTOTP","generateHOTP","generateSync","generateTOTPSync","generateHOTPSync","verify","normalizeVerifyOptions","token","verifyTOTP","verifyHOTP","verifySync","verifyTOTPSync","verifyHOTPSync","OTP","options","strategy","crypto","defaultCrypto","base32","defaultBase32","guardrails","createGuardrails","length","generateSecretCore","generate","generateSync","verify","verifySync","generateURI"]}
@@ -1,2 +1,2 @@
1
- "use strict";var T=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var H=(t,e)=>{for(var r in e)T(t,r,{get:e[r],enumerable:!0})},R=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of V(e))!x.call(t,o)&&o!==r&&T(t,o,{get:()=>e[o],enumerable:!(n=b(e,o))||n.enumerable});return t};var v=t=>R(T({},"__esModule",{value:!0}),t);var k={};H(k,{generate:()=>C,generateSecret:()=>G,generateSync:()=>D,generateURI:()=>w,verify:()=>z,verifySync:()=>B});module.exports=v(k);var u=require("@otplib/core"),c=require("@otplib/hotp"),y=require("@otplib/totp"),O=require("@otplib/uri");var d=require("@otplib/plugin-base32-scure"),S=require("@otplib/plugin-crypto-noble"),m=Object.freeze(new S.NobleCryptoPlugin),h=Object.freeze(new d.ScureBase32Plugin);function l(t){return{secret:t.secret,strategy:t.strategy??"totp",crypto:t.crypto??m,base32:t.base32??h,algorithm:t.algorithm??"sha1",digits:t.digits??6,period:t.period??30,epoch:t.epoch??Math.floor(Date.now()/1e3),t0:t.t0??0,counter:t.counter}}function P(t){return{...l(t),token:t.token,epochTolerance:t.epochTolerance??0,counterTolerance:t.counterTolerance??0}}function f(t,e,r){if(t==="totp")return r.totp();if(t==="hotp"){if(e===void 0)throw new u.ConfigurationError("Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }");return r.hotp(e)}throw new u.ConfigurationError(`Unknown OTP strategy: ${t}. Valid strategies are 'totp' or 'hotp'.`)}function G(t){let{crypto:e=m,base32:r=h,length:n=20}=t||{};return(0,u.generateSecret)({crypto:e,base32:r,length:n})}function w(t){let{strategy:e="totp",issuer:r,label:n,secret:o,algorithm:a="sha1",digits:p=6,period:i=30,counter:s}=t;return f(e,s,{totp:()=>(0,O.generateTOTP)({issuer:r,label:n,secret:o,algorithm:a,digits:p,period:i}),hotp:g=>(0,O.generateHOTP)({issuer:r,label:n,secret:o,algorithm:a,digits:p,counter:g})})}async function C(t){let e=l(t),{secret:r,crypto:n,base32:o,algorithm:a,digits:p}=e,i={secret:r,crypto:n,base32:o,algorithm:a,digits:p};return f(e.strategy,e.counter,{totp:()=>(0,y.generate)({...i,period:e.period,epoch:e.epoch,t0:e.t0}),hotp:s=>(0,c.generate)({...i,counter:s})})}function D(t){let e=l(t),{secret:r,crypto:n,base32:o,algorithm:a,digits:p}=e,i={secret:r,crypto:n,base32:o,algorithm:a,digits:p};return f(e.strategy,e.counter,{totp:()=>(0,y.generateSync)({...i,period:e.period,epoch:e.epoch,t0:e.t0}),hotp:s=>(0,c.generateSync)({...i,counter:s})})}async function z(t){let e=P(t),{secret:r,token:n,crypto:o,base32:a,algorithm:p,digits:i}=e,s={secret:r,token:n,crypto:o,base32:a,algorithm:p,digits:i};return f(e.strategy,e.counter,{totp:()=>(0,y.verify)({...s,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance}),hotp:g=>(0,c.verify)({...s,counter:g,counterTolerance:e.counterTolerance})})}function B(t){let e=P(t),{secret:r,token:n,crypto:o,base32:a,algorithm:p,digits:i}=e,s={secret:r,token:n,crypto:o,base32:a,algorithm:p,digits:i};return f(e.strategy,e.counter,{totp:()=>(0,y.verifySync)({...s,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance}),hotp:g=>(0,c.verifySync)({...s,counter:g,counterTolerance:e.counterTolerance})})}0&&(module.exports={generate,generateSecret,generateSync,generateURI,verify,verifySync});
1
+ "use strict";var T=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var H=Object.prototype.hasOwnProperty;var R=(t,e)=>{for(var r in e)T(t,r,{get:e[r],enumerable:!0})},v=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of x(e))!H.call(t,o)&&o!==r&&T(t,o,{get:()=>e[o],enumerable:!(n=V(e,o))||n.enumerable});return t};var G=t=>v(T({},"__esModule",{value:!0}),t);var j={};R(j,{generate:()=>D,generateSecret:()=>w,generateSync:()=>z,generateURI:()=>C,verify:()=>B,verifySync:()=>k});module.exports=G(j);var l=require("@otplib/core"),c=require("@otplib/hotp"),g=require("@otplib/totp"),O=require("@otplib/uri");var P=require("@otplib/core"),S=require("@otplib/plugin-base32-scure"),b=require("@otplib/plugin-crypto-noble"),m=Object.freeze(new b.NobleCryptoPlugin),d=Object.freeze(new S.ScureBase32Plugin);function f(t){return{secret:t.secret,strategy:t.strategy??"totp",crypto:t.crypto??m,base32:t.base32??d,algorithm:t.algorithm??"sha1",digits:t.digits??6,period:t.period??30,epoch:t.epoch??Math.floor(Date.now()/1e3),t0:t.t0??0,counter:t.counter,guardrails:t.guardrails??(0,P.createGuardrails)()}}function h(t){return{...f(t),token:t.token,epochTolerance:t.epochTolerance??0,counterTolerance:t.counterTolerance??0}}function y(t,e,r){if(t==="totp")return r.totp();if(t==="hotp"){if(e===void 0)throw new l.ConfigurationError("Counter is required for HOTP strategy. Example: { strategy: 'hotp', counter: 0 }");return r.hotp(e)}throw new l.ConfigurationError(`Unknown OTP strategy: ${t}. Valid strategies are 'totp' or 'hotp'.`)}function w(t){let{crypto:e=m,base32:r=d,length:n=20}=t||{};return(0,l.generateSecret)({crypto:e,base32:r,length:n})}function C(t){let{strategy:e="totp",issuer:r,label:n,secret:o,algorithm:s="sha1",digits:p=6,period:i=30,counter:a}=t;return y(e,a,{totp:()=>(0,O.generateTOTP)({issuer:r,label:n,secret:o,algorithm:s,digits:p,period:i}),hotp:u=>(0,O.generateHOTP)({issuer:r,label:n,secret:o,algorithm:s,digits:p,counter:u})})}async function D(t){let e=f(t),{secret:r,crypto:n,base32:o,algorithm:s,digits:p}=e,i={secret:r,crypto:n,base32:o,algorithm:s,digits:p};return y(e.strategy,e.counter,{totp:()=>(0,g.generate)({...i,period:e.period,epoch:e.epoch,t0:e.t0,guardrails:e.guardrails}),hotp:a=>(0,c.generate)({...i,counter:a,guardrails:e.guardrails})})}function z(t){let e=f(t),{secret:r,crypto:n,base32:o,algorithm:s,digits:p}=e,i={secret:r,crypto:n,base32:o,algorithm:s,digits:p};return y(e.strategy,e.counter,{totp:()=>(0,g.generateSync)({...i,period:e.period,epoch:e.epoch,t0:e.t0,guardrails:e.guardrails}),hotp:a=>(0,c.generateSync)({...i,counter:a,guardrails:e.guardrails})})}async function B(t){let e=h(t),{secret:r,token:n,crypto:o,base32:s,algorithm:p,digits:i}=e,a={secret:r,token:n,crypto:o,base32:s,algorithm:p,digits:i};return y(e.strategy,e.counter,{totp:()=>(0,g.verify)({...a,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance,guardrails:e.guardrails}),hotp:u=>(0,c.verify)({...a,counter:u,counterTolerance:e.counterTolerance,guardrails:e.guardrails})})}function k(t){let e=h(t),{secret:r,token:n,crypto:o,base32:s,algorithm:p,digits:i}=e,a={secret:r,token:n,crypto:o,base32:s,algorithm:p,digits:i};return y(e.strategy,e.counter,{totp:()=>(0,g.verifySync)({...a,period:e.period,epoch:e.epoch,t0:e.t0,epochTolerance:e.epochTolerance,guardrails:e.guardrails}),hotp:u=>(0,c.verifySync)({...a,counter:u,counterTolerance:e.counterTolerance,guardrails:e.guardrails})})}0&&(module.exports={generate,generateSecret,generateSync,generateURI,verify,verifySync});
2
2
  //# sourceMappingURL=functional.cjs.map