Skip to content
Preptima
mediumConceptCodingEntryMidSenior

You need a random number from 1 to 6 and you wrote rand() % 6. What is wrong with that, and when does it stop being merely wrong and become a vulnerability?

rand() % 6 yields 0 to 5, and because RAND_MAX + 1 is not a multiple of 6 it shows modulo bias towards 0 and 1. Rejection sampling fixes the bias. It becomes a vulnerability when an attacker benefits from predicting the value, as with tokens, keys or nonces, because rand() is predictable. Those need a CSPRNG.

4 min readUpdated 2026-10-09

Answer

Short answer

There are three separate problems. rand() % 6 returns 0 to 5, not 1 to 6, and it has modulo bias: rand() produces RAND_MAX + 1 equally likely values, that count is not a multiple of 6, so some results come up slightly more often. It becomes a vulnerability when someone gains from predicting the number, such as a session token, a reset code or a key, because rand() is a deterministic generator whose output can be reconstructed. Rejection sampling fixes the bias, and only a CSPRNG fixes the predictability.

Was this answer helpful?

Likely follow-ups

  • Your rejection loop throws away draws. What is the worst-case expected number of calls to rand() for any n, and why is it under two?
  • Someone seeds rand() with time(NULL) for password reset tokens. Walk through how an attacker who knows roughly when the token was issued exploits that.
  • Is a 0.02 percent bias towards some faces acceptable in a board game app? Where would the same bias stop being acceptable?
  • How would you shuffle a deck uniformly, and which two mistakes make a shuffle biased even with a perfect generator?

Related questions