@epic-web/top
轻松支持应用程序中的双因子认证(2FA) .创建和验证加密安全、基于时间的一次性密码 (TOTP)使用基于HMAC的一次性密码(HOTP)算法.
npm install @epic-web/totp
问题
您想要支持 2FA 客户端或生成安全的一次性密码到其它处 验证您的用户.
这个解决方案
这是从 编号 (麻省理工学院)
主要动机是支持一个比 SHA-1
(虽然Google认证员只支持) SHA-1使用寿命较长的检察官办公室
比较安全的算法). 维护者没有积极回应问题或
数年内调取请求.
守则的现代化作了一些改进(最近一次公布) 2014年),并改进API. 但核心算法不变.
术语
- 检察官办公室: 一个时间密码
- 现场直播: 基于 HMAC 的一次性密码
- TOTP 调试: 基于时间的一次性密码
这个 TOTP 调试 我们通常用于核查代码。 这个可以使用 2FA(双要素认证),但也用于电子邮件验证, 密码重置等.
使用量
此套件输出出三种方法:
generateTOTP- 这会产生检察官办公室,并返回用于 生成它.verifyTOTP- 这验证了检察官办公室对用来生成它的配置.getTOTPAuthUri- 生成URI,用于将检察官办公室添加到 认证软件.
2FA 代码
以下是生成 2FA auth URI 的典型过程(用户可以添加) 他们的认证程序.
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.
核实电子邮件/电话号码的所有权
以下是一次性验证用户电子邮件/电话的典型过程 编号/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
}
增强安全的自定义字符集
为什么字符集事项
当涉及到安全时,每一点的 en都算数. 环测量 还有你的检察官办公室的安全 传统TOTP 设置经常使用6位数字代码,提供一百万(10^6) 组合。 此执行的默认行为 。 虽然如此 强壮,还有改进的余地.
通过引入自定义字符集特性,可以指数化 增加检察官办公室的肽,使其更加安全 野蛮人的攻击 例如,如果将字符集扩展为包含 26 大写字母和10个数字,一个6个字符的检察官办公室将拥有36^6=21亿 组合。 当与利率限制机制配对时, 此配置 变得几乎不受野蛮武力攻击.
主要认证形式的可能性
随着这种复杂性的增加,从理论上讲,TOTP可以作为主要形式: 认证,而不仅仅是第二个因素。 这特别有用 要求加强安全的申请.
自定义字符集的使用
除了现有的选项外,您还可以在两个选项中指定一个字符集
generateTOTP 财务报告和审定财务报表 verifyTOTP。 。 。 .
以下是您如何生成自定义字符集的 OTP :
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,
})
顺便说一句,你可能要排除字母O和数字0到 方便用户输入代码.
API 密码
这个库是用 jsdoc所以希望你的编辑支持
给你看这些东西,但以防万一,这里:
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
*/
许可证
麻省理工学院