Skip to content
apikey.tools
GENGenerators

One-Time Password & Temporary PIN Generator

Generate OTP codes and PINs, with the attempt-limiting requirements stated plainly.

GENRuns in this tabInput not transmitted

Input

6chars
min
chars

Output

computing

A six-digit code has 20 bits of entropy. There are one million possibilities. That is not a lot — and it does not need to be, because a one-time password is not protected by entropy. It is protected by attempt limiting and a short expiry. Get those two wrong and no code length saves you.

The security model

Three controls do the work, and all three are required:

  1. Attempt limits. Five attempts per code, then invalidate the code entirely — not just reject the attempt. Without this, a million guesses against a six-digit code is a few minutes of work.
  2. Short expiry. Five to ten minutes. Long enough for an email to arrive and be read, short enough that a captured code is worthless by the time it is used.
  3. Single use. The code is invalidated on first successful verification, regardless of what happens next in the flow.

Miss any one and the others do not compensate. A code with a 5-minute expiry but unlimited attempts is broken. A code with 5 attempts but a 24-hour expiry is a weak password.

Choosing a length and alphabet

FormatSearch spaceSuitable for
4 digits10,000Device PINs with hardware attempt limiting only
6 digits1,000,000The standard for SMS and email verification
8 digits100,000,000Higher-value confirmations
8 Base32~1.1 × 10¹²Recovery codes that will be typed once

Digits are correct for anything typed on a phone: numeric keypads are faster and the failure rate is lower. Base32 without ambiguous glyphs is better for recovery codes, which are typed from paper and only once.

Rate limit the account, not just the code

Invalidating a code after five attempts stops an attacker guessing one code. It does not stop them requesting a hundred codes and making five attempts against each — which multiplies their chances by a hundred. Limit code *issuance* per account as well as attempts per code.

Comparison to TOTP

This generates a random code that your server stores and compares. That is different from TOTP (RFC 6238), where an authenticator app derives a code from a shared secret and the current time, with no delivery step at all. TOTP is the stronger design — nothing transits a network — but it requires enrolment. Use this for delivery-based verification, and TOTP where you can ask users to enrol an app.

Frequently asked questions

Is six digits long enough?

Yes, with five attempts and a ten-minute expiry. The probability of guessing within five attempts is 1 in 200,000, and the code is dead before a second window opens. Without those controls, six digits is trivially brute-forced.

Should I allow the user to request a new code immediately?

Rate-limit resends and invalidate the previous code when a new one is issued. Otherwise an attacker collects several simultaneously valid codes, multiplying their attempts.

Why avoid letters that look like digits?

Because someone reading 0 and typing O produces a failed attempt, and failed attempts consume the attempt budget. The Base32 option here uses Crockford's alphabet, which excludes I, L, O and U for exactly this reason.

More generators tools

Draw key material from the browser's CSPRNG