RFC 4226 HOTP implementation for otplib
npm install @otplib/hotpRFC 4226 HOTP implementation for otplib.
``bash`
npm install @otplib/hotp
pnpm install @otplib/hotp
yarn add @otplib/hotp
`typescript
import { generate, verify } from "@otplib/hotp";
import { crypto } from "@otplib/plugin-crypto-node";
import { base32 } from "@otplib/plugin-base32-scure";
// Generate an HOTP token for counter 0
const token = await generate({
secret: "GEZDGNBVGY3TQOJQGEZDGNBVGY",
counter: 0,
crypto,
base32,
});
// Verify an HOTP token
const result = await verify({
secret: "GEZDGNBVGY3TQOJQGEZDGNBVGY",
token: "123456",
counter: 0,
crypto,
base32,
counterTolerance: 0,
});
// result.valid: boolean
// result.delta: number | null
`
Generate an HOTP code for a specific counter:
`typescript
import { generate } from '@otplib/hotp';
import { crypto } from '@otplib/plugin-crypto-node';
import { base32 } from '@otplib/plugin-base32-scure';
const token = await generate({
secret: new Uint8Array([...]), // Required: secret as bytes
counter: 0, // Required: counter value
crypto, // Required: crypto plugin
base32, // Optional: base32 plugin (for decoding)
algorithm: 'sha1', // Optional: 'sha1' | 'sha256' | 'sha512'
digits: 6, // Optional: 6 | 7 | 8
});
`
Verify an HOTP code:
`typescript
import { verify } from '@otplib/hotp';
import { crypto } from '@otplib/plugin-crypto-node';
import { base32 } from '@otplib/plugin-base32-scure';
const result = await verify({
secret: new Uint8Array([...]), // Required: secret as bytes
token: '123456', // Required: token to verify
counter: 0, // Required: expected counter
crypto, // Required: crypto plugin
base32, // Optional: base32 plugin (for decoding)
algorithm: 'sha1', // Optional: hash algorithm
digits: 6, // Optional: expected digits
counterTolerance: 5, // Optional: look-ahead tolerance
});
// Returns: { valid: boolean, delta: number | null }
``
Full documentation available at otplib.yeojz.dev:
- Getting Started Guide
- API Reference
MIT © 2026 Gerald Yeo