Follow-on question to Is UUID.randomUUID() suitable for use as a one-time password?, where the accepted answer hinted that you didn't need 122 bits (e.g. UUIDs) to have enough randomness for security.
-
what do you mean by a one-time password being secure? As long as it expires in a much shorter time then one could brute-force guess it, then it should be secure. – Mitch Wheat Sep 14 '13 at 11:51
-
For sake of pedagogy, let's forget about the one-time part. How many bytes should a random base-64 string be to be practically unguessable, given proper rate-limiting (say, 100 guesses/minute)? – yayitswei Sep 14 '13 at 12:02
-
You mean assuming the NSA haven't built-in a backdoor? – Mitch Wheat Sep 14 '13 at 12:03
-
I can't confirm or deny that. – yayitswei Sep 14 '13 at 12:04
-
1Is this password supposed to be remembered or typed by a human? If not, you should probably just go with 128 bits or such to be on the safe side. – ntoskrnl Sep 14 '13 at 12:56
-
Nope. 128 bits is what I ended up using. – yayitswei Sep 14 '13 at 12:58
-
122 bits read from a secure PRNG is plenty. In many situations you get away with much lower values. But I'd prefer to use a CSPRNG directly instead of using a GUID/UUID generator. – CodesInChaos Sep 14 '13 at 15:22
1 Answers
That depends on how complex it has to be to be practically un-guessable.
First set out a time period for when guessing is so impractical that it's practically unusable, for example a year (365 days).
Divide the time period by the time that it takes to make a single request with the link in the mail. (I.e. not the time for a single request-response, but how often you could do requests using parallel processing.) For example 0.1 second, which gives 315360000 requests in the time period one year.
Multiply by the number of active codes, and multiply that by two, to compensate for the average time for finding a valid code. For example 100 codes gives 63072000000 combinations.
For that example you would need 36 random bits (236 = 68719476736) to get a practically un-guessable code.

- 687,336
- 108
- 737
- 1,005
-
So like 5 bytes? That's less than I expected. Adding on rate-limiting it could be even shorter. – yayitswei Sep 14 '13 at 12:18