ASVS 5.0 V6.5.4 requires lookup secrets and out of band authentication codes to carry at least 20 bits of entropy. Six random digits or four random alphanumeric characters is typically enough. It is a Level 2 requirement.
Why it matters
Too short a code can be guessed even with rate limits. Three random digits is about 10 bits, so one thousand guesses cover the whole space. Twenty bits means about a million possibilities, which combined with attempt limits and short expiry makes brute force impractical.
How to implement it
Work out entropy as the length times log2 of the alphabet size. Six digits is 6 x 3.32, about 19.9 bits, which is why six digits is the usual floor. Take seven if you want margin.
import math, secrets
def entropy_bits(alphabet_size: int, length: int) -> float:
return length * math.log2(alphabet_size)
assert entropy_bits(10, 7) >= 20
code = "".join(secrets.choice("0123456789") for _ in range(7))
Pair length with limits: attempt caps (V6.6.3) and a short life (V6.5.5).
How to test it
- Read the generator and compute the entropy.
- Request 100 codes and confirm the length and alphabet are what the code claims.
- Check that codes are random and not derived from a counter.
Common mistakes
- Four digit codes "because users complain".
- Removing ambiguous characters until the alphabet is tiny.
- Counting entropy from a predictable generator.
Quick check
Does a six digit code from a weak random function meet 20 bits?
No. The entropy only counts if the generator is cryptographically secure (V6.5.3).