Recovery codes… Or just one recovery code?

Published: (February 12, 2026 at 03:08 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Overview

Authentication discussions usually focus on:

  • Passkeys
  • TOTP
  • Hardware tokens
  • Passwordless

Recovery mechanisms are rarely analysed with the same rigour, yet recovery often defines the actual security boundary. If login is strong but recovery is weak, the system is weak.

Backup Code Lists (5–10 one‑time codes)

Properties

  • Multiple static tokens
  • One‑time use
  • Regenerable list

Typical Issues

  • Users do not store them properly
  • Screenshots are taken
  • Codes are forgotten
  • No entropy analysis is done
  • Security is assumed because there are “many codes”

Security Considerations

  • Entropy is what actually matters.
  • Recovery becomes delegated authentication.
  • Security depends on:
    • Email account protection
    • SIM security
    • External attack surface

This shifts the threat model rather than strengthening it.

Seed Phrases (12–24 words)

Characteristics

  • Recovery of private key
  • High entropy
  • Offline storage expectation

Usability

  • Cryptographically rigorous, but has high usability cost.

Assumptions

  • Attacker has recovery endpoint access
  • No data leak
  • No internal compromise
  • Attack is purely online

Security Depends On

  • Entropy
  • Generation quality
  • Rate limiting

Not on the number of codes issued.

Tested Configuration

  • Length: 15 characters
  • Alphabet size: 31 symbols (ambiguous characters such as 0/O and 1/I/L excluded)
  • Generation: CSPRNG (crypto.randomBytes) with rejection sampling (no modulo bias)
  • TTL: No fixed TTL
  • Rate limiting: Strict; a few attempts within several minutes
  • Rotation: Automatic after successful use

Entropy Calculation

  • Alphabet size: 31
  • Total search space: (31^{15})
  • Entropy: ≈ 78 bits

Aggressive Attack Scenario

  • Attempts: ~1.5 million per year
  • Probability of success: Negligible (effectively infeasible for an online attack)

Issuing 10 codes does not multiply the entropy of a single attempt; an attacker still guesses one valid code at a time.

Security Depends On

  • Per‑account rate limiting
  • Per‑identifier throttling
  • Entropy per code
  • Correct random generation
  • Safe storage model

Not on how many printable tokens are handed to the user.

Randomness

// Use a cryptographically secure PRNG
const crypto = require('crypto');
function generateCode(length, alphabet) {
  const bytes = crypto.randomBytes(length * 2); // oversample
  let result = '';
  let i = 0;
  while (result.length < length && i < bytes.length) {
    const idx = bytes[i] % alphabet.length;
    // Rejection sampling to avoid modulo bias
    if (bytes[i] < 256 - (256 % alphabet.length)) {
      result += alphabet[idx];
    }
    i++;
  }
  return result;
}
  • Avoid Math.random().
  • Use rejection sampling when mapping bytes to the alphabet to eliminate modulo bias.

Rate Limiting

Critical Points

  • Limit per recovery identifier (not only per IP).
  • Combine per‑account and per‑IP limits.
  • Add exponential backoff if necessary.

Rotation

After a successful recovery:

  1. Invalidate the previous code.
  2. Generate a new one.
  3. Avoid long‑term static tokens.

Conclusion

Recovery is not a UX afterthought; it is an authentication primitive. If recovery entropy and attempt control are properly engineered, a single recovery code can be strictly sufficient under an online threat model.

The real question is not “How many codes?” but “What is the entropy and how is the attack surface controlled?”

0 views
Back to Blog

Related posts

Read more »

Cast Your Bread Upon the Waters

!Cover image for Cast Your Bread Upon the Watershttps://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-t...