User Rating 0.0 โ˜…โ˜…โ˜…โ˜…โ˜…
Total Usage 0 times
Category Security
QR Code (otpauth:// URI)
Is this tool helpful?

Your feedback helps us improve.

โ˜… โ˜… โ˜… โ˜… โ˜…

About

Misconfigured OTP parameters cause authentication lockouts. A wrong hash algorithm, an off-by-one counter, or a clock drift beyond the tolerance window means denied access and frustrated users. This tool computes HMAC-based One-Time Passwords per RFC 4226 (HOTP) and RFC 6238 (TOTP) entirely in your browser using the Web Crypto API. It accepts a Base32-encoded secret K, selects the hash function H โˆˆ {SHA-1, SHA-256, SHA-512}, and applies dynamic truncation to the resulting HMAC digest. For TOTP, the counter C is derived as (T โˆ’ T0)X where X defaults to 30 s. No server calls are made. Your secret key never leaves this page.

Pro tip: Most authenticator apps only support SHA-1 with 6 digits and 30-second periods. If you configure SHA-256 or SHA-512, verify your authenticator actually supports it. Many silently fall back to SHA-1, producing mismatched codes. This tool lets you validate exact parameter combinations before deploying to production. Note: TOTP accuracy depends on your device clock. A drift exceeding 30 s from UTC will produce codes that fail server-side validation unless the server implements a look-ahead/look-behind window.

hotp totp otp hmac two-factor-authentication rfc-4226 rfc-6238 2fa mfa google-authenticator

Formulas

HOTP computation per RFC 4226:

HOTP(K, C) = Truncate(HMACโˆ’H(K, C)) mod 10d

Where Truncate applies dynamic truncation. Let HS = HMACโˆ’H(K, C). The offset o is the low-order 4 bits of the last byte of HS:

o = HS[len(HS) โˆ’ 1] โˆง 0x0F

Extract 4 bytes from HS at offset o, mask the most significant bit:

P = ((HS[o] โˆง 0x7F) << 24) | (HS[o+1] << 16) | (HS[o+2] << 8) | HS[o+3]

Final code: P mod 10d, zero-padded to d digits.

For TOTP (RFC 6238), the counter C is time-derived:

C = floor(T โˆ’ T0X)

Where K = shared secret key (Base32-decoded), C = counter value (8-byte big-endian), H = hash algorithm (SHA-1, SHA-256, or SHA-512), d = number of digits (6 - 8), T = current Unix time in seconds, T0 = epoch start (usually 0), X = time step in seconds (default 30).

Reference Data

ParameterRFC DefaultGoogle AuthenticatorMicrosoft AuthenticatorAuthyNotes
AlgorithmSHA-1SHA-1 onlySHA-1 / SHA-256SHA-1 onlyRFC 6238 supports SHA-256/512
Digits6666 / 7 / 8Range: 6 - 8
Period (X)30 s30 s30 s30 sSome services use 60 s
Secret encodingBase32 (RFC 4648)Base32Base32Base32Padding optional
Min secret length128 bits80 bits128 bits128 bitsRFC recommends 160 bits for SHA-1
Recommended secret (SHA-1)160 bits (20 bytes) - - - 32 Base32 chars
Recommended secret (SHA-256)256 bits (32 bytes) - - - 52 Base32 chars
Recommended secret (SHA-512)512 bits (64 bytes) - - - 103 Base32 chars
Counter size (HOTP)8 bytesN/AN/AN/ABig-endian unsigned 64-bit
Look-ahead window1 - 3 steps111Server-side tolerance
Resync threshold (HOTP)10 steps - - - RFC 4226 ยง7.4
URI schemeotpauth://YesYesYesDe facto standard
T0 (epoch)Unix epoch (0)000Seconds since 1970-01-01
HMAC output (SHA-1)20 bytes - - - Truncated to 4 bytes
HMAC output (SHA-256)32 bytes - - - Truncated to 4 bytes
HMAC output (SHA-512)64 bytes - - - Truncated to 4 bytes
RFC 4226 test vector secret12345678901234567890 (ASCII) - - - Base32: GEZDGNBVGY3TQOJQ
RFC 6238 test vector (SHA-1)Counter 1 โ†’ 287082 - - - Time = 59 s

Frequently Asked Questions

Three common causes: (1) Your device clock is out of sync with UTC. TOTP divides Unix time by the period, so even a 30-second drift produces a different counter value. Sync your clock via NTP. (2) The hash algorithm mismatches. Google Authenticator only supports SHA-1. If you configured SHA-256 in your server, Google Authenticator silently uses SHA-1 and produces a different code. (3) The secret was incorrectly encoded. Ensure you use the raw Base32 string without spaces or hyphens. Padding characters (=) are optional per RFC 4648 but some implementations choke on them.
RFC 4226 Section 4 requires the shared secret to be at least 128 bits (16 bytes, 26 Base32 characters). However, the RFC recommends matching the HMAC output length: 160 bits (20 bytes) for SHA-1, 256 bits (32 bytes) for SHA-256, and 512 bits (64 bytes) for SHA-512. Keys shorter than the hash output are zero-padded internally by HMAC, which does not reduce security but wastes entropy potential. Keys longer than the hash block size (64 bytes for SHA-1/256, 128 bytes for SHA-512) are first hashed, which is functionally equivalent but adds unnecessary computation.
A server typically accepts codes from counter values Cโˆ’1, C, and C+1 (a window of 1 step in each direction). This compensates for clock drift and network latency. With a 30-second period, that gives roughly a 90-second acceptance window. Increasing the window to 2 steps (150 seconds) reduces lockouts but increases the attack surface. Each additional step doubles the probability of a brute-force match from 1/10^d to n/10^d where n is the total window size.
Yes. HOTP increments the counter on each generation. If a user generates codes without submitting them, their counter advances beyond the server's look-ahead window (typically 10 steps per RFC 4226 Section 7.4). Beyond that threshold, the server cannot find a matching counter value and the token is effectively locked. Recovery requires server-side counter reset. TOTP avoids this because its counter is derived from time, not usage.
Yes, for this specific use case. SHA-1 collision attacks (SHAttered, 2017) target the compression function to find two inputs with the same hash. HMAC-SHA-1 uses the hash as a keyed PRF, which is resistant to collision attacks. The HMAC security proof requires only second-preimage resistance, which SHA-1 still provides. RFC 6238 nonetheless recommends SHA-256 or SHA-512 for new deployments as a defense-in-depth measure. The practical risk of HMAC-SHA-1 compromise for OTP is negligible at current computational capabilities.
The time step X directly affects usability and security. A shorter period (e.g., 15 seconds) increases security by narrowing the valid window but frustrates users who cannot type the code fast enough. A longer period (e.g., 60 seconds) is more forgiving but each code is valid longer, increasing exposure to shoulder-surfing. Most authenticator apps hardcode 30 seconds. If your server issues otpauth:// URIs with period=60, some apps ignore it and default to 30, causing mismatched codes. Always verify client-side support before deploying non-standard periods.