@epic-web/totp

中文文档
4.0.1发布于 2025/02/26MITTypeScriptES Module构建来源已验证近 30 天下载 15.8万

Create and verify cryptographically secure Time-based One-time Passwords (TOTP) using the HMAC-based One-time Password (HOTP) algorithm.

原始使用文档
文档目录15 节
  1. The problem
  2. This solution
  3. Terms
  4. Usage
  5. 2FA code
  6. Verification of email/phone number ownership
  7. Customizable Character Set for Increased Security
  8. Why Charset Matters
  9. Potential for Main Form of Authentication
  10. Usage with Custom Character Set
  11. API
  12. generateTOTP
  13. verifyTOTP
  14. getTOTPAuthUri
  15. License

🕰 @epic-web/totp

Support Two Factor Authentication (2FA) in your application with ease.

Create and verify cryptographically secure Time-based One-time Passwords (TOTP) using the HMAC-based One-time Password (HOTP) algorithm.

npm install @epic-web/totp

Build Status MIT License Code of Conduct

The problem

You want to support 2FA clients or generate safe one-time passwords to otherwise verify your users.

This solution

This was copy/paste/modified/tested from notp (MIT)

The primary motivation was to support a more secure algorithm than SHA-1 (though Google Authenticator only supports SHA-1, longer-lived OTPs should use a more secure algorithm). The maintainer has not actively responded to issues or pull requests in years.

Some improvements were made to modernize the code (which was last published in 2014) and improve the API. But the core algorithm is unchanged.

Terms

  • OTP: One Time Password
  • HOTP: HMAC-based One Time Password
  • TOTP: Time-based One Time Password

The TOTP is what we typically use for verification codes. This can be used for 2FA (two-factor authentication), but also used for email verification, password reset, etc.

Usage

This package exports three methods:

  • generateTOTP - This generates the OTP and returns the config used to generate it.
  • verifyTOTP - This verifies the OTP against the config used to generate it.
  • getTOTPAuthUri - This generates a URI that can be used to add the OTP to an authenticator app.

2FA code

Here's the typical process for generating a 2FA auth URI (which the user can add to their authenticator app).

import { generateTOTP, getTOTPAuthUri, verifyTOTP } from '@epic-web/totp'

// Here's how to use the default config. All the options are returned:
const { secret, period, digits, algorithm } = await generateTOTP()
const otpUri = getTOTPAuthUri({
    period,
    digits,
    algorithm,
    secret,
    accountName: user.email,
    issuer: 'Your App Name',
})
// check docs below for customization options.

// optional, but recommended: import * as QRCode from 'qrcode'
// const qrCode = await QRCode.toDataURL(otpUri)

// now you can display the QR code and the URI to the user and let them enter
// their code from their authenticator app.
// however you get the code from the user, do it:
const code = await getCodeFromUser()

// now verify the code:
const isValid = await verifyTOTP({ otp: code, secret, period, digits, algorithm })

// if it's valid, save the secret, period, digits, and algorithm to the database
// along with who it belongs to and use this info to verify the user when they
// login or whatever.

Verification of email/phone number ownership

Here's the typical process for a one-time verification of a user's email/phone number/etc.:

import { generateTOTP, verifyTOTP } from '@epic-web/totp'

const { otp, secret, digits, period, algorithm } = await generateTOTP({
    algorithm: 'SHA-256', // more secure algorithm should be used with longer-lived OTPs
    period: 10 * 60, // 10 minutes
})

await sendOtpToUser({
    email: user.email,
    otp,
    secret,
    digits,
    period,
    algorithm,
})
await saveVerificationToDatabase({
    secret,
    digits,
    period,
    algorithm,
    target: user.email,
})

// when the user gives you the code (however you do that):
const code = await getCodeFromUser()

// now verify the code:
const userCodeConfig = await getVerificationFromDatabase({
    target: user.email,
})
const isValid = await verifyTOTP({ otp: code, ...userCodeConfig })

if (isValid) {
    await deleteVerificationFromDatabase({ target: user.email })
    // allow the user to proceed
} else {
    // show an error
}

Customizable Character Set for Increased Security

Why Charset Matters

When it comes to security, every bit of entropy counts. Entropy measures the unpredictability and in turn the security of your OTPs. The traditional TOTP setup often employs a 6-digit numerical code, providing a million (10^6) combinations. This is the default behaviour for this implementation. While that is robust, there's room for improvement.

By introducing a customizable character set feature, you can exponentially increase the entropy of the OTPs, making them much more secure against brute-force attacks. For example, if you extend your character set to include 26 uppercase letters and 10 digits, a 6-character OTP would have 36^6 = 2.1 billion combinations. When paired with rate-limiting mechanisms, this configuration becomes practically impervious to brute-force attacks.

Potential for Main Form of Authentication

With this added complexity, TOTPs can, in theory, be used as the primary form of authentication, rather than just a second factor. This is particularly useful for applications requiring heightened security.

Usage with Custom Character Set

In addition to the existing options, you can specify a charSet in both generateTOTP and verifyTOTP.

Here's how you can generate an OTP with a custom character set:

import { generateTOTP, verifyTOTP } from '@epic-web/totp'

const { otp, secret, period, digits, algorithm, charSet } = await generateTOTP({
    charSet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', // custom character set
})

// Remember to save the charSet to your database as well.

// To verify
const isValid = await verifyTOTP({
    otp,
    secret,
    period,
    digits,
    algorithm,
    charSet,
})

Just as an aside, you probably want to exclude the letter O and the number 0 to make it easier for users to enter the code.

API

This library is built with jsdoc, so hopefully your editor supports that and will show you all this stuff, but just in case, here's that:

generateTOTP

/**
 * Creates a time-based one-time password (TOTP). This handles creating a random
 * secret (base32 encoded), and generating a TOTP for the current time. As a
 * convenience, it also returns the config options used to generate the TOTP.
 *
 * @param {Object} [options] Configuration options for the TOTP.
 * @param {number} [options.period=30] The number of seconds for the OTP to be
 * valid. Defaults to 30.
 * @param {number} [options.digits=6] The length of the OTP. Defaults to 6.
 * @param {string} [options.algorithm='SHA-1'] The algorithm to use. Defaults to
 * SHA-1.
 * @param {string} [options.secret] The secret to use for the TOTP. It should be
 * base32 encoded (you can use https://npm.im/thirty-two). Defaults to a random
 * secret: base32.encode(crypto.randomBytes(10)).toString().
 * @param {string} [options.charSet='0123456789'] - The character set to use, defaults to the numbers 0-9.
 * @returns {Promise<{otp: string, secret: string, period: number, digits: number, algorithm: string, charSet: string}>}
 * The OTP, secret, and config options used to generate the OTP.
 */

verifyTOTP

/**
 * Verifies a time-based one-time password (TOTP). This handles decoding the
 * secret (base32 encoded), and verifying the OTP for the current time.
 *
 * @param {Object} options The otp, secret, and configuration options for the
 * TOTP.
 * @param {string} options.otp The OTP to verify.
 * @param {string} options.secret The secret to use for the TOTP.
 * @param {number} [options.period] The number of seconds for the OTP to be valid.
 * @param {number} [options.digits] The length of the OTP.
 * @param {string} [options.algorithm] The algorithm to use.
 * @param {string} [options.charSet] The character set to use, defaults to the numbers 0-9.
 * @param {number} [options.window] The number of OTPs to check before and after
 * the current OTP. Defaults to 1.
 *
 * @returns {Promise<{delta: number}|null>} an object with "delta" which is the delta
 * between the current OTP and the OTP that was verified, or null if the OTP is
 * invalid.
 */

getTOTPAuthUri

/**
 * Generates a otpauth:// URI which you can use to generate a QR code or users
 * can manually enter into their password manager.
 *
 * @param {Object} options Configuration options for the TOTP Auth URI.
 * @param {number} options.period The number of seconds for the OTP to be valid.
 * @param {number} options.digits The length of the OTP.
 * @param {string} options.algorithm The algorithm to use.
 * @param {string} options.secret The secret to use for the TOTP Auth URI.
 * @param {string} options.accountName A way to uniquely identify this Auth URI
 * (in case they have multiple of these).
 * @param {string} options.issuer The issuer to use for the TOTP Auth URI.
 *
 * @returns {string} The OTP Auth URI
 */

License

MIT

版本与发布记录

@epic-web/totp 共发布 20 个版本,首次发布于 2023/08/03;过去 12 个月发布了 0 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
4.0.1latest2025/02/261.7 年前
4.0.02025/02/251.7 年前
3.1.02025/02/181.7 年前
3.0.22025/02/161.7 年前
3.0.12025/02/161.7 年前
3.0.02025/02/151.7 年前

关于 @epic-web/totp 的常见问题

@epic-web/totp 是什么?

Create and verify cryptographically secure Time-based One-time Passwords (TOTP) using the HMAC-based One-time Password (HOTP) algorithm.

如何安装 @epic-web/totp?

在项目目录运行 npm install @epic-web/totp,或使用 pnpm add / yarn add / bun add。

@epic-web/totp 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@epic-web/totp 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@epic-web/totp 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@epic-web/totp 可以商用吗?

@epic-web/totp 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@epic-web/totp 的下载量有多少?

根据 npm 官方下载统计,@epic-web/totp 在 2026/10/14 – 2026/11/12 这 30 天内被下载 158,359 次,日均约 5,279 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@epic-web/totp 还在维护吗?

最新版本 4.0.1 发布于 2025/02/26(1.7 年前);至今共发布 20 个版本,其中过去 12 个月发布了 0 个;首次发布于 2023/08/03。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。