A lightweight, zero-dependency Node.js library for generating and verifying Time-Based One-Time Passwords (TOTP) and HMAC-Based One-Time Passwords (HOTP), compliant with RFC 6238 and RFC 4226.
- 🔐 Generate TOTP and HOTP codes
- ✅ Verify TOTP codes with time window support
- 🔑 Generate cryptographically secure secrets
- 🔧 Support for multiple hash algorithms (SHA-1, SHA-256, SHA-512)
- 📦 Zero dependencies (uses native Node.js crypto)
- 🎯 RFC 4648 Base32 encoding/decoding implementation
- ⚡ Lightweight and fast
- 🎨 Flexible options API
npm install @hongtak/totpimport { generateSecret, totp } from '@hongtak/totp'
// Generate a secret key
const secret = generateSecret()
console.log('Secret:', secret)
// Output: Secret: JBSWY3DPEHPK3PXP...
// Generate a TOTP code
const code = totp.generate(secret)
console.log('Code:', code)
// Output: Code: 123456
// Verify a TOTP code
const isValid = totp.verify(secret, code)
console.log('Valid:', isValid)
// Output: Valid: true
// Generate with custom options
const code8Digit = totp.generate(secret, {
digits: 8,
step: 60,
algorithm: 'sha256'
})import { generateSecret, hotp } from '@hongtak/totp'
const secret = generateSecret()
const counter = 0
// Generate an HOTP code
const code = hotp.generate(secret, counter)
console.log('Code:', code)
// Output: Code: 123456
// Verify an HOTP code
const isValid = hotp.verify(secret, counter, code)
console.log('Valid:', isValid)
// Output: Valid: true
// Generate with custom options
const code8Digit = hotp.generate(secret, counter, {
digits: 8,
algorithm: 'sha512'
})import { base32 } from '@hongtak/totp'
// Encode
const encoded = base32.encode(Buffer.from('Hello World'))
console.log(encoded)
// Output: JBSWY3DPEBLW64TMMQ
// Decode
const decoded = base32.decode('JBSWY3DPEBLW64TMMQ')
console.log(decoded.toString())
// Output: Hello WorldGenerates a cryptographically secure random secret.
Parameters:
length(number, optional): Length of the random bytes to generate. Default is 32.
Returns: Base32-encoded secret string.
Example:
const secret = generateSecret()
// Returns: 'JBSWY3DPEHPK3PXP...'Generates a TOTP code based on the current time.
Parameters:
secret(string): Base32-encoded secret keyopts(object, optional): Configuration optionsdigits(number): Number of digits in the code. Default is6.epoch(number): Timestamp in milliseconds. Default isDate.now().algorithm(string): Hash algorithm ('sha1','sha256','sha512'). Default is'sha1'.step(number): Time step in seconds. Default is30.
Returns: String containing the TOTP code.
Example:
const code = totp.generate(secret, {
digits: 8,
step: 60,
algorithm: 'sha256'
})Verifies a TOTP code against the secret, allowing for time drift.
Parameters:
secret(string): Base32-encoded secret keytoken(string): TOTP code to verifyopts(object, optional): Configuration optionsdigits(number): Number of digits in the code. Default is6.epoch(number): Timestamp in milliseconds. Default isDate.now().algorithm(string): Hash algorithm. Default is'sha1'.step(number): Time step in seconds. Default is30.window(number): Number of time steps to check before and after current time. Default is0.
Returns: Boolean indicating whether the code is valid.
Example:
const isValid = totp.verify(secret, '12345678', {
digits: 8,
window: 1
})Generates an HOTP code based on a counter value.
Parameters:
secret(string): Base32-encoded secret keycounter(number): Counter valueopts(object, optional): Configuration optionsdigits(number): Number of digits in the code. Default is6.algorithm(string): Hash algorithm ('sha1','sha256','sha512'). Default is'sha1'.
Returns: String containing the HOTP code.
Example:
const code = hotp.generate(secret, 42, {
digits: 8,
algorithm: 'sha512'
})Verifies an HOTP code against the secret and counter.
Parameters:
secret(string): Base32-encoded secret keycounter(number): Counter valuetoken(string): HOTP code to verifyopts(object, optional): Configuration optionsdigits(number): Number of digits in the code. Default is6.algorithm(string): Hash algorithm. Default is'sha1'.
Returns: Boolean indicating whether the code is valid.
Example:
const isValid = hotp.verify(secret, 42, '12345678', {
digits: 8
})Alias for generateSecret(). Available on the hotp module for convenience.
Encodes binary data to Base32 string.
Parameters:
input(Buffer): Binary data to encodepadding(boolean, optional): Whether to include padding. Default isfalse.
Returns: Base32-encoded string.
Example:
const encoded = base32.encode(Buffer.from('Hello'))
// Returns: 'JBSWY3DP'Decodes a Base32 string to binary data.
Parameters:
input(string): Base32-encoded string
Returns: Buffer containing decoded binary data.
Example:
const decoded = base32.decode('JBSWY3DP')
// Returns: Buffer containing 'Hello'TOTP generates a time-based one-time password using:
- A shared secret key (Base32-encoded)
- Current Unix timestamp divided by a time step (default 30 seconds)
- HMAC algorithm (SHA-1, SHA-256, or SHA-512) to generate a hash
- Dynamic truncation to produce a numeric code
The verification function accounts for clock drift by checking codes within a time window.
HOTP generates a counter-based one-time password using:
- A shared secret key (Base32-encoded)
- A counter value that increments with each use
- HMAC algorithm to generate a hash
- Dynamic truncation to produce a numeric code
This library includes a custom RFC 4648-compliant Base32 implementation:
- Uses the standard RFC 4648 alphabet:
ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 - Supports optional padding with
=characters - Handles case-insensitive decoding
MIT License - see LICENSE file for details.
Choi Hong Tak hongtak@gmail.com